Compare commits

...

12 Commits

Author SHA1 Message Date
ui-beam-9
29ac1b288e 删除所有注释 2025-04-22 20:08:45 +08:00
ui-beam-9
0fa7c3a559 删除授权用户验证 2025-04-22 20:06:23 +08:00
ui-beam-9
113c65a5ce 允许任意工号登录系统 2025-04-22 19:55:10 +08:00
ui-beam-9
455fa6c179 授权用户+1 2025-04-22 18:53:21 +08:00
ui-beam-9
e266ed763d 禁用不安全请求的警告 2025-04-22 12:32:05 +08:00
ui-beam-9
21e4a46357 发布新版本v20250422120008 2025-04-22 12:20:44 +08:00
ui-beam-9
5faaeb3891 回退到v20250414155609 2025-04-22 09:22:13 +08:00
ui-beam-9
fa68a3dc3f 回退到v20250414155609 2025-04-22 09:11:03 +08:00
ui-beam-9
c43bf4222c 修复误删文件 2025-04-22 09:05:30 +08:00
ui-beam-9
a8ad96556a 暂存更改 2025-04-22 09:04:52 +08:00
ui-beam-9
ec37c4af31 修复前端量级无法显示数据,增加清风审核和大神 CMS 的 Cookie 输入修改为可选 2025-04-22 08:14:38 +08:00
ui-beam-9
d5b93c12e2 修复前端量级无法显示数据,增加清风审核和大神 CMS 的 Cookie 输入修改为可选 2025-04-22 08:13:41 +08:00
12 changed files with 612 additions and 1020 deletions

View File

@ -1,17 +0,0 @@
# 网易大神实时审核数据监控
## 项目结构
- releases/: 发布版本
- latest/: 最新稳定版本
- v[版本号]/: 历史版本
- dev/: 开发版本
- latest/: 最新开发版本
- v[版本号]-dev/: 历史开发版本
- config/: 配置文件目录
## 版本管理
- main分支稳定发布版本
- dev分支开发版本
## 自动运行
使用 `download_auto_run.py` 脚本拉取并启动最新版本

View File

