Pending Barcodes (Dashboard Box - Optimized Edition)

Collects barcodes, adds a 'Pending' button to sidebar, and extracts sample counts from navbar (Fixes panel disappearing, closes on click-outside)

目前為 2025-11-11 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

作者
Hamad AlShegifi
評價
0 0 0
版本
4.7
建立日期
2025-10-02
更新日期
2025-11-11
尺寸
31.2 KB
授權條款
MIT
腳本執行於

import json
import socket
import threading
import time
from flask import Flask, request, jsonify
from flask_cors import CORS
import os

# --- Configuration ---
BARCODES_FILE = 'barcodes.json'
SERVER_PORT = 5678 # Port for the web server (for Tampermonkey)
BROADCAST_PORT = 5679 # Port for network discovery and sync
BROADCAST_INTERVAL = 20 # Seconds between sync broadcasts

# --- Flask Web Server Setup ---
app = Flask(__name__)
CORS(app) # Allow requests from the Tampermonkey script

# --- Barcode Data Management ---
data_lock = threading.Lock()

def load_barcodes():
"""Safely loads barcodes from the JSON file."""
with data_lock:
if not os.path.exists(BARCODES_FILE):
return []
try:
with open(BARCODES_FILE, 'r') as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
return []

def save_barcodes(barcodes):
"""Safely saves barcodes to the JSON file."""
with data_lock:
# Sort by count to maintain some order
barcodes.sort(key=lambda x: x.get('count', 0))
with open(BARCODES_FILE, 'w') as f:
json.dump(barcodes, f, indent=4)

def merge_barcodes(local_list, received_list):
"""Merges two lists of barcodes, avoiding duplicates based on the 'barcode' value."""
merged_dict = {item['barcode']: item for item in local_list}
changed = False
for item in received_list:
if item['barcode'] not in merged_dict:
merged_dict[item['barcode']] = item
changed = True
else:
if item.get('found', False) and not merged_dict[item['barcode']].get('found', False):
merged_dict[item['barcode']]['found'] = True
changed = True

if not changed:
return local_list # Return original list if no changes

final_list = list(merged_dict.values())
for i, item in enumerate(final_list):
item['count'] = i + 1
return final_list


# --- API Endpoints for Tampermonkey ---

@app.route('/get_barcodes', methods=['GET'])
def get_barcodes():
"""Endpoint for the script to fetch the current list of barcodes."""
return jsonify(load_barcodes())

# *** NEW, SAFER ENDPOINT FOR ADDING BARCODES ***
@app.route('/add_barcode', methods=['POST'])
def add_barcode():
"""Endpoint for the script to send a single new barcode."""
new_entry = request.json
if not new_entry or 'barcode' not in new_entry:
return jsonify({"status": "error", "message": "Invalid data format."}), 400

barcodes = load_barcodes()

# Check for duplicates
if any(b['barcode'] == new_entry['barcode'] for b in barcodes):
return jsonify({"status": "success", "message": "Barcode already exists."}), 200

# Add the new entry and re-assign counts
barcodes.append(new_entry)
for i, item in enumerate(barcodes):
item['count'] = i + 1

save_barcodes(barcodes)
print(f"[{time.ctime()}] Added new barcode: {new_entry['barcode']}")
return jsonify({"status": "success", "message": "Barcode added."}), 201

@app.route('/update_barcodes', methods=['POST'])
def update_barcodes():
"""Endpoint for the script to send a full list of barcodes (e.g., after deleting)."""
new_barcodes = request.json
if isinstance(new_barcodes, list):
save_barcodes(new_barcodes)
return jsonify({"status": "success", "message": "Barcode list updated."}), 200
return jsonify({"status": "error", "message": "Invalid data format."}), 400


# --- Network Syncing Logic (UDP Broadcast) ---

def broadcast_sync():
"""Periodically sends the entire local barcode list to the network."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
while True:
time.sleep(BROADCAST_INTERVAL)
barcodes = load_barcodes()
if barcodes:
message = json.dumps(barcodes).encode('utf-8')
try:
sock.sendto(message, ('', BROADCAST_PORT))
# print(f"[{time.ctime()}] Sent sync broadcast with {len(barcodes)} items.")
except Exception as e:
print(f"Error sending broadcast: {e}")

def listen_for_sync():
"""Listens for barcode lists from other computers and merges them."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', BROADCAST_PORT))
print(f"Listening for sync data on UDP port {BROADCAST_PORT}")
my_ip = socket.gethostbyname(socket.gethostname())

while True:
try:
data, addr = sock.recvfrom(65507)
if addr[0] != my_ip:
received_barcodes = json.loads(data.decode('utf-8'))
local_barcodes = load_barcodes()
merged_list = merge_barcodes(local_barcodes, received_barcodes)

if merged_list is not local_barcodes:
save_barcodes(merged_list)
print(f"[{time.ctime()}] Received and merged {len(received_barcodes)} barcodes from {addr[0]}. New total: {len(merged_list)}.")
except Exception as e:
print(f"Error receiving sync data: {e}")


if __name__ == '__main__':
print("--- Barcode Sync Server ---")
if not os.path.exists(BARCODES_FILE):
save_barcodes([])
print(f"Created empty barcodes file at: {os.path.abspath(BARCODES_FILE)}")

listener_thread = threading.Thread(target=listen_for_sync, daemon=True)
listener_thread.start()
broadcaster_thread = threading.Thread(target=broadcast_sync, daemon=True)
broadcaster_thread.start()

print(f"Starting web server for Tampermonkey on http://localhost:{SERVER_PORT}")
app.run(host='0.0.0.0', port=SERVER_PORT)