feat: Initial commit for contraband ranking system
This commit is contained in:
128
app.py
Normal file
128
app.py
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
违禁品查获排行榜 - Web展示应用
|
||||
支持日榜、月榜、总榜展示,带动态筛选和可视化效果
|
||||
"""
|
||||
|
||||
from flask import Flask, render_template, jsonify
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, date
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# 数据文件路径 (支持从环境变量覆盖)
|
||||
DATA_FILE = os.environ.get('CONTRABAND_DATA_FILE',
|
||||
os.path.join(os.path.dirname(__file__), 'security_data_v2.json'))
|
||||
|
||||
|
||||
def load_and_process_data():
|
||||
"""
|
||||
加载并处理违禁品数据
|
||||
返回格式: {维度: {榜单列表}}
|
||||
维度: 'month', 'all'
|
||||
- month: 本月统计(有记录人员)
|
||||
- all: 总榜(所有在职人员,包括0记录)
|
||||
"""
|
||||
# 检查数据文件
|
||||
if not os.path.exists(DATA_FILE):
|
||||
app.logger.warning(f"数据文件不存在: {DATA_FILE}")
|
||||
return {'month': [], 'all': []}
|
||||
|
||||
try:
|
||||
with open(DATA_FILE, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
except (json.JSONDecodeError, UnicodeDecodeError) as e:
|
||||
app.logger.error(f"数据文件解析失败: {e}")
|
||||
return {'month': [], 'all': []}
|
||||
|
||||
members = data.get("members", {})
|
||||
logs = data.get("logs", [])
|
||||
|
||||
# 获取业务日期(处理跨夜班的情况)
|
||||
today_date = date.today()
|
||||
today_str = today_date.strftime("%Y-%m-%d")
|
||||
current_month = today_date.strftime("%Y-%m")
|
||||
|
||||
# 初始化三个维度的容器: {维度: {姓名: [明细列表]}}
|
||||
categories = {
|
||||
"month": {},
|
||||
"all": {}
|
||||
}
|
||||
|
||||
# 总榜初始化:所有在职人员(包括0记录)
|
||||
for name, info in members.items():
|
||||
if info.get('status') == 'active':
|
||||
categories["all"][name] = []
|
||||
|
||||
# 遍历日志进行分类
|
||||
for log in logs:
|
||||
# 跳过已删除的记录
|
||||
if log.get('is_deleted'):
|
||||
continue
|
||||
|
||||
name = log.get('name')
|
||||
biz_date = log.get('biz_date', '')
|
||||
biz_month = log.get('biz_month', '')
|
||||
|
||||
# 构建明细
|
||||
detail = {
|
||||
"time": log.get('actual_time', ''),
|
||||
"content": log.get('content', '')
|
||||
}
|
||||
|
||||
# 归档至"总榜"(只统计在职人员)
|
||||
if name in categories["all"]:
|
||||
categories["all"][name].append(detail)
|
||||
|
||||
# 归档至"月榜"
|
||||
if biz_month == current_month:
|
||||
categories["month"].setdefault(name, []).append(detail)
|
||||
|
||||
# 格式化前端所需的榜单数据
|
||||
final_data = {}
|
||||
for cat, user_map in categories.items():
|
||||
sorted_rank = []
|
||||
for name, details in user_map.items():
|
||||
member_info = members.get(name, {})
|
||||
sorted_rank.append({
|
||||
"name": name,
|
||||
"score": len(details),
|
||||
"shift": member_info.get("shift", "未知"),
|
||||
"status": member_info.get("status", "unknown"),
|
||||
"details": details
|
||||
})
|
||||
|
||||
# 按分数降序排序
|
||||
sorted_rank.sort(key=lambda x: x['score'], reverse=True)
|
||||
final_data[cat] = sorted_rank
|
||||
|
||||
return final_data
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""主页 - 加载所有榜单数据"""
|
||||
all_data = load_and_process_data()
|
||||
return render_template('index.html',
|
||||
data_json=json.dumps(all_data, ensure_ascii=False))
|
||||
|
||||
|
||||
@app.route('/api/rankings')
|
||||
def api_rankings():
|
||||
"""API接口 - 返回JSON格式的榜单数据"""
|
||||
all_data = load_and_process_data()
|
||||
return jsonify(all_data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 开发环境配置
|
||||
debug_mode = os.environ.get('FLASK_DEBUG', 'False').lower() in ('true', '1', 't')
|
||||
host = '127.0.0.1'
|
||||
port = 9517
|
||||
|
||||
print(f"🚀 违禁品排行榜启动中...")
|
||||
print(f"📁 数据文件: {DATA_FILE}")
|
||||
print(f"🌐 访问地址: http://{host}:{port}")
|
||||
|
||||
app.run(host=host, port=port, debug=debug_mode)
|
||||
Reference in New Issue
Block a user