feat(app): 添加扫描日志页面
All checks were successful
continuous-integration/drone/push Build is passing

添加了一个新的页面logs.html,用于显示今天的扫描日志。用户可以在该页面上查看扫描的条码和相关信息。
This commit is contained in:
Ching 2025-02-09 18:06:13 +08:00
parent a7865638f4
commit fe4be1b06e
3 changed files with 202 additions and 1 deletions

24
app.py
View File

@ -4,7 +4,7 @@ import os
import re
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask, jsonify, request
from flask import Flask, jsonify, request, render_template
from pygrocy import EntityType, Grocy
import atexit
import base64
@ -16,6 +16,7 @@ import requests
from barcode import BarcodeSpider, ShowApiSpider
from recipe import get_recipe_from_xiachufang
import models
logger = loguru.logger
# config = configparser.ConfigParser()
@ -540,6 +541,27 @@ def add_to_stream():
return jsonify({"message": str(e)}), 500
@app.route('/scanlogs/today', methods=['GET'])
def get_today_scanlogs():
try:
# 获取今天的所有日志并序列化
logs = models.ScanLog.get_today_logs()
serialized_logs = [log.serialize() for log in logs]
return jsonify({
'logs': serialized_logs,
'count': len(serialized_logs)
}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/logs')
def show_logs():
return render_template('logs.html')
# 初始化 APScheduler 并添加定时任务
scheduler = BackgroundScheduler()
scheduler.add_job(func=consume_stream, trigger="interval", seconds=10)

63
models.py Normal file
View File

@ -0,0 +1,63 @@
from peewee import *
from datetime import datetime, time
import json
# Create database instance
db = SqliteDatabase('scanner.db')
class BaseModel(Model):
class Meta:
database = db
class BarcodeDB(BaseModel):
barcode = CharField(unique=True)
product_info = TextField()
class Meta:
table_name = 'barcode_db'
class ScanLog(BaseModel):
barcode = CharField()
scan_at = DateTimeField(default=datetime.now)
class Meta:
table_name = 'scan_logs'
@classmethod
def get_today_logs(cls):
# Get today's start and end timestamps
today = datetime.now().date()
today_start = datetime.combine(today, time.min) # Start of day (00:00:00)
today_end = datetime.combine(today, time.max) # End of day (23:59:59.999999)
# Query logs for today
return cls.objects.filter(
scan_at__gte=today_start,
scan_at__lte=today_end
).order_by('-scan_at')
def serialize(self):
# Try to get product info from BarcodeDB
name = None
try:
product = BarcodeDB.get(BarcodeDB.barcode == self.barcode)
product_info = json.loads(product.product_info)
name = product_info.get('name')
except BarcodeDB.DoesNotExist:
pass
return {
'barcode': self.barcode,
'name': name,
'scan_at': self.scan_at
}
# Create tables
def create_tables():
with db:
db.create_tables([BarcodeDB, ScanLog])
if __name__ == '__main__':
create_tables()

116
templates/logs.html Normal file
View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>Today's Scan Logs</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
table {
width: 80%;
margin: 20px auto;
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
.empty-name {
background-color: #ffe6e6;
}
.retry-button {
padding: 5px 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.retry-button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<h1 style="text-align: center;">Today's Scan Logs</h1>
<div id="logs-container">
<table>
<thead>
<tr>
<th>Barcode</th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tbody id="logs-body">
</tbody>
</table>
</div>
<script>
// 加载日志数据
function loadLogs() {
$.ajax({
url: '/scanlogs/today',
method: 'GET',
success: function(logs) {
const tbody = $('#logs-body');
tbody.empty();
logs.forEach(function(log) {
const row = $('<tr>');
if (!log.name) {
row.addClass('empty-name');
}
row.append($('<td>').text(log.barcode));
row.append($('<td>').text(log.name || 'Empty'));
const actionCell = $('<td>');
if (!log.name) {
const retryButton = $('<button>')
.addClass('retry-button')
.text('Retry')
.click(() => retryBarcode(log.barcode));
actionCell.append(retryButton);
}
row.append(actionCell);
tbody.append(row);
});
},
error: function(xhr, status, error) {
alert('Failed to load logs: ' + error);
}
});
}
// 重试处理条码
function retryBarcode(barcode) {
$.ajax({
url: '/barcode',
method: 'POST',
data: JSON.stringify({ barcode: barcode }),
contentType: 'application/json',
success: function(response) {
alert('Barcode has been added to queue');
loadLogs(); // 重新加载数据
},
error: function(xhr, status, error) {
alert('Failed to process barcode: ' + error);
}
});
}
// 页面加载时获取数据
$(document).ready(function() {
loadLogs();
// 每30秒自动刷新一次
setInterval(loadLogs, 30000);
});
</script>
</body>
</html>