@ -1 +1 @@
v20250414155609
v20250422193845

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,449 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Python 2.7 Auto Download Script
For NetEase Da Shen Review Data Monitoring System
"""
import os
import sys
import time
import shutil
import urllib2
import getpass
import base64
import subprocess
import traceback
import codecs
from datetime import datetime
# 先尝试设置控制台代码页为UTF-8仅Windows环境
try:
if sys.platform.startswith('win'):
subprocess.call('chcp 936', shell=True)
except:
pass
# 基本配置
#COS_URL = "http://cos.ui-beam.com/work_scripts/monitor/dev/latest/"
COS_URL = "http://cos.ui-beam.com/work_scripts/monitor/releases/latest/"
TEMP_DIR = os.path.join(os.path.expanduser("~"), "Desktop", "monitor_temp")
LOG_FILE = os.path.join(TEMP_DIR, "download_log.txt")
# 要下载的文件列表 - 格式: (URL相对路径, 本地保存路径, 是否必需)
FILES_TO_DOWNLOAD = [
("start_monitor.cmd", "start_monitor.cmd", True),
("dashboard.py", "dashboard.py", True),
("breeze_monitor.py", "breeze_monitor.py", True),
("breeze_monitor_CHAT.py", "breeze_monitor_CHAT.py", True),
("cms_monitor.py", "cms_monitor.py", True),
("cms_coefficients.json", "cms_coefficients.json", True),
("breeze_coefficients.json", "breeze_coefficients.json", True),
("templates/dashboard.html", "templates/dashboard.html", True),
("templates/login.html", "templates/login.html", True),
("static/ds-favicon.ico", "static/ds-favicon.ico", True),
("install_dependencies.bat", "install_dependencies.bat", True),
("inspect_monitor.py", "inspect_monitor.py", True)
]
# 记录日志函数
def log_message(message):
"""记录日志消息"""
try:
# 确保日志目录存在
log_dir = os.path.dirname(LOG_FILE)
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 使用codecs打开文件指定编码为gbk
with codecs.open(LOG_FILE, "a", "gbk") as f:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_line = "[%s] %s\n" % (timestamp, message)
f.write(log_line)
# 使用safe_print输出到控制台
safe_print(message)
except Exception as e:
safe_print("[ERROR] Could not write to log file: %s" % str(e))
# 使用UTF-8安全打印
def safe_print(text):
"""安全打印函数,处理编码问题"""
try:
if isinstance(text, unicode):
print(text.encode('gbk', 'ignore'))
else:
print(text)
except UnicodeEncodeError:
print(text.encode('gbk', 'ignore'))
except Exception as e:
print("[ERROR] Print error: %s" % str(e))
# 获取最新版本号
def get_latest_version():
"""获取最新版本号"""
try:
#version_url = "http://cos.ui-beam.com/work_scripts/monitor/dev/latest/VERSION.txt" # 测试版本版本号地址
version_url = "http://cos.ui-beam.com/work_scripts/monitor/releases/VERSION.txt" # 正式版本版本号地址
response = urllib2.urlopen(version_url)
version = response.read().strip()
return version
except Exception as e:
error_msg = u"获取版本号失败: %s" % unicode(str(e), 'gbk', 'ignore')
safe_print(error_msg)
return u"未知版本"
# 非中文字符界面信息
MESSAGES = {
'tool_title': u"网易大神审核数据监控系统安装工具",
'no_auth_version': u"当前最新版本:{0}".format(get_latest_version()),
'downloading': u"正在下载文件,请稍候...",
'script_started': u"下载脚本已启动",
'temp_dir': u"临时目录",
'dir_init_failed': u"初始化目录失败,退出",
'created_temp_dir': u"创建临时目录",
'dir_exists': u"临时目录已存在,正在清理内容...",
'dir_cleared': u"临时目录已清理",
'created_templates_dir': u"创建templates目录",
'created_static_dir': u"创建static目录",
'using_proxy': u"使用代理下载",
'retrying_with_proxy': u"尝试使用代理重试...",
'downloaded_files': u"已下载文件",
'of': u"个,共",
'files': u"个文件",
'download_required_failed': u"部分必需文件下载失败",
'all_files_downloaded': u"所有文件下载成功",
'install_deps_not_found': u"依赖安装脚本未找到",
'installing_deps': u"正在安装依赖...",
'deps_output': u"依赖安装输出",
'deps_error': u"依赖安装错误",
'deps_installed': u"依赖安装成功",
'deps_failed': u"依赖安装失败,返回码",
'deps_script_error': u"运行依赖安装脚本出错",
'start_script_not_found': u"启动脚本未找到",
'starting_system': u"正在启动监控系统...",
'system_started': u"监控系统启动成功",
'start_system_failed': u"启动监控系统失败",
'manual_guide_title': u"手动安装指南",
'manual_guide_intro': u"如果自动安装失败,请按照以下步骤手动安装:",
'use_ie': u"1. 获取系统文件:使用浏览器下载这些文件:",
'save_to_structure': u"2. 文件结构:将文件保存到以下结构:",
'run_deps_first': u"3. 安装依赖运行install_dependencies.bat安装依赖",
'then_run_start': u"4. 启动系统运行start_monitor.cmd启动系统",
'created_manual_guide': u"已创建手动安装指南",
'create_guide_failed': u"创建手动指南失败",
'script_copied': u"已将下载脚本复制到临时目录",
'copy_script_failed': u"复制脚本失败",
'deps_install_failed_try_start': u"依赖安装失败,尝试直接启动监控系统",
'steps_failed': u"某些步骤失败,请检查日志获取详情",
'try_manual': u"您可以尝试使用以下指南手动安装",
'unhandled_exception': u"未处理的异常",
'execution_completed': u"脚本执行完成",
'press_enter': u"按回车键退出..."
}
# 初始化目录函数
def init_directory():
"""初始化临时目录"""
try:
# 创建主目录
if not os.path.exists(TEMP_DIR):
os.makedirs(TEMP_DIR)
log_message("[INFO] %s: %s" % (MESSAGES['created_temp_dir'], TEMP_DIR))
else:
log_message("[INFO] %s" % MESSAGES['dir_exists'])
# 清理现有目录内容,只保留日志文件
for item in os.listdir(TEMP_DIR):
item_path = os.path.join(TEMP_DIR, item)
if item != "download_log.txt": # 现在只保留日志文件
if os.path.isdir(item_path):
shutil.rmtree(item_path)
else:
os.remove(item_path)
log_message("[INFO] %s" % MESSAGES['dir_cleared'])
# 创建templates子目录
templates_dir = os.path.join(TEMP_DIR, "templates")
if not os.path.exists(templates_dir):
os.makedirs(templates_dir)
log_message("[INFO] %s" % MESSAGES['created_templates_dir'])
# 创建static子目录
static_dir = os.path.join(TEMP_DIR, "static")
if not os.path.exists(static_dir):
os.makedirs(static_dir)
log_message("[INFO] %s" % MESSAGES['created_static_dir'])
return True
except Exception as e:
log_message("[ERROR] Failed to initialize directory: %s" % str(e))
return False
# 下载函数
def download_file(url_path, local_path, use_proxy=False):
"""下载单个文件,默认不使用代理"""
full_url = "%s/%s" % (COS_URL, url_path)
full_local_path = os.path.join(TEMP_DIR, local_path)
# 确保目标目录存在
local_dir = os.path.dirname(full_local_path)
if not os.path.exists(local_dir):
os.makedirs(local_dir)
log_message("[INFO] Downloading %s to %s" % (full_url, full_local_path))
try:
# 设置代理信息
if use_proxy:
log_message("[INFO] %s" % MESSAGES['using_proxy'])
proxy_handler = urllib2.ProxyHandler({
'http': 'http://CD-WEBPROXY02.yajuenet.internal:8080',
'https': 'http://CD-WEBPROXY02.yajuenet.internal:8080'
})
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
else:
# 禁用代理
proxy_handler = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
# 下载文件
response = urllib2.urlopen(full_url, timeout=30)
content = response.read()
# 写入文件
with open(full_local_path, 'wb') as f:
f.write(content)
log_message("[INFO] Successfully downloaded: %s" % local_path)
return True
except urllib2.URLError as e:
log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e)))
# 如果不使用代理失败,尝试使用代理
if not use_proxy:
log_message("[INFO] %s" % MESSAGES['retrying_with_proxy'])
return download_file(url_path, local_path, True)
return False
except Exception as e:
log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e)))
return False
# 下载所有文件
def download_all_files():
"""下载所有必要的文件"""
success_count = 0
failed_required = False
for url_path, local_path, required in FILES_TO_DOWNLOAD:
# 先尝试不使用代理下载
if download_file(url_path, local_path, False):
success_count += 1
elif required:
failed_required = True
log_message("[INFO] %s %d %s %d %s" % (
MESSAGES['downloaded_files'],
success_count,
MESSAGES['of'],
len(FILES_TO_DOWNLOAD),
MESSAGES['files']
))
if failed_required:
log_message("[ERROR] %s" % MESSAGES['download_required_failed'])
return False
return True
# 运行依赖安装脚本
def run_install_dependencies():
"""运行依赖安装脚本"""
install_script = os.path.join(TEMP_DIR, "install_dependencies.bat")
if not os.path.exists(install_script):
log_message("[ERROR] %s: %s" % (MESSAGES['install_deps_not_found'], install_script))
return False
try:
log_message("[INFO] %s" % MESSAGES['installing_deps'])
# 记录当前工作目录
original_dir = os.getcwd()
# 切换到临时目录并启动脚本
os.chdir(TEMP_DIR)
# 使用subprocess运行批处理文件并显示在控制台
# 移除stdout和stderr的PIPE重定向让输出直接显示在控制台
process = subprocess.Popen(["cmd", "/c", install_script],
shell=True)
# 等待脚本执行完成
return_code = process.wait()
# 返回到原始目录
os.chdir(original_dir)
if return_code == 0:
log_message("[INFO] %s" % MESSAGES['deps_installed'])
return True
else:
log_message("[ERROR] %s: %d" % (MESSAGES['deps_failed'], return_code))
return False
except Exception as e:
log_message("[ERROR] %s: %s" % (MESSAGES['deps_script_error'], str(e)))
return False
# 启动监控系统
def start_monitor_system():
"""启动监控系统"""
start_script = os.path.join(TEMP_DIR, "start_monitor.cmd")
if not os.path.exists(start_script):
log_message("[ERROR] %s: %s" % (MESSAGES['start_script_not_found'], start_script))
return False
try:
log_message("[INFO] %s" % MESSAGES['starting_system'])
# 记录当前工作目录
original_dir = os.getcwd()
# 切换到临时目录并启动脚本
os.chdir(TEMP_DIR)
# 使用subprocess启动批处理文件不等待其完成
process = subprocess.Popen(["cmd", "/c", "start", "", "start_monitor.cmd"],
shell=True)
# 返回到原始目录
os.chdir(original_dir)
log_message("[INFO] %s" % MESSAGES['system_started'])
return True
except Exception as e:
log_message("[ERROR] %s: %s" % (MESSAGES['start_system_failed'], str(e)))
return False
# 创建手动指南
def create_manual_guide():
"""创建手动安装指南"""
guide_path = os.path.join(TEMP_DIR, "manual_install_guide.txt")
try:
with codecs.open(guide_path, "w", "gbk") as f:
f.write("=" * 50 + "\n")
f.write("%s\n" % MESSAGES['manual_guide_title'])
f.write("=" * 50 + "\n\n")
f.write("%s\n\n" % MESSAGES['manual_guide_intro'])
f.write("%s\n\n" % MESSAGES['use_ie'])
for url_path, local_path, required in FILES_TO_DOWNLOAD:
full_url = "%s/%s" % (COS_URL, url_path)
f.write(" %s\n" % full_url)
f.write("\n%s\n\n" % MESSAGES['save_to_structure'])
f.write(" %s/\n" % TEMP_DIR)
f.write(" |-- start_monitor.cmd\n")
f.write(" |-- dashboard.py\n")
f.write(" |-- breeze_monitor.py\n")
f.write(" |-- breeze_monitor_CHAT.py\n")
f.write(" |-- cms_monitor.py\n")
f.write(" |-- inspect_monitor.py\n")
f.write(" |-- cms_coefficients.json\n")
f.write(" |-- breeze_coefficients.json\n")
f.write(" |-- install_dependencies.bat\n")
f.write(" |-- templates/\n")
f.write(" | |-- dashboard.html\n")
f.write(" | |-- login.html\n")
f.write(" |-- static/\n")
f.write(" |-- ds-favicon.ico\n\n")
f.write("%s\n\n" % MESSAGES['run_deps_first'])
f.write("%s\n\n" % MESSAGES['then_run_start'])
f.write("=" * 50 + "\n")
log_message("[INFO] %s: %s" % (MESSAGES['created_manual_guide'], guide_path))
return True
except Exception as e:
log_message("[ERROR] %s: %s" % (MESSAGES['create_guide_failed'], str(e)))
return False
# 主函数
def main():
"""主函数"""
try:
# 使用print可能会更安全不使用log_message来输出开头的界面
safe_print(u"\n%s" % MESSAGES['tool_title'])
print("======================================================\n")
safe_print(u"%s" % MESSAGES['no_auth_version'])
safe_print(u"%s\n" % MESSAGES['downloading'])
# 初始化日志
if not os.path.exists(os.path.dirname(LOG_FILE)):
os.makedirs(os.path.dirname(LOG_FILE))
log_message("\n" + "=" * 40)
log_message("[INFO] %s" % MESSAGES['script_started'])
log_message("[INFO] %s: %s" % (MESSAGES['temp_dir'], TEMP_DIR))
# 初始化目录
if not init_directory():
log_message("[ERROR] %s" % MESSAGES['dir_init_failed'])
return 1
# 创建手动指南
create_manual_guide()
# 下载文件
if download_all_files():
log_message("[INFO] %s" % MESSAGES['all_files_downloaded'])
# 安装依赖
if run_install_dependencies():
log_message("[INFO] %s" % MESSAGES['deps_installed'])
# 启动监控系统
if start_monitor_system():
# 稍等几秒,让监控系统先启动
time.sleep(3)
return 0
else:
log_message("[WARNING] %s" % MESSAGES['deps_install_failed_try_start'])
if start_monitor_system():
# 稍等几秒,让监控系统先启动
time.sleep(3)
return 0
log_message("[WARNING] %s" % MESSAGES['steps_failed'])
log_message("[INFO] %s: %s" % (
MESSAGES['try_manual'],
os.path.join(TEMP_DIR, "manual_install_guide.txt")
))
return 1
except Exception as e:
log_message("[ERROR] %s: %s" % (MESSAGES['unhandled_exception'], str(e)))
log_message("[TRACE] %s" % traceback.format_exc())
return 1
finally:
log_message("[INFO] %s" % MESSAGES['execution_completed'])
# 入口点
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,12 +1,11 @@
# -*- coding: utf-8 -*-
import base64,zlib,sys,os,getpass,json,time,random
from urllib import request as _req
import base64,zlib,sys,os,time,random
import threading,importlib,subprocess
def _u4spFJjOudXQ(d,k):
def _agAjBFr1KeeY(d,k):
return bytes(a^b for a,b in zip(d,k*(len(d)//len(k)+1)))
def _oan24KuHy(t,m,is_error=False):
def _D1AyQvAz0(t,m,is_error=False):
try:
try:
from playsound import playsound
@ -15,15 +14,15 @@ def _oan24KuHy(t,m,is_error=False):
stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
from playsound import playsound
# 播放系统声音
try:
import winsound
sound_type = winsound.MB_ICONERROR if is_error else winsound.MB_ICONINFORMATION
winsound.MessageBeep(sound_type)
except:
print("\a") # 备用蜂鸣声
print("\a")
# 在控制台打印消息
print("\n" + "="*50)
print(f"{t}: {m}")
print("="*50 + "\n")
@ -33,91 +32,18 @@ def _oan24KuHy(t,m,is_error=False):
print(f"\n{t}: {m} (提示音播放失败: {str(e)})\n")
return False
def _gGH0GWVKzJJ(t,m,e=0):
_oan24KuHy(t,m,e==1)
def _cPsIFmOQB7j(t,m,e=0):
_D1AyQvAz0(t,m,e==1)
def _wY4F1hg37():
_p=[104,116,116,112,58,47,47,99,111,115,46,117,105,45,98,101,97,109,46,99,111,109,47,119,111,114,107,95,115,99,114,105,112,116,115,47,109,111,110,105,116,111,114,47,99,111,110,102,105,103,47,115,116,97,102,102,46,106,115,111,110]
return ''.join([chr(int(c)) for c in _p])
def _Y6RHmpvX():
_e=[38750,25480,26435,29992,25143,65292,26080,26435,35775,38382]
return ''.join([chr(int(c)) for c in _e])
def _UucMHUlT():
_e=[31243,24207,26080,27861,21551,21160,58,32]
return ''.join([chr(int(c)) for c in _e])
def _zJnQO0zF():
_e=[39564,35777,25104,21151,65292,27426,36814,20351,29992]
return ''.join([chr(int(c)) for c in _e])
def _ai41mwqhbZ():
try:
_TPB2AaQC=getpass.getuser().upper()
_yWRVqZPV=os.path.basename(os.path.expanduser("~")).upper()
# 转换为小写进行比较
_Pw5eFewc=_TPB2AaQC.lower()
_dZjE1je=None
_oMo7wyh4=_wY4F1hg37()
_s,_p,_v=random.randint(1,5),random.randint(1,5),int(time.time())
try:
_h={"User-Agent":"Mozilla/5.0","X-Access-Token":str(_s*_p*_v)}
_r=_req.Request(_oMo7wyh4,headers=_h)
with _req.urlopen(_r,timeout=5) as _resp:
_fwYU7nW=_resp.read().decode()
_dZjE1je=json.loads(_fwYU7nW)
except:pass
if not _dZjE1je:
try:
_fwYU7nW=base64.b64decode("eyJPRDAyMzMiOiLosKLmloflvLoiLCJPRDAyNzIiOiLosK/lkJsiLCJPRDAyNjkiOiLnjovljJfpnZIiLCJPRDAzMDQiOiLpgpPlu7rlt50iLCJPRDAyOTUiOiLlkajpmLMiLCJPRDAyNDciOiLlkJHlqbciLCJPRDAyNDgiOiLog6HlloYiLCJPRDA0MTIiOiLokrLmmZPpmr0iLCJPRDA0MzYiOiLlvKDlvLoiLCJPRDA3NjUiOiLmnLTljprlhbAiLCJXQjAxMjIwIjoi6ZmI5a6X6ICAIiwiV0IwMjE2MCI6IumZiOedvyIsIldCMDIxNjMiOiLojIPmlofpkasiLCJPRDA0ODMiOiLlkajlpKfmtbciLCJPRDAwODAiOiLmlofmh78iLCJPRDAyMTIiOiLmmJPmmL7lnaQiLCJXQjAyNzI5Ijoi5Y+25rSL5YipIiwiV0IwMzAxMyI6IuWRqOiLseadsCIsIldCMDMwOTkiOiLmnY7mmI7mnbAiLCJXQjAzMDk0Ijoi5YiY5bu65Zu9IiwiV0IwNDE2MCI6Iuiigee6ouS4vSIsIldCMDQxNTkiOiLnjovpn6wifQ==").decode()
_dZjE1je=json.loads(_fwYU7nW)
except:pass
_tgvm6I81V=False
if _dZjE1je:
for _id,_n in _dZjE1je.items():
# 转换ID为小写进行比较
_SsFxjqx=_id.lower()
# 不区分大小写的比较
if (_Pw5eFewc==_SsFxjqx or
_yWRVqZPV.lower()==_SsFxjqx or
_Pw5eFewc.startswith(_SsFxjqx) or
_yWRVqZPV.lower().startswith(_SsFxjqx) or
_SsFxjqx in _Pw5eFewc or
_SsFxjqx in _yWRVqZPV.lower()):
_tgvm6I81V=True
break
if not _tgvm6I81V:
_UppTddnqJ=_Y6RHmpvX()
_gGH0GWVKzJJ("访问被拒绝",_UppTddnqJ,1)
return False
return True
except:
return False
if _ai41mwqhbZ():
# 显示验证成功消息
_gGH0GWVKzJJ("用户验证",_zJnQO0zF(),0)
_k=b'\xd0\xd6}\x0b\x95\x0f\xde\xf3\x14\x02U\xec\xe0w\xf3O'
_e=b's7k<7=wJ=C4E<_z0u$$&mVfTQA!oa4LU*`CU;(Mbz<gK0v6vVzr9ZB&f#2aYvDbUQPLJG>KaN*7)U82oH~>tw+2Z(&`6;<o+f0HjcRR;o_?iX;sNSX!e&C4ViVsg_7eo0{<)vEiGk<Nyh7i2C7%*~^lQylGlM%Iiw!}ElxvX5dBxe)S(GR?S#naIkpq>VF{uTOxT`dAx&u`KkhOyiVfapCH!KB+I<FtRu8i5g$DHX-5Cowe~ylWNF@R~YFhM>O)NhvxG4gOR)>rAsxgR{0o(}yLBHJsO4MZPl^vf6$(A|TD}IWA2s9#TXSOgb8PQXZR&WV0RN2VKu<9bh(D{6D(G?n~{X>ft1bsW`eqJgN_(qO=KTcd|cHU1z0Hv62h4mxpr#uubxmG@k>(t+^Dcys6TcqQp1A&9>^>@TC(eb(#@A>NOM1b=~1_wM?u<j#IhYZT}WK{L;M~I8z&f8mo2Y)=Zrp-T}H2T8t>*J}Rf(NWf@~$?`iw#d&;;Ch_QelPK9{h12#gH03jxLXXV;<~`F%gnBZZRAj6U1<VnGmmz%WSeDfU@Z!rY6&Fi}*9AMi=eAQbP#NILH`hx6c}B#Olnd9qTZtjkZ^KA&_NLg_Bh~4L%eOZ7S*sJPga}?r?z`@=P1;SnPOHBXj!Tx$0q$!vxEE-ig}2>i0A9Ae(NIk}RL5Qo`qnyHtq|t>oiiTK-++ZyfJYifv>Nd}=$%nZp-FcN?B#v$CJBy)bS4k&c=Nr~is(d12!z!80@hrdhfHH>WLZ_Rx}3LC+b8#<L5C+9E>c(Qbbd)}BPwt}_SgUHF^7(F`5v@Jep~N)xBit?xl9q;s{e;!qILjp2Z|c9y@+;lMlS}_$>zza&0=Yzftcr?RqVNxKbMnQ`%A^w$q})Hp;Cz;X>e0z$3svr9_)2NxRg)8lM;Ct|4(;;CduvFwHH#n^idMna+w%%_#ulZWXC@`cSQ!IH#v~I{utstuse!zI*W!iKHG2ZZ@xb!Ke;$~9ND%7E(ogdAm_TcBxAiaCJ$2YdN!2V{RLcU&eWIoq~)mt^qd2Bio`EZ4r6s`mlyr!wxi|<M6_P_ajq#YmieIB7l7z4&BNe3?sL0`w~|*u2!uPI?2>gulmyH<Rh3NB!h1)HQ%*VFET!1YKj1;u-%tWLp54+ryjK>xImoB^JMlC9O4Q)WOe@6|xGJ3DQTzuQ#6()K2I?@E6(?Hb#Q6Se_fji1qbbWMoauLv19qJ`ocpk8_^F!1fOpOP4KPx1&h<OS7e7kggwk2g(%fp|Lc+dPB&W4MS(vlUPfVv^2Fsy=?td7P&onq)_^ePi7o+NwK#}2b+8bZJx2|$rqxfUJq};Yfm%p`NRD&XaD^%A^Ka8Bk`P@r`5ppMn23y$i7&L1pK{8qH%a!FM5<tyJSzZy7>-INu$s>2pkY_1b|B;PoyS*TDK6&f}K66Oq!+Na{QSPkROXlItLltchUtM;XqDl8s^(+GE#q??+@T6}{pcM^H#u@ZTql-%37vQ9C+ZlpYXPIWSWr5OtshodDS?X#`qp_5F_mGtReb;XrkYJN+LP2;mlm3^?+Xl_2ufi2>V(n?sGX{iyQ%HIJ*G)#I59}0?ed7vdi#bv-1-J!B$wsj}veri@B71a)rk=BL%H(oz4=^2hO<8^%8TzK_V*2}XMIk}iu=C23R?kfo;EvE1_&28vN7wC@|H~5*E(IQn6%3YPS`NWXubto_n;K5?ZJoQ)r|Ox94*K%868c@7i_ikw8CQ4Z9dhp}Vj0zS#XO<deZs;SEduCLS4hVRoe{+6DAQigk#0Pn(z*Xumh*KBdK8n)S08xDbv15o-~2c@A1TUtV{4RAQlr`?i9`MQ(-be5m0wz#xqXAOD;buHfX?Asmz;|ePkGCC0pu01`{IW76W_4&7b)@r`zSmLQ3o^D>kStcAH3<uVX~ST{RMlYQ?}y8V8N%twCSPr_0O|yj_FQ<6=DNP>1%Sz)U~UQ!T+njmx+b)>KU3GBK7KnIm&tD<!e)y=yjxfMZUk;4CdOS?8wY{sJg{~4#Vw(5B&5U5mZo4r$+CM+?A!Wl<RIgG@d_OY^_524pTKt(U01owYn}l1t)@3HS3jw=>rA@B(ftHZ#01SRdl8@Pk2!@k|UZ0|7g`Dt6+3%Im0<@#+tc@YCr^tYkRWmg|4UHYZ!<$1&ak&DtLbd?BR{fAA&S$zoX;4t08PkY6JNa3-~yqdC81l=C^h8q)M0vZpXWQ%PVLMR>EuZ!zrP<ZX&ijA`dWN7zZ138-x)xB2L`*|EUaIJ54-9Rl}tHRxn14nHL=A<RGK1>u5aJ`~b!R6^Jj<8Gr;s5BcJ9z5xvLI1Qw6lB$Om{2C69R!|@g8Q30UP16|e^7j`3AtD>7i|GNnEb*!|Pf5<f9d0_Xca}bfFTw&lW;Kav3xXN?3Ouk+m%WOjJeJ=sj;(nOt3coLVqyR@#NC0lW<v'
try:
_d=base64.b85decode(_e)
_x=_u4spFJjOudXQ(_d,_k)
_c=zlib.decompress(_x)
exec(compile(_c.decode('utf-8'),'<string>','exec'))
except Exception as e:
_gGH0GWVKzJJ("错误",_UucMHUlT()+str(e)[:50],1)
sys.exit(1)
else:
time.sleep(1)
_GxOvPU=b'\xb0a=\xce\xc0\x1b\xcb\xfe1:\x8b\xd0\x18>\xdfK'
_gFwziLer=b'$o+tpy>uA3DaEu;`dZ7L_Q<Y!baSp}XHRB$m`H`dpvxBp<ctkHfCq4rd6vyE(O^4z8=J|U8n%fGEaYu!ShoytjP~t;+!1GKBL%K07mSCet&S53jplePhN-0G>bMW1LRaixz@3E5%Qiv6=BNC9O(bWYwhnWoYgn0h)^m6j?6^s^0bkATDMpZbrDT!a^@<aD+btx$rDQH$uh^2=)1}D=rO@LkIqml$g9ASgPn86o3@sa%-*_1q+}u?ZrH(H|qnKedv0xSoZAldTzF4M0ri*BJE6xdyRV$aD5UM5`m*Suc+G*kGS(y##OGZ&2X#&JVs#mv<1O#0qQc2opI9TXq1a_9kj{L1=zx6SMi~wYQ#N#8T!UIX7BBm-|cwc*MN!ur|_b@ZZ<yq&M5vSe#Rq!~j+#Zrr_s}BE=#Dh!2<$&C6)jQwzaa*|P~|^UO$C5K?&SF%IO_v8+3I5;z#2D(dK@()gII_V`#EGTqQwN{UY+L{9n^h*?8@bSJupy+Mn<T)#yrexpzA0T%&Z@rA~=jYvnj?zp+fAStSx{FWqVOa!Zm5<eXa{Q2&?BQb)XAFf)OsW!j6p(s8Gz#S6~aoEK<>)u`>yPqreT;4|E8$qq5D_2JJVyGyWR$IUG}N(Hu)h%Y!hCwUc4LE*$^Y+h2piB-XVLKwd<e<p7<dRZ63<^k|a>td4RCnqhjM_yqIzxC_AZC&{T&;P6_4;SS_5&83fbSpZuOj8Z)+a~+$DQ6ACJfVz>;>R$wmU68@{C+>ove+5r%1nw1g?}(yb{vRoyxy}n6PUROVA!=M<1`@7(4xZEKQ83Q8tO}t^TVpXsPq(>I+51r*|Lc-$hfdy8|HC%6-9I+B6FU>$?A{lZH7iA@;V-9J0Qjt#8m~=e0|M#OsiyHk^hTU5Oh}DcKMH&+ep@w!?SNX%wkoG22L@Y(Mt-dx-~&go(P_-&iqJH6n3l`!G1DqHQhnH%&v3lIp0A?#<u9LnAG25q#*#zo4+($cYOO7GIpJtI)<K5!Kv4R9ad)UW12>G*f`7Q(ow6LPo4|tmf!%jM4An1k>T_?3TX$e&vM(drPU^}GBm*8YB)U8!v%!Al@5#g}t#qLNyJxP7lB$V)@XZ&Sj3qUO!4TOraIKQ>Ix=gIGx>QNd9lsG8rYxeCmAk0{%Vr`=|cmy9PoL?!?+*$Dr2Az89&e%of1OcskJK}r1KheQ~o8IFdu~9Jh9Smm*s2o_C4MuxzVYt`#-Tg{7mqyt-X)VrB4&V^?81Eu0neQLMva>q3Vb7DwRg&B6a?dakHQ@e4uUdw*`x2W_;m9yK4=f>I~*#0Ofo#cND5o6@~PC|098cPv>4(!%ri4@yMe~vWIJ9tjZ31OXHV`YM6=0+~k$N={pO8X6%?WO(1?NWD1AUGu+7_a`%mm3`zu^&d%viF=|`N@X%?Ts)d+ko`wET#xTGDUc?9?mTtHmbk=g@v#-s`Bcd(U3Q1#?hjA%x4P`Fvr9&#@rLcNIg)P%^K2X?9!#oNbLiDj>{vljxpU_IM1vZkn{D^8weA2XVTllzsmnYOXD8qUdwOCD1x(HM-^GVkUjuP0aiu%h^nxsY5Q?bOm23&0L@^zS+_oX<M9aKuA-YrKxAb{I+F%O+M(qRYUcW+^egQjgwGOb>8Z--sH7)@&tJi>U@nzPq-C6)mk<>%j?bN7=d7{~k)n1JWW62thI+VjmV)=V;vb-UK24;s`#ilsgsV^d=G4J!K=^8Sp9E5a;_>a%f}>t{k9OhaPmI7%@Uno#+1rHkPmDAv~$2s$=yuL0`~{icK>eaB0}v{vGyD)7@%_Cz(#F93$Yawn$rjeJ6Cze{-iN<H6nMpH^{s_OP4>GZukh5$O1uxEs(K{T(nORm;V)!Ot|vZPfnw=m~(VN+FguJ)7rHs@~7?_k~ro1c8o1QRCP&Nay@=k>+I0R`IJs1a_ic8)yxn23wU)L!8+pxdTktI?3Y?JF-$iQF;|fuX*G<i~Y`Z@{Vcimuw(cj5nz9P+2w9U^~|h{EK)5UQ%wDc%I16oKG<$PI->Ti5uGD#R)w=^cDZ$MLU7iGi@cvD2^z%-0iN3>pGITSp*9^tS|@P4fajWst&=VE=%Q%sbdQ-1`p`4}-um0ARB}YCw+&YHGFtpWl_?{&Znx9Q)@`KGT(h3im`!K5wVypq6>#lToBFWjsZae{5<9$=Orz=gSyw-xQ;H{xx|=Pdg_r^RX1B8Gg)~v!h`CfpSJWmX4QstDGpw1J-{2<`I8}mTQ_nLb!0HO%o1&KD^Hf+6VCSpB_w^ZdoZwaQk|}u6b&R`Jh}Pu{5@z&QRj(1WD=!bw6(uOq3B$D#1KXMo1v{Si0o2$G(yq*&@)gt{Dspd2e2(7{?9c*U!m4*=skf>s~>BdF8)3YH<+#<tG-j7a@K^de#><Lk(9|^UF2<YK!oS!l|FH8Lj~mcH~tF%lDr)H+B_1;pJb6o(c'
try:
_L4lLFNi=base64.b85decode(_gFwziLer)
_xoMpEZj=_agAjBFr1KeeY(_L4lLFNi,_GxOvPU)
_W9cROmjF=zlib.decompress(_xoMpEZj)
exec(compile(_W9cROmjF.decode('utf-8'),'<string>','exec'))
except Exception as e:
_YdA3Am9Vo="程序无法启动: "+str(e)[:50]
_cPsIFmOQB7j("错误",_YdA3Am9Vo,1)
sys.exit(1)

View File

@ -3,15 +3,6 @@ chcp 65001 >nul
cd /d "C:\Python39"
echo 正在安装网易大神审核数据监控系统所需依赖...
echo 请稍候...
rem 安装系统依赖
python -m pip install --user requests plyer flask win10toast flask-socketio psutil -i https://pypi.tuna.tsinghua.edu.cn/simple
rem 安装加密/解密所需的标准库依赖
echo.
echo 正在安装加密/解密所需的依赖...
python -m pip install --user base64io pycryptodome -i https://pypi.tuna.tsinghua.edu.cn/simple
echo.
echo 依赖安装完成!
echo 请使用 start_monitor.cmd 启动系统

390
releases.html Normal file
View File

@ -0,0 +1,390 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网易大神实时审核数据监控看板 - 版本更新日志</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
body {
background-color: #f7f7f7;
color: #333;
line-height: 1.6;
padding: 20px;
}
.container {
max-width: 1000px;
margin: 0 auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
padding: 30px;
}
header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eaeaea;
}
header h1 {
color: #1a1a1a;
font-size: 28px;
margin-bottom: 5px;
}
header p {
color: #666;
}
.release-item {
margin-bottom: 35px;
padding-bottom: 25px;
border-bottom: 1px solid #eaeaea;
}
.release-item:last-child {
border-bottom: none;
}
.release-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.release-date {
font-size: 18px;
font-weight: bold;
color: #1a1a1a;
}
.release-tag {
background-color: #eaf4fe;
color: #1890ff;
padding: 4px 10px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.2s;
}
.release-tag:hover {
background-color: #d8eafd;
}
.release-tag a {
color: #1890ff;
text-decoration: none;
}
.release-content {
margin-top: 15px;
}
.no-log {
color: #888;
font-style: italic;
padding: 10px 0;
}
h5 {
color: #722ed1;
margin-bottom: 10px;
font-size: 16px;
}
ul {
padding-left: 20px;
}
li {
margin-bottom: 5px;
}
li strong {
color: #333;
}
li ul {
margin-top: 5px;
margin-bottom: 10px;
}
footer {
text-align: center;
margin-top: 30px;
color: #999;
font-size: 14px;
}
.bug-fix {
background-color: #fff2e8;
border-left: 3px solid #fa8c16;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 0 4px 4px 0;
}
.feature {
background-color: #e6f7ff;
border-left: 3px solid #1890ff;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 0 4px 4px 0;
}
.optimization {
background-color: #f6ffed;
border-left: 3px solid #52c41a;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 0 4px 4px 0;
}
.enhancement {
background-color: #f9f0ff;
border-left: 3px solid #722ed1;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 0 4px 4px 0;
}
.first-version {
background-color: #f0f5ff;
border-left: 3px solid #2f54eb;
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 0 4px 4px 0;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>网易大神实时审核数据监控看板 - 版本更新日志</h1>
<p>记录系统各版本的更新内容和修复问题</p>
</header>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月22日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250422193845" target="_blank">v20250422193845</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月22日更新 (v20250422193845)</h5>
<div class="feature">
<h4>登录功能优化</h4>
<ul>
<li>优化了系统登录逻辑,现在允许任意工号登录系统</li>
<li>登录后会自动从staff.json文件中查找对应的员工姓名</li>
<li>如果工号存在于staff.json中显示格式为"工号 (姓名)"</li>
<li>如果工号不存在于staff.json中则仅显示工号</li>
</ul>
</div>
<div class="optimization">
<h4>界面显示优化</h4>
<ul>
<li>优化了当前登录用户的显示格式</li>
<li>移除了多余的括号显示</li>
<li>统一了用户信息的展示方式</li>
</ul>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月22日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250422120008" target="_blank">v20250422120008</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月22日更新 (v20250422120008)</h5>
<div class="bug-fix">
<h4>Bug修复</h4>
<p><strong>前端量级显示依赖双业务数据问题修复</strong></p>
<p>修复了仅有单一业务数据时,前端量级显示一直"加载中"的问题。现在即使用户只有清风审核或只有大神CMS的数据系统也能正确显示相应的量级信息不再要求必须同时存在两个业务的数据。</p>
</div>
<div class="feature">
<h4>业务登录灵活性优化</h4>
<p>优化了系统登录逻辑现在用户可以选择性输入清风审核或大神CMS的Cookie不再强制要求同时输入两者。系统将根据用户提供的Cookie自动识别并只监控相应的业务数据提升了系统的灵活性和用户体验。</p>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月14日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250414155609" target="_blank">v20250414155609</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月14日更新 (v20250414155609)</h5>
<div class="first-version">
<p class="no-log">无更新日志</p>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月13日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250413153104" target="_blank">v20250413153104</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月13日更新 (v20250413153104)</h5>
<div class="optimization">
<h4>进程管理优化</h4>
<ul>
<li>优化了监控进程的启动和终止逻辑,确保进程能够正确关闭和重启</li>
<li>改进了CMS监控进程的启动方式现在与Breeze进程一样在独立窗口中运行</li>
<li>修复了更新当前小时数据时可能导致进程重复的问题</li>
<li>增强了进程终止机制,添加超时和强制终止功能</li>
<li>优化了临时检查进程的管理,确保检查完成后能正确恢复监控状态</li>
<li>添加了进程状态检查和等待机制,防止进程启动和终止时的竞争条件</li>
<li>添加了进程状态检查的超时机制</li>
<li>优化了start_monitor.cmd脚本自动关闭命令窗口保持界面简洁</li>
</ul>
</div>
<div class="feature">
<h4>用户界面改进</h4>
<ul>
<li>修改了当前登录用户的显示格式,改为"工号(姓名)"的形式</li>
<li>统一了顶部按钮的样式和布局</li>
<li>优化了登录错误提示信息,提供更清晰的错误原因和联系方式</li>
<li>添加未识别工单弹窗展示功能,方便用户快速查看无法识别的工单</li>
<li>修改按钮文案,使功能描述更加准确</li>
<li>添加操作确认对话框,防止误操作</li>
</ul>
</div>
<div class="enhancement">
<h4>工单识别优化</h4>
<ul>
<li>优化了聊天类工单的识别逻辑,支持通过标题关键词识别"私聊频繁"、"聊天室频繁"等工单类型</li>
<li>增强了对空值(None)的处理,避免"NoneType is not iterable"错误</li>
<li>调整了媒体类型名称,将"图片"更改为"IMAGES""视频"更改为"VIDEOS",统一英文命名</li>
<li>优化了URL匹配逻辑支持更多来源的媒体识别</li>
<li>改进了工单类型识别方法,提高识别准确率</li>
</ul>
</div>
<div class="feature">
<h4>功能与数据处理优化</h4>
<ul>
<li>改进了"更新当前小时数据"和"更新全天数据"功能的实现</li>
<li>添加API返回零记录时的自动重试机制最多重试5次间隔5秒</li>
<li>优化了进程间通信机制</li>
<li>改进了数据更新流程,减少不必要的进程重启</li>
</ul>
</div>
<div class="enhancement">
<h4>日志与错误处理增强</h4>
<ul>
<li>添加日志级别区分功能,使用不同图标标识不同级别(⚠️警告、❌错误)</li>
<li>优化日志输出格式,减少冗余信息,使日志更加简洁明了</li>
<li>工单识别错误时记录详细信息包括工单ID、标题和唯一ID便于排查问题</li>
<li>添加了更详细的错误日志记录</li>
<li>改进了进程异常情况的处理逻辑</li>
<li>增加了进程终止失败时的备选方案</li>
</ul>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月10日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250410232012" target="_blank">v20250410232012</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月10日更新 (v20250410232012)</h5>
<div class="feature">
<h4>登录页面美化</h4>
<ul>
<li>优化了登录页面的整体布局和样式</li>
<li>调整了输入框和按钮的视觉效果</li>
<li>改进了错误提示的显示方式</li>
<li>优化了页面响应式布局</li>
</ul>
</div>
<div class="optimization">
<h4>界面优化</h4>
<ul>
<li>删除了仪表盘中的冗余按钮,使界面更加简洁</li>
<li>优化了按钮的布局和排列</li>
</ul>
</div>
<div class="enhancement">
<h4>版本管理优化</h4>
<ul>
<li>新增releases文件夹优化版本管理结构</li>
<li>测试版本号添加"-dev"后缀,便于区分</li>
<li>正式版本保持纯版本号格式</li>
</ul>
</div>
<div class="feature">
<h4>版本检测功能优化</h4>
<ul>
<li>优化版本检测对话框,根据检测结果动态显示不同标题</li>
<li>检测到更新时显示"检测到版本更新"</li>
<li>常规检测时显示"系统版本检测"</li>
</ul>
</div>
<div class="bug-fix">
<h4>数据统计优化</h4>
<p>修复了大神大宋视频的检测统计逻辑,提高数据准确性</p>
</div>
<div class="optimization">
<h4>按钮文案优化</h4>
<p>将"检测更新"按钮文案更新为"检测版本更新",使功能更加明确</p>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月8日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250408165207" target="_blank">v20250408165207</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月8日更新 (v20250408165207)</h5>
<div class="feature">
<h4>一键部署功能</h4>
<p>添加download_auto_run.py一键安装脚本自动下载文件、安装依赖并启动系统简化安装流程</p>
</div>
<div class="optimization">
<h4>CMS数据查询效率提升</h4>
<p>将每页查询数量从30条增加到500条大幅减少API请求次数加快数据刷新速度</p>
</div>
<div class="enhancement">
<h4>系数配置文件</h4>
<p>添加cms_coefficients.json和breeze_coefficients.json配置文件便于系统重装后恢复系数设置</p>
</div>
<div class="feature">
<h4>登出优化</h4>
<p>登出时自动清理所有共享数据文件并完全退出程序,加强数据安全性</p>
</div>
<div class="enhancement">
<h4>实时数据监控</h4>
<p>优化配置文件监控逻辑,更快响应系数变化</p>
</div>
</div>
</div>
<div class="release-item">
<div class="release-header">
<div class="release-date">2025年4月8日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250408134718" target="_blank">v20250408134718</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月8日更新 (v20250408134718)</h5>
<div class="first-version">
<h4>首次发布</h4>
<p>此版本为该项目的第一版,无日志</p>
</div>
</div>
</div>
<footer>
<p>© 2025 网易DS监控系统 - 版本更新日志</p>
</footer>
</div>
</body>
</html>

View File

@ -733,7 +733,7 @@
<span id="version-display" class="version-display">加载中...</span>
</div>
<div class="header-buttons">
<button class="current-user">当前登录用户:{{ username }}{{ staff_name }}</button>
<button class="current-user">当前登录用户:{{ staff_name }}</button>
<button class="refresh-button">刷新数据</button>
<button class="check-now-button">更新当前小时数据</button>
<button class="test-alarm-button">测试告警</button>
@ -1141,73 +1141,87 @@
function updateDashboard(data) {
try {
// 更新统计栏数据
if (data.breeze && data.breeze.hourly) {
if (data.breeze) {
// 更新顶部统计数据
document.getElementById('breeze-total').textContent = data.breeze.hourly.total || '0';
document.getElementById('breeze-daily-total').textContent = data.breeze.daily ? (data.breeze.daily.total || '0') : '0';
document.getElementById('breeze-total').textContent = data.breeze.hourly && data.breeze.hourly.total ? data.breeze.hourly.total : '0';
document.getElementById('breeze-daily-total').textContent = data.breeze.daily && data.breeze.daily.total ? data.breeze.daily.total : '0';
// 更新Breeze工单系统面板
document.getElementById('breeze-hourly-count').textContent = data.breeze.hourly.total || '-';
document.getElementById('breeze-hourly-weighted').textContent = data.breeze.hourly.weighted_total ? data.breeze.hourly.weighted_total.toFixed(2) : '-';
document.getElementById('breeze-daily-count').textContent = data.breeze.daily ? (data.breeze.daily.total || '-') : '-';
document.getElementById('breeze-daily-weighted').textContent = data.breeze.daily ? (data.breeze.daily.weighted_total || '-').toFixed(2) : '-';
// 更新小时类别数据
const breezeHourlyCategories = document.getElementById('breeze-hourly-categories');
if (data.breeze.hourly.categories) {
let categoriesHTML = `
<div class="category-header">
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
for (const [name, info] of Object.entries(data.breeze.hourly.categories)) {
if (info.count > 0) {
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
if (data.breeze.hourly) {
document.getElementById('breeze-hourly-count').textContent = data.breeze.hourly.total || '0';
document.getElementById('breeze-hourly-weighted').textContent = data.breeze.hourly.weighted_total ? data.breeze.hourly.weighted_total.toFixed(2) : '0.00';
// 更新小时类别数据
const breezeHourlyCategories = document.getElementById('breeze-hourly-categories');
if (data.breeze.hourly.categories) {
let categoriesHTML = `
<div class="category-header">
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
for (const [name, info] of Object.entries(data.breeze.hourly.categories)) {
if (info.count > 0) {
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
}
}
breezeHourlyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeHourlyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
}
breezeHourlyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeHourlyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
document.getElementById('breeze-hourly-count').textContent = '0';
document.getElementById('breeze-hourly-weighted').textContent = '0.00';
document.getElementById('breeze-hourly-categories').innerHTML = '<div class="loading">暂无可用数据</div>';
}
// 更新日类别数据
const breezeDailyCategories = document.getElementById('breeze-daily-categories');
if (data.breeze.daily.categories) {
let categoriesHTML = `
<div class="category-header">
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
for (const [name, info] of Object.entries(data.breeze.daily.categories)) {
if (info.count > 0) {
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
// 更新日数据
if (data.breeze.daily) {
document.getElementById('breeze-daily-count').textContent = data.breeze.daily.total || '0';
document.getElementById('breeze-daily-weighted').textContent = data.breeze.daily.weighted_total ? data.breeze.daily.weighted_total.toFixed(2) : '0.00';
// 更新日类别数据
const breezeDailyCategories = document.getElementById('breeze-daily-categories');
if (data.breeze.daily.categories) {
let categoriesHTML = `
<div class="category-header">
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
for (const [name, info] of Object.entries(data.breeze.daily.categories)) {
if (info.count > 0) {
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
}
}
breezeDailyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeDailyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
}
breezeDailyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeDailyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
document.getElementById('breeze-daily-count').textContent = '0';
document.getElementById('breeze-daily-weighted').textContent = '0.00';
document.getElementById('breeze-daily-categories').innerHTML = '<div class="loading">暂无可用数据</div>';
}
// 更新最后更新时间
document.getElementById('breeze-last-update').textContent = '最后更新: ' + data.breeze.hourly_update;
document.getElementById('breeze-last-update').textContent = '最后更新: ' + (data.breeze.hourly_update || '无数据');
// 更新时间戳
if (data.breeze.hourly_update) {
@ -1219,19 +1233,28 @@
}
// 更新CMS数据
if (data.cms && data.cms.hourly) {
if (data.cms) {
// 更新顶部统计栏
const cmsTotal = data.cms.hourly.total_count || 0;
document.getElementById('cms-total').textContent = cmsTotal;
document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0';
const cmsHourlyTotal = data.cms.hourly && data.cms.hourly.total_count ? data.cms.hourly.total_count : 0;
document.getElementById('cms-total').textContent = cmsHourlyTotal;
document.getElementById('cms-daily-total').textContent = data.cms.daily && data.cms.daily.total_count ? data.cms.daily.total_count : '0';
// 更新CMS审核系统面板
document.getElementById('cms-hourly-comment').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.comment : '-';
document.getElementById('cms-hourly-feed').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.feed : '-';
document.getElementById('cms-hourly-complaint').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.complaint : '-';
document.getElementById('cms-hourly-count').textContent = data.cms.hourly.total_count || '-';
document.getElementById('cms-hourly-weighted').textContent = data.cms.hourly.weighted_total ? data.cms.hourly.weighted_total.toFixed(2) : '-';
document.getElementById('cms-last-update').textContent = '最后更新: ' + data.cms.hourly_update;
if (data.cms.hourly && data.cms.hourly.stats) {
document.getElementById('cms-hourly-comment').textContent = data.cms.hourly.stats.comment || '0';
document.getElementById('cms-hourly-feed').textContent = data.cms.hourly.stats.feed || '0';
document.getElementById('cms-hourly-complaint').textContent = data.cms.hourly.stats.complaint || '0';
document.getElementById('cms-hourly-count').textContent = data.cms.hourly.total_count || '0';
document.getElementById('cms-hourly-weighted').textContent = data.cms.hourly.weighted_total ? data.cms.hourly.weighted_total.toFixed(2) : '0.00';
} else {
document.getElementById('cms-hourly-comment').textContent = '0';
document.getElementById('cms-hourly-feed').textContent = '0';
document.getElementById('cms-hourly-complaint').textContent = '0';
document.getElementById('cms-hourly-count').textContent = '0';
document.getElementById('cms-hourly-weighted').textContent = '0.00';
}
document.getElementById('cms-last-update').textContent = '最后更新: ' + (data.cms.hourly_update || '无数据');
// 更新时间戳
if (data.cms.hourly_update) {
@ -1240,26 +1263,36 @@
if (data.cms.daily_update) {
document.getElementById('cms-daily-time').textContent = data.cms.daily_update;
}
}
// 更新CMS每日数据
if (data.cms && data.cms.daily && data.cms.daily.stats) {
document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats.comment || '-';
document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats.feed || '-';
document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats.complaint || '-';
document.getElementById('cms-daily-count').textContent = data.cms.daily.total_count || '-';
document.getElementById('cms-daily-weighted').textContent = data.cms.daily.weighted_total ? data.cms.daily.weighted_total.toFixed(2) : '-';
// 更新CMS每日数据
if (data.cms.daily && data.cms.daily.stats) {
document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats.comment || '0';
document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats.feed || '0';
document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats.complaint || '0';
document.getElementById('cms-daily-count').textContent = data.cms.daily.total_count || '0';
document.getElementById('cms-daily-weighted').textContent = data.cms.daily.weighted_total ? data.cms.daily.weighted_total.toFixed(2) : '0.00';
} else {
document.getElementById('cms-daily-comment').textContent = '0';
document.getElementById('cms-daily-feed').textContent = '0';
document.getElementById('cms-daily-complaint').textContent = '0';
document.getElementById('cms-daily-count').textContent = '0';
document.getElementById('cms-daily-weighted').textContent = '0.00';
}
}
// 更新CC审核平台数据
if (data.inspect && data.inspect.hourly) {
const hourlyTotal = data.inspect.hourly.total || 0;
const hourlyWeighted = data.inspect.hourly.weighted_total || 0;
if (data.inspect) {
const hourlyTotal = data.inspect.hourly && data.inspect.hourly.total ? data.inspect.hourly.total : 0;
const hourlyWeighted = data.inspect.hourly && data.inspect.hourly.weighted_total ? data.inspect.hourly.weighted_total : 0;
document.getElementById('inspect-hourly-total').textContent = hourlyTotal;
document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(hourlyWeighted)})`;
document.getElementById('inspect-daily-total').textContent = data.inspect.daily ? (data.inspect.daily.total || '0') : '0';
if (data.inspect.daily) {
document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total)})`;
document.getElementById('inspect-daily-total').textContent = data.inspect.daily.total || '0';
document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total || 0)})`;
} else {
document.getElementById('inspect-daily-total').textContent = '0';
document.getElementById('inspect-daily-weighted').textContent = '(0)';
}
// 更新时间戳

View File

@ -570,18 +570,18 @@
</div>
<div class="form-group">
<label>Breeze工单系统 Cookie</label>
<input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie" required>
<label>Breeze工单系统 Cookie(可选)</label>
<input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie(可选)">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项
此选项可填可不填适用于您需要监控Breeze系统工单的情况
</div>
</div>
<div class="form-group">
<label>CMS系统 Cookie</label>
<input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie" required>
<label>CMS系统 Cookie(可选)</label>
<input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie(可选)">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项
此选项可填可不填适用于您需要监控CMS系统操作的情况
</div>
</div>
@ -593,6 +593,10 @@
</div>
</div>
<div class="form-info" style="background-color: #fffbe6; border: 1px solid #ffe58f; padding: 10px; border-radius: 4px; margin-bottom: 15px;">
<p style="margin: 0; color: #d48806; font-size: 13px;">请至少填写一项系统Cookie否则无法获取任何审核数据</p>
</div>
<div class="cookie-guide">
<a href="http://cos.ui-beam.com/work_scripts/monitor/cookie-extension/README.html" target="_blank">如何获取Cookie点击查看详细指南</a>
</div>
@ -630,6 +634,16 @@
const formData = new FormData(this);
// 检查是否至少有一个Cookie填写了
const breezeCookie = formData.get('breeze_cookie');
const cmsCookie = formData.get('cms_cookie');
const inspectCookie = formData.get('inspect_cookie');
if (!breezeCookie && !cmsCookie && !inspectCookie) {
showMessage('error', '请至少填写一个系统的Cookie');
return;
}
fetch('/login', {
method: 'POST',
body: formData
@ -654,4 +668,4 @@
});
</script>
</body>
</html>
</html>