Compare commits

...

18 Commits

Author SHA1 Message Date
ui-beam-9
c0591bb986 移除版本号显示 2025-04-30 02:05:03 +08:00
ui-beam-9
9a320cba65 删除版本号获取 2025-04-29 22:30:43 +08:00
ui-beam-9
ecb30f7aa1 发布新版本v20250429213045 2025-04-29 22:24:48 +08:00
ui-beam-9
6a7170cbb0 发布新版本v20250429213045 2025-04-29 22:20:35 +08:00
ui-beam-9
d8bbf99087 发布新版本v20250429213045 2025-04-29 22:03:17 +08:00
ui-beam-9
08c23af39c 发布新版本v20250429213045 2025-04-29 22:01:18 +08:00
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
15 changed files with 1066 additions and 836 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 v20250429213045

View File

@ -1,22 +0,0 @@
{
"NTES_GOD_IMAGES": 0.54,
"NTES_GOD_VIDEOS": 3.8,
"NTES_GOD_CHAT_IMAGES": 0.54,
"NTES_GOD_CHAT_VIDEOS": 3.8,
"NTES_DASONG": 139.19,
"SPIDER_VIDEO": 3.8,
"SPIDER_VIDEO_SP": 13.3,
"NTES_GOD_AI": 0.54,
"NTES_GOD_TOP": 3.8,
"T_SPIDER_VIDEO": 3.8,
"T_SPIDER_VIDEO_SP": 13.3,
"V_SPIDER_VIDEO": 3.8,
"V_SPIDER_VIDEO_SP": 13.3,
"NTES_GOD_XHS": 0.54,
"XHS_SPIDER_VIDEO": 3.8,
"Cupid": 0.54,
"CHAT_P2P": 0.55,
"CHAT_TEAM": 0.55,
"CHAT_ROOM": 0.55,
"CHAT_ROOM_MSG": 0.55
}

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 +0,0 @@
{ "comment": 0.55, "feed": 1.54, "complaint": 5.4 }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,16 +18,21 @@ import traceback
import codecs import codecs
from datetime import datetime from datetime import datetime
# 先尝试设置控制台代码页为UTF-8仅Windows环境 # 先尝试设置控制台代码页为GBK仅Windows环境
try: try:
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
# Windows下默认使用GBK编码代码页936
# 先设置控制台代码页
subprocess.call('chcp 936', shell=True) subprocess.call('chcp 936', shell=True)
# 再设置Python默认编码
import sys
reload(sys)
sys.setdefaultencoding('gbk')
except: except:
pass pass
# 基本配置 # 基本配置
#COS_URL = "http://cos.ui-beam.com/work_scripts/monitor/dev/latest/" COS_URL = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main"
COS_URL = "http://cos.ui-beam.com/work_scripts/monitor/releases/latest/"
TEMP_DIR = os.path.join(os.path.expanduser("~"), "Desktop", "monitor_temp") TEMP_DIR = os.path.join(os.path.expanduser("~"), "Desktop", "monitor_temp")
LOG_FILE = os.path.join(TEMP_DIR, "download_log.txt") LOG_FILE = os.path.join(TEMP_DIR, "download_log.txt")
@ -38,8 +43,6 @@ FILES_TO_DOWNLOAD = [
("breeze_monitor.py", "breeze_monitor.py", True), ("breeze_monitor.py", "breeze_monitor.py", True),
("breeze_monitor_CHAT.py", "breeze_monitor_CHAT.py", True), ("breeze_monitor_CHAT.py", "breeze_monitor_CHAT.py", True),
("cms_monitor.py", "cms_monitor.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/dashboard.html", "templates/dashboard.html", True),
("templates/login.html", "templates/login.html", True), ("templates/login.html", "templates/login.html", True),
("static/ds-favicon.ico", "static/ds-favicon.ico", True), ("static/ds-favicon.ico", "static/ds-favicon.ico", True),
@ -56,48 +59,130 @@ def log_message(message):
if not os.path.exists(log_dir): if not os.path.exists(log_dir):
os.makedirs(log_dir) os.makedirs(log_dir)
# 处理可能的编码问题
try:
# 如果是字符串确保它是unicode
if isinstance(message, str):
message = message.decode('gbk', 'ignore')
# 使用codecs打开文件指定编码为gbk # 使用codecs打开文件指定编码为gbk
with codecs.open(LOG_FILE, "a", "gbk") as f: with codecs.open(LOG_FILE, "a", "gbk", errors='ignore') as f:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_line = "[%s] %s\n" % (timestamp, message) log_line = "[%s] %s\n" % (timestamp, message)
f.write(log_line) f.write(log_line)
except:
# 如果上面的方法失败,尝试另一种方式写入
with open(LOG_FILE, "a") as f:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
try:
log_line = "[%s] %s\n" % (timestamp, message)
if isinstance(log_line, unicode):
f.write(log_line.encode('gbk', 'ignore'))
else:
f.write(str(log_line))
except:
f.write("[%s] [ENCODE_ERROR] 无法写入日志内容\n" % timestamp)
# 使用safe_print输出到控制台 # 使用safe_print输出到控制台
safe_print(message) safe_print(message)
except Exception as e: except Exception as e:
safe_print("[ERROR] Could not write to log file: %s" % str(e)) try:
# 以简单的方式输出日志错误
error_msg = "日志写入错误,继续执行程序"
print(error_msg)
except:
pass # 如果连简单输出都失败,就完全忽略错误
# 使用UTF-8安全打印 # 使用UTF-8安全打印
def safe_print(text): def safe_print(text):
"""安全打印函数,处理编码问题""" """安全打印函数,处理编码问题"""
try: try:
if isinstance(text, unicode): # 如果是字节串且不是unicode尝试转换
if isinstance(text, str) and not isinstance(text, unicode):
try:
# 先尝试gbk解码
text = text.decode('gbk', 'ignore')
except:
try:
# 再尝试utf-8解码
text = text.decode('utf-8', 'ignore')
except:
# 都失败,直接转为字符串
text = unicode(str(text), 'gbk', 'ignore')
# 输出到控制台
if sys.platform.startswith('win'):
# Windows平台强制使用gbk编码
print(text.encode('gbk', 'ignore')) print(text.encode('gbk', 'ignore'))
else: else:
print(text) # 其他平台使用utf-8编码
except UnicodeEncodeError: print(text.encode('utf-8', 'ignore'))
print(text.encode('gbk', 'ignore'))
except Exception as e: except Exception as e:
print("[ERROR] Print error: %s" % str(e)) # 如果还是失败,使用最简单的方式
try:
print(u"打印失败")
except:
pass # 完全放弃
# 获取最新版本号 # 获取最新版本号
def get_latest_version(): def get_latest_version():
"""获取最新版本号""" """获取最新版本号"""
try: try:
#version_url = "http://cos.ui-beam.com/work_scripts/monitor/dev/latest/VERSION.txt" # 测试版本版本号地址 version_url = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main/VERSION.txt"
version_url = "http://cos.ui-beam.com/work_scripts/monitor/releases/VERSION.txt" # 正式版本版本号地址
response = urllib2.urlopen(version_url) # 添加身份验证
username = "bug"
password = "12345678"
auth_string = base64.b64encode('%s:%s' % (username, password))
# 创建请求对象并添加认证头
request = urllib2.Request(version_url)
request.add_header('Authorization', 'Basic %s' % auth_string)
# 尝试不使用代理下载
try:
# 禁用代理
proxy_handler = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
response = urllib2.urlopen(request, timeout=30)
version = response.read().strip() version = response.read().strip()
return version return version
except urllib2.URLError as e:
log_message("[WARNING] 不使用代理获取版本失败,尝试使用代理: %s" % str(e))
# 使用代理重试
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)
response = urllib2.urlopen(request, timeout=30)
version = response.read().strip()
return version
except Exception as e: except Exception as e:
error_msg = u"获取版本号失败: %s" % unicode(str(e), 'gbk', 'ignore') error_msg = u"获取版本号失败: %s" % unicode(str(e), 'gbk', 'ignore')
safe_print(error_msg) log_message("[ERROR] %s" % error_msg)
# 如果获取失败直接从文件URL解析出固定版本号格式
try:
# 搜索files_to_download中最新的版本号
for url_path, _, _ in FILES_TO_DOWNLOAD:
if "VERSION" in url_path.upper():
log_message("[INFO] 尝试从文件路径解析版本号: %s" % url_path)
return "v" + datetime.now().strftime("%Y%m%d%H%M%S")
except:
pass
return u"未知版本" return u"未知版本"
# 非中文字符界面信息 # 非中文字符界面信息
MESSAGES = { MESSAGES = {
'tool_title': u"网易大神审核数据监控系统安装工具", 'tool_title': u"网易大神审核数据监控系统安装工具",
'no_auth_version': u"当前最新版本:{0}".format(get_latest_version()),
'downloading': u"正在下载文件,请稍候...", 'downloading': u"正在下载文件,请稍候...",
'script_started': u"下载脚本已启动", 'script_started': u"下载脚本已启动",
'temp_dir': u"临时目录", 'temp_dir': u"临时目录",
@ -193,47 +278,74 @@ def download_file(url_path, local_path, use_proxy=False):
if not os.path.exists(local_dir): if not os.path.exists(local_dir):
os.makedirs(local_dir) os.makedirs(local_dir)
log_message("[INFO] Downloading %s to %s" % (full_url, full_local_path)) # 只显示文件名不显示完整URL
log_message(u"[INFO] 正在下载文件: %s" % os.path.basename(url_path))
try: try:
# 设置代理信息 # 设置代理信息
if use_proxy: if use_proxy:
log_message("[INFO] %s" % MESSAGES['using_proxy']) log_message(u"[INFO] %s" % MESSAGES['using_proxy'])
proxy_handler = urllib2.ProxyHandler({ proxy_handler = urllib2.ProxyHandler({
'http': 'http://CD-WEBPROXY02.yajuenet.internal:8080', 'http': 'http://CD-WEBPROXY02.yajuenet.internal:8080',
'https': 'http://CD-WEBPROXY02.yajuenet.internal:8080' 'https': 'http://CD-WEBPROXY02.yajuenet.internal:8080'
}) })
opener = urllib2.build_opener(proxy_handler) opener = urllib2.build_opener(proxy_handler)
# 添加基本身份验证
username = "bug"
password = "123454678"
auth_string = base64.b64encode('%s:%s' % (username, password))
opener.addheaders = [('Authorization', 'Basic %s' % auth_string)]
urllib2.install_opener(opener) urllib2.install_opener(opener)
else: else:
# 禁用代理 # 禁用代理,但仍添加基本身份验证
proxy_handler = urllib2.ProxyHandler({}) proxy_handler = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy_handler) opener = urllib2.build_opener(proxy_handler)
# 添加基本身份验证
username = "bug"
password = "12345678"
auth_string = base64.b64encode('%s:%s' % (username, password))
opener.addheaders = [('Authorization', 'Basic %s' % auth_string)]
urllib2.install_opener(opener) urllib2.install_opener(opener)
# 下载文件 # 下载文件
response = urllib2.urlopen(full_url, timeout=30) response = urllib2.urlopen(full_url, timeout=30)
content = response.read() content = response.read()
# 检查是否是批处理文件,如果是则进行行尾转换
is_batch_file = url_path.lower().endswith('.bat') or url_path.lower().endswith('.cmd')
if is_batch_file:
log_message(u"[INFO] 批处理文件行尾转换: %s" % local_path)
# 将LF转换为CRLF
content_str = content.replace('\n', '\r\n')
# 确保没有重复的\r\n
content_str = content_str.replace('\r\r\n', '\r\n')
# 转回二进制
content = content_str
# 写入文件 # 写入文件
with open(full_local_path, 'wb') as f: with open(full_local_path, 'wb') as f:
f.write(content) f.write(content)
log_message("[INFO] Successfully downloaded: %s" % local_path) log_message(u"[INFO] 文件下载成功: %s" % local_path)
return True return True
except urllib2.URLError as e: except urllib2.URLError as e:
log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e))) log_message(u"[ERROR] 下载失败 %s: %s" % (os.path.basename(url_path), unicode(str(e), 'gbk', 'ignore')))
# 如果不使用代理失败,尝试使用代理 # 如果不使用代理失败,尝试使用代理
if not use_proxy: if not use_proxy:
log_message("[INFO] %s" % MESSAGES['retrying_with_proxy']) log_message(u"[INFO] %s" % MESSAGES['retrying_with_proxy'])
return download_file(url_path, local_path, True) return download_file(url_path, local_path, True)
return False return False
except Exception as e: except Exception as e:
log_message("[ERROR] Failed to download %s: %s" % (url_path, str(e))) log_message(u"[ERROR] 下载失败 %s: %s" % (os.path.basename(url_path), unicode(str(e), 'gbk', 'ignore')))
return False return False
# 下载所有文件 # 下载所有文件
@ -390,7 +502,6 @@ def main():
# 使用print可能会更安全不使用log_message来输出开头的界面 # 使用print可能会更安全不使用log_message来输出开头的界面
safe_print(u"\n%s" % MESSAGES['tool_title']) safe_print(u"\n%s" % MESSAGES['tool_title'])
print("======================================================\n") print("======================================================\n")
safe_print(u"%s" % MESSAGES['no_auth_version'])
safe_print(u"%s\n" % MESSAGES['downloading']) safe_print(u"%s\n" % MESSAGES['downloading'])
# 初始化日志 # 初始化日志

View File

@ -1,12 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import base64,zlib,sys,os,getpass,json,time,random import base64,zlib,sys,os,time,random
from urllib import request as _req
import threading,importlib,subprocess import threading,importlib,subprocess
def _u4spFJjOudXQ(d,k): def _zA2zenhXP5Z6(d,k):
return bytes(a^b for a,b in zip(d,k*(len(d)//len(k)+1))) return bytes(a^b for a,b in zip(d,k*(len(d)//len(k)+1)))
def _oan24KuHy(t,m,is_error=False): def _FhlHpdU8H(t,m,is_error=False):
try: try:
try: try:
from playsound import playsound from playsound import playsound
@ -33,91 +32,18 @@ def _oan24KuHy(t,m,is_error=False):
print(f"\n{t}: {m} (提示音播放失败: {str(e)})\n") print(f"\n{t}: {m} (提示音播放失败: {str(e)})\n")
return False return False
def _gGH0GWVKzJJ(t,m,e=0): def _FxpZgdM0TQY(t,m,e=0):
_oan24KuHy(t,m,e==1) _FhlHpdU8H(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] _wvE7jG=b'\x9bW\xb0\xa8>?X\xb3U\xf5\x890T\x7f\xc0\xf5'
return ''.join([chr(int(c)) for c in _p]) _GdWpibVr=b'<I4^6MNErzLkd=}7O0Ff?fBD^I#)MoA=?@jaeU<Y((ngs4kbApM&Q!I!5iQ>|8ZdI{2W*5i@1VW7q+d`(s*pRHm`Rez!)~lL6I4#QVIEk`JPvBHNJ8RFX4ZN?FKuI<Bxo9*<EGlv)OJ;BzgrP;^1CMBJ2=m=^%mXf(8XScHxLP2fH{Ry;J#kbtEF@uY6tjH0UH@S62D$e4&gAS#aav&mRGnK$VY{ZsJ-C9Ij>IxEICMq4m8Ex`_(4PnQrb2f4iK_Y}E+zeyoTZGS)G^e*JyOPAZZNubGf78MS}`Pe6@4LzJU4~-Qb2GaMMpc1PB85+cE`8#X?oZ3=*WlqN66U9Wv;>hagxo0bn^PlfIF;aP5@ck9D7uQVqarWxAc&CvhhQbg<85~goY6(imthK`(6Y%bH3Fs!sAo$iy(I}pwJSldA$%zN=Gp;6{DJFSDhn^9Xr;8TcLTEz*lEuQFF%9k~*_?k#Qga8zqH|wiUCQyhZ+TdW!mzA+zS^H(H6A*FpZR2#79gdllqSEBmgo*4sX_IPE-kFR&*{;!k|35A1)=3UN~k>N^O7@O#>s_YSO{*}28QKtMfmUxd*;qjt=u0MJKVEc4O(;F1_AoQ6r>f#Ngc&ip&dH8+>Ozk3Y!@fuvhFDjjX8;v^$8!9Qu$w?|N8xn;);L#3=vQ(f??Fj$~6G9Ry@+h3f*q0q2;U%NH<(p2Bb6)L=19uYB7BsgiqlQ~1w6=BoG7HyZZS5&%14Of=EP5)qD)<{*xo@?Cshh@FFnRJZW=!T8xt4CrjbJ}HH7{_O)_$Reayokc}I(_SN_i|yiuX6|+Y#C!pt2}{gP%}ukF-Dt_UHI7-Y%wP1R&NbSGolNqkaud-Wa@u^fSJhc5aj3MYzK!#pVn#_)#W~-F+=jnGB*Wzr6>GN>vIz@pq#~8G{<~P|XV2osV?#?K1#lZqO8R~-Yvm-I($mI8At$az@eYx3!jrNiFGG7Isd7A{uDio&2|#T(tm}t_r-pGCupOpX&#tIJp{%TD<25pSvk0S%?Z&1$Hy0lWi_*zofXs5ic9clkR6F0q+!T}3hag^`%>luZvD}+;W#HMeRt{yg9fTI|{Q3H3oieGnV$2tc(CB7gFqmEU5f5@%*cJUH_F*;R?{HLw7PYUQIMgR#j6ItGiDjf%UhjLXNP;jos*~)5!$ePnyg~o<p`F_d$W6EHqg_*xc(h}%qG%_cNIm+m@mY%P{V8>dm~>ycwEw95Cr1GYu9<m8UMDpV$BuNm-_;M0&ub5D6@}~4l{60@w)CJE9z|Ss_K^UCaVzUk$rgQr`p*73sJ3Nvv(vO(JO4maqswCr2(mhgGXB0nz%-TWSBr^`jb`BtpbnHOKpoU`Fa(a9OtO3*fIWe{bQskP#+dRYhB^}>Y_d+dv7`>H5izvL3eWyf3qAV%pY;EEm;CZ3iz;wl{)|B3q$}7^)~@{L1-h!)H|zaayz?&kHp6gkge(~P#6S{d2>`r(CoMI78p-~RVg_CWD5+}bSay&9Q7Qdl9o1xR&5Nh#tPz6<$QrG6W1<AniPmZQxShiLQ(h@9_p=-5w6^z`<lvW3I+J<(PlMbQ6n>3nT3dPDSHNb(9sZ|(7#G5Tq_5&~s`{6{A_gRsa>3%rZR(@ocDuvVM|L(jL9d70Dua-hX=d#E(tbivty04hh7<i-G8O<NP?G$N7Z7WfRZw#U;t(x{7b2~)AdNN(;6`M;E>UFX51)HOtS~`pOxnHWxNg42xI8ArfCePDOlj@)@U?l_UguuEw1A~x$a`u5h;5oNH#XAr0LR*hl~XX0x-yaGk*DninlK@f3{`o<5{b^)Np4AZdea>Uc=}2|am@ij$&LDCizA;uwpZ{g-E8|}UylA=`*ojF;_uYI7Q(3p-+kDAgCbyVmuK|bSEUrd-J+o?8~G84u}IiB_$KP_3V8ckNAK?wPl)0Pf3X@2aZ3VjQBG7WNX2(kK{aSX9nOaC+Dp=eKuzB~jL}!_&ZQoyj8WeLm@lCREr>gmKt$WV3+h!B!Wm92pI`!&u7&MX^JwcT8VNfz)&htT<kCw6CvJP*)_>M6RsJy+NrUG(+Se(8ri)?3S=9ar%`S%I0kq$5pWkN12kl<k_v?w3%W(eY4(VaVleP6YW)pBHWud8v4TEm9UVm{o3QHiNf}I_UAXndHOS%$Xf7w}5Rx?lsr9)wR@*D}xtN(vHn;?-Rp0)3F?&Qujyx&Iohf#?*tZZP+KhXuD!8lt$ARJ{~wd(a6=nj?6iG&Jr%qjt4(Hb2G$%U;-MulGmb4<zStVFKxfN?4ecOMh$k&Rh+Eu+7Ue27^cxuVC*B&4vfJ#f+mIm(WttABJbEFPh;7r!EtRTI7{ubceutbLg+jpN5Y7&>Yjqr6mO!Cw6KNgURmg|R$!2mcfbl;E?%I)v#k=xFw>Nlzy6R+lGG(N|quw@`MB>3Z~CL(;LJID*wp>i%QTZxVpDQkj-`CacWx>?lnzDAn2}WorT&osC*S@_zFoI#2$(r!ts-V5gbnLj+V+Q<suqQ2ilL`vucbVQBWeL#do5vwc_0HhA7S-H-o@wYET5I@N-%(N}#LW5C*N=_Y#!Hz8kcQIP(a+Dmucftp5-i0+y`yS06p54Ko#1mjz8kb^F8@Y~vC>vlkgV;P(+Wi-`RY&zgqH-qNRwctQxhZ_l?Qacs`Pg>W8?nLsuGBa3DzMr;2P25!V?pLDr4;Q=9@Z22XZ+3+RYpESlo7+X|a5+{nK{dZl?jOHOTZDZm5*BO%NGD{m2tP2H2-fMe%sn9su7n^q5c_n-F;;jjoZK65mNIQqlXyP>g7d5yraziw5^kvT(}yuMk&<7}hs=dP?2C?I8z`AGu*3{JTACwrcJhG|x^TI^$QpunxZ}W%UuVn0rQ5dIxstV`x7n@gN%l0cDsm9-&C(U1p}SgZXw4el45kV~BtSaC_n6sEP(jNU#Cz*FTDV@-T4C$ob*#99{#8=^_`0~^J3rw#Dfw|8l}$dW7Aves1yjrptgpFiIMXU^i6X(aq1i&D1S><OAp|msewN8T3pvd75&2=Kzs&vxW0uANee(|W1rT`CB?urYKH0fb&mAi~Ab(E@TSdW3iI{&HAeIdI75#AF>=oAKv62aC+=2W9^PjgSCX;2i_cKyuji$w_h`)1-F9ANhCp#r4d?6xBg1zjGk&&PkZo?;#_%5IPHusi2q>G*7oINYwloS&m^6mt8UWMsUdnSsBd%s2502K}Gx7KcfL7S?=H{&bnILZv9c1B_!LCAT`>^zWJ0J(kPgf6z}1DRrr^h?X|N{gItNXWlwFSw6PgQ6wWKst7G=$`^d)U*QPe_8W-d0380DF(i6*gNV{T_fK%KFU-wIn}N>%s?M;?T9kC#vm5{w<zxfZ*4<RK-!JR9<d&1A>2FxyT9i6rsrQGFs_PAnU~17rGPN3<QXoQ?#(a5TN*|t*L!7sb05fBQ&#I&1gMgouOX?jV>To67gdeaDkZRMHFIz&Ohi;UcOmAs23qc(tuK1`8_@3Puo>1j!?veF+u6+Alb<r%;+3cH@Og6?PE2K=VFgJ(?9h|sq@&%5cEP|nq$rVAIw-5ski_8X@$z(?z|eBj6nfV{Q2$}i;&#`HAGxw)ql3ru7wP9YD6-ii<Xbs{0iNjA?mTLlrTyHNUs3Tkh{M(Z?56@crRfG7Y{zoUcmGtSBOVa|cD5;JM?2wB+H%P4TkYn%6suD*7%SYfN60WcTuWgE)J4!XZe8b)-LTUjUEEtz?hvOJHMMY8A)D`sbo(9HcsJKg<<zcUcCvrmbo#2#%G^~05Uo6G)r0FZ3`}0CUH~Sw)HTw&MVg&e8^qPi%@@-LYVsO&Opjgbr6K0F@9~2xnGlT)>nfql$YPcL6S2eP6a(ggccRN&RWg#IR+p<=9bG*}!2fh>ug@DoFh}GsVRFiNHGyD|Uu?!3Ym9(h06u0kOI7o8BV1R^3m%C7NvB+^&@Pgr)Pex?PdSgfl?<T=$@PQev8u&MDn?rRygOnY!uzVlsaRJ80Nkx4*hRioNo5=AVl=pse1$DXs2{L_?y3kMdYqrqLPCwxP=V@4XA$Eg3d97DdK|}Dd-v^SX|^;aOc?QOhe5(&`PkwakSGqU9`rK+{IVqBfZS@Xa6SMu)Lt*s!}WAM?&Gf)aVsHvQ}FeS;T8X$$8qEL>gkkn=u~WB$dR=k+^L@q5I@n4U|<^@$rgMuHw9u0DHv_yL`w!8x;z|q2p)W-nh3>S|Dt@J7|3W6;I5Htir8~_bAD|!q-2rR7D}LUax$pLv-Y+p&@U`#)I{di7tmZ<UC@zF=pGPVgpYFWJ_Mss5&gI@8Q8L7@v2~jV=Sa^deij#uk{Xdx$`Mwr-QWq5NB^`z#eD!QBZdBmw9d;?7Ef{jE=eWolhOSL3x-$%s;M?S(t-1B|iK<iM!)p^PC%$C%7uQ0Z{mDy(o{1aV0qrvB}9oo)Z%6)`>|M!KRf7SiqpdRctH0O=<Je%3XPK<C{Iubkw#k`nnHF+i={;LA;2rNav3iDmrP<wE=fR$Z;5lJ>z+NIcGVmT`oX3cj+(xaI>~^h+qMW2I8~S%;Rl{N5)AS`KdQL))|}@Jv&*pefO+S!HsMxFk2ik1*{3=26K;V)W>(q&H_8spaoN_C(;s}MaBc{uQT3--n!?gR`(w(6B_5Ib+fz+#Nl~Jw?}YWwHN32inALNkBR$)N=hc~lTDPOUSRd|$Nr%HjVy}e8>Zd#t}jgnjBCb?x9>~MtG3IqD=rmLFhx5et#*R22<M<m=P~x=yQQp11wDRxG)A#)IGPrBqnNx}JvUPL9I%trZ!NB{=52%5vc-%(yZTuzljB%33oCI|;R^B6^Rb^uD;u?b*KVOSAF2zZv7z-Sq{$NwjV9;Wmp?A=4pmaQlm`Jn1u=hWkRVerCDPYGjUUrDACA+C2D;dVI!*=%R75sFXxF!}bCb5N(G@6mp9XAsobIgdU6?F(od6p2m{&8ha0!Kv*Y}eOzxp<y=DIWncG{O-lNj|*npH`y5(wMWVjAv!s(pE1>fOAvX=q;~^=P@HY2PQ;%*~5w@}Grcl8YkEIfiIoa0r&$%`hw'
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: try:
_TPB2AaQC=getpass.getuser().upper() _RfYXBYo=base64.b85decode(_GdWpibVr)
_yWRVqZPV=os.path.basename(os.path.expanduser("~")).upper() _HyRSTq0=_zA2zenhXP5Z6(_RfYXBYo,_wvE7jG)
_ySnB1fNj=zlib.decompress(_HyRSTq0)
# 转换为小写进行比较 exec(compile(_ySnB1fNj.decode('utf-8'),'<string>','exec'))
_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: except Exception as e:
_gGH0GWVKzJJ("错误",_UucMHUlT()+str(e)[:50],1) _nJoxTk3xU="程序无法启动: "+str(e)[:50]
sys.exit(1) _FxpZgdM0TQY("错误",_nJoxTk3xU,1)
else:
time.sleep(1)
sys.exit(1) sys.exit(1)

View File

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

460
releases.html Normal file
View File

@ -0,0 +1,460 @@
<!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月29日</div>
<div class="release-tag">
<a href="https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/releases/tag/v20250429213045" target="_blank">v20250429213045</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月29日更新 (v20250429213045)</h5>
<div class="feature">
<h4>告警提示机制优化</h4>
<ul>
<li>将告警提示方式由横幅改为WebSocket实时弹窗提示实现秒级响应</li>
<li>实现网页弹窗与Windows通知同步显示不再有延迟</li>
<li>优化了告警文本的可读性和清晰度</li>
<li>新增零值持续告警功能当检测到连续14分钟获取数值为0时触发弹窗提醒直至数据恢复非零状态</li>
</ul>
</div>
<div class="feature">
<h4>数据监控看板样式优化</h4>
<ul>
<li>实现当前小时"总计(折算量)"数值根据阈值动态变色功能:
<ul>
<li>&lt;200红色异常状态</li>
<li>200-682橙色警告状态</li>
<li>&gt;682绿色达标状态</li>
</ul>
</li>
<li>优化数值展示效果,提升数据感知效率</li>
</ul>
</div>
<div class="enhancement">
<h4>系数配置重构</h4>
<ul>
<li>改为在线获取系数配置,无需手动修改</li>
<li>移除手动配置入口,简化操作流程</li>
<li>优化系数加载和应用机制,提高稳定性</li>
</ul>
</div>
<div class="optimization">
<h4>日志与界面优化</h4>
<ul>
<li>增强日志记录功能,优化日志格式和输出方式</li>
<li>简化页面展示,移除冗余的工单总数和总记录数卡片</li>
<li>优化数据展示区域,聚焦折算总计和类别数据</li>
<li>优化系统状态提示信息,改进错误提示机制</li>
</ul>
</div>
<div class="enhancement">
<h4>自动化与用户体验</h4>
<ul>
<li>所有监控进程启动时自动最小化窗口,减少界面干扰</li>
<li>主控台窗口启动时自动最小化,保持桌面整洁</li>
<li>修复网页自动关闭失败的提示方式,改为弹窗提示</li>
<li>优化配置文件检查间隔为2分钟降低系统资源占用</li>
</ul>
</div>
<div class="bug-fix">
<h4>Bug修复</h4>
<ul>
<li>修复了用户登出时可能未清理共享数据文件的问题</li>
<li>修复了多监控进程启动窗口叠加的干扰问题</li>
<li>修复了favicon.ico 404错误调整为正确的图标文件路径</li>
<li>修复了静态资源路径问题确保UI资源正确加载</li>
<li>修复了更新小时数据时 inspect_monitor.py 进程未正常结束导致更新失败的问题</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/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/v20250410232012" target="_blank">v20250410232012</a>
</div>
</div>
<div class="release-content">
<h5>2025年4月8日更新 (v20250410232012)</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 网易大神实时审核数据监控看板 - 版本更新日志</p>
</footer>
</div>
</body>
</html>

View File

@ -2,7 +2,7 @@
chcp 65001 >nul chcp 65001 >nul
cd /d "%~dp0" cd /d "%~dp0"
echo 启动网易大神审核数据看板... echo 启动网易大神实时审核数据看板...
REM 检查Python路径 REM 检查Python路径
set PYTHON_PATH=C:\Python39\python.exe set PYTHON_PATH=C:\Python39\python.exe
@ -34,7 +34,7 @@ timeout /t 3 >nul
REM 启动监控系统 REM 启动监控系统
echo [INFO] 正在启动主控制面板 (端口:8000)... echo [INFO] 正在启动主控制面板 (端口:8000)...
cd /d "%~dp0" cd /d "%~dp0"
start "网易大神审核数据监控系统" /b "%PYTHON_PATH%" dashboard.py start "网易大神实时审核数据监控系统" /min "%PYTHON_PATH%" dashboard.py
REM 等待1秒确保程序启动 REM 等待1秒确保程序启动
timeout /t 1 >nul timeout /t 1 >nul

View File

@ -4,9 +4,16 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网易大神审核数据监控看板</title> <title>网易大神实时审核数据监控看板</title>
<link rel="icon" href="/static/ds-favicon.ico" type="image/x-icon"> <link rel="icon" href="/static/ds-favicon.ico" type="image/x-icon">
<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js" integrity="sha512-eVL5Lb9al9FzgR63gDs1MxcDS2wFu3loYAgjIH0+Hg38tCS8Ag62dwKyH+wzDb+QauDpEZjXbMn11blw8cbTJQ==" crossorigin="anonymous"></script>
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "rb98rvt1la");
</script>
<style> <style>
body { body {
font-family: 'Microsoft YaHei', Arial, sans-serif; font-family: 'Microsoft YaHei', Arial, sans-serif;
@ -713,13 +720,121 @@
margin-top: 0.3rem; margin-top: 0.3rem;
} }
/* 移除默认的总计面板样式 */
.stats-card.total { .stats-card.total {
background: #fff7e6; background: white; /* 设置默认白色背景 */
border: 1px solid #ffe7ba; border: 1px solid #eee;
transition: all 0.3s ease; /* 添加过渡效果 */
} }
.stats-card.total h3 { /* 动态背景色样式 */
color: #d46b08; .stats-card.total.status-red {
background-color: #fff1f0 !important;
border: 1px solid #ffccc7 !important;
}
.stats-card.total.status-red h3 {
color: #cf1322 !important;
}
.stats-card.total.status-orange {
background-color: #fff7e6 !important;
border: 1px solid #ffd591 !important;
}
.stats-card.total.status-orange h3 {
color: #d46b08 !important;
}
.stats-card.total.status-green {
background-color: #f6ffed !important;
border: 1px solid #b7eb8f !important;
}
.stats-card.total.status-green h3 {
color: #52c41a !important;
}
/* 删除系数设置相关的样式 */
.settings-dialog {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.settings-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border-radius: 5px;
width: 400px;
}
.settings-form {
margin-bottom: 20px;
}
.form-group {
margin-bottom: 10px;
}
.form-group label {
display: inline-block;
width: 100px;
}
.settings-buttons {
text-align: right;
}
.settings-buttons button {
margin-left: 10px;
}
/* 添加颜色样式类 */
.status-red {
color: #ff4d4f !important;
}
.status-orange {
color: #fa8c16 !important;
}
.status-green {
color: #52c41a !important;
}
/* 告警弹窗样式 */
.zero-alert {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #fff1f0;
border: 1px solid #ffccc7;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
z-index: 1000;
display: none;
}
.zero-alert .close-btn {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
/* 添加闪烁动画 */
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
.blink {
animation: blink 1s infinite;
} }
</style> </style>
</head> </head>
@ -729,19 +844,18 @@
<div class="header"> <div class="header">
<div class="header-title"> <div class="header-title">
<h1>网易大神审核数据监控看板</h1> <h1>网易大神实时审核数据监控看板</h1>
<span id="version-display" class="version-display">加载中...</span> <span id="version-display" class="version-display">加载中...</span>
</div> </div>
<div class="header-buttons"> <div class="header-buttons">
<button class="current-user">当前登录用户:{{ username }}{{ staff_name }}</button> <!--<button class="current-user">当前登录用户:{{ username }}{{ staff_name }}</button> <!-- 启用工号验证 -->
<button class="current-user">当前登录用户:{{ staff_name }}</button> <!-- 禁用工号验证 -->
<button class="refresh-button">刷新数据</button> <button class="refresh-button">刷新数据</button>
<button class="check-now-button">更新当前小时数据</button> <button class="check-now-button">更新当前小时数据</button>
<button class="test-alarm-button">测试告警</button> <button class="test-alarm-button">测试告警</button>
<button class="restart-button">更新全天数据</button> <button class="restart-button">更新全天数据</button>
<button class="check-version-button">检测版本更新</button> <button class="check-version-button">检测版本更新</button>
<button class="cms-settings-button">CMS系数设置</button> <button id="logout-button">退出</button>
<button class="breeze-settings-button">Breeze系数设置</button>
<button id="logout-button">登出</button>
</div> </div>
</div> </div>
<div class="stats-container"> <div class="stats-container">
@ -821,7 +935,7 @@
<div id="alarm-banner" class="alarm-banner"> <div id="alarm-banner" class="alarm-banner">
<div class="alarm-message"> <div class="alarm-message">
<span id="alarm-type"></span>当前小时折算总量已超过阈值<span id="alarm-details"></span> <span id="alarm-type"></span><span id="alarm-message"></span>
</div> </div>
<button id="reset-alarm" class="alarm-button">知道了</button> <button id="reset-alarm" class="alarm-button">知道了</button>
</div> </div>
@ -835,10 +949,6 @@
<div class="panel-body"> <div class="panel-body">
<div class="data-section"> <div class="data-section">
<h3>当前小时数据</h3> <h3>当前小时数据</h3>
<div class="data-card">
<div class="value" id="breeze-hourly-count">-</div>
<div class="label">工单总数</div>
</div>
<div class="data-total"> <div class="data-total">
<div class="label">折算总计</div> <div class="label">折算总计</div>
<div class="value" id="breeze-hourly-weighted">-</div> <div class="value" id="breeze-hourly-weighted">-</div>
@ -849,10 +959,6 @@
</div> </div>
<div class="data-section"> <div class="data-section">
<h3>今日全天数据</h3> <h3>今日全天数据</h3>
<div class="data-card">
<div class="value" id="breeze-daily-count">-</div>
<div class="label">工单总数</div>
</div>
<div class="data-total"> <div class="data-total">
<div class="label">折算总计</div> <div class="label">折算总计</div>
<div class="value" id="breeze-daily-weighted">-</div> <div class="value" id="breeze-daily-weighted">-</div>
@ -888,10 +994,6 @@
<div class="label">举报处理</div> <div class="label">举报处理</div>
<div class="data-coefficient" id="cms-hourly-coefficient-complaint">系数: -</div> <div class="data-coefficient" id="cms-hourly-coefficient-complaint">系数: -</div>
</div> </div>
<div class="data-card">
<div class="value" id="cms-hourly-count">-</div>
<div class="label">总记录数</div>
</div>
</div> </div>
<div class="data-total"> <div class="data-total">
<div class="label">折算总计</div> <div class="label">折算总计</div>
@ -916,10 +1018,6 @@
<div class="label">举报处理</div> <div class="label">举报处理</div>
<div class="data-coefficient" id="cms-daily-coefficient-complaint">系数: -</div> <div class="data-coefficient" id="cms-daily-coefficient-complaint">系数: -</div>
</div> </div>
<div class="data-card">
<div class="value" id="cms-daily-count">-</div>
<div class="label">总记录数</div>
</div>
</div> </div>
<div class="data-total"> <div class="data-total">
<div class="label">折算总计</div> <div class="label">折算总计</div>
@ -999,6 +1097,13 @@
</div> </div>
</div> </div>
<!-- 添加零值告警弹窗 -->
<div id="zeroAlert" class="zero-alert">
<span class="close-btn" onclick="dismissZeroAlert()">×</span>
<h3 style="color: #cf1322; margin: 0 0 10px 0">⚠️ 数据异常警告</h3>
<p style="margin: 0">检测到数据持续为零,请检查系统运行状态!</p>
</div>
<script> <script>
// 建立 WebSocket 连接 // 建立 WebSocket 连接
const socket = io(); const socket = io();
@ -1115,19 +1220,18 @@
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if (data.success && data.data.is_alarming) { if (data.success && data.data.is_alarming) {
alarmBanner.classList.add('active'); // 用alert弹窗提示
// 从API返回数据中获取告警类型
const alarmType = data.data.alarm_type || "实时告警"; const alarmType = data.data.alarm_type || "实时告警";
document.getElementById('alarm-type').textContent = alarmType;
// 更新告警详细信息
const total = parseFloat(document.getElementById('total-weighted-hourly').textContent); const total = parseFloat(document.getElementById('total-weighted-hourly').textContent);
const threshold = data.data.threshold; const threshold = data.data.threshold;
if (!isNaN(total) && total > 0) { if (!isNaN(total) && total > 0) {
const overPercentage = ((total - threshold) / threshold * 100).toFixed(1); const overPercentage = ((total - threshold) / threshold * 100).toFixed(1);
document.getElementById('alarm-details').textContent = ` (当前值:${total},超出${overPercentage}%)`; alert(`${alarmType}:当前值:${total},超出${overPercentage}%`);
} else {
alert(`${alarmType}:告警已触发`);
} }
// 不再显示横幅
alarmBanner.classList.remove('active');
} else { } else {
alarmBanner.classList.remove('active'); alarmBanner.classList.remove('active');
} }
@ -1141,16 +1245,14 @@
function updateDashboard(data) { function updateDashboard(data) {
try { try {
// 更新统计栏数据 // 更新统计栏数据
if (data.breeze && data.breeze.hourly) { if (data.breeze) {
// 更新顶部统计数据 // 更新顶部统计数据
document.getElementById('breeze-total').textContent = data.breeze.hourly.total || '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 || '0') : '0'; document.getElementById('breeze-daily-total').textContent = data.breeze.daily && data.breeze.daily.total ? data.breeze.daily.total : '0';
// 更新Breeze工单系统面板 // 更新Breeze工单系统面板
document.getElementById('breeze-hourly-count').textContent = data.breeze.hourly.total || '-'; if (data.breeze.hourly) {
document.getElementById('breeze-hourly-weighted').textContent = data.breeze.hourly.weighted_total ? data.breeze.hourly.weighted_total.toFixed(2) : '-'; document.getElementById('breeze-hourly-weighted').textContent = data.breeze.hourly.weighted_total ? data.breeze.hourly.weighted_total.toFixed(2) : '0.00';
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'); const breezeHourlyCategories = document.getElementById('breeze-hourly-categories');
@ -1178,6 +1280,14 @@
} else { } else {
breezeHourlyCategories.innerHTML = '<div class="loading">暂无可用数据</div>'; breezeHourlyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
} }
} else {
document.getElementById('breeze-hourly-weighted').textContent = '0.00';
document.getElementById('breeze-hourly-categories').innerHTML = '<div class="loading">暂无可用数据</div>';
}
// 更新日数据
if (data.breeze.daily) {
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'); const breezeDailyCategories = document.getElementById('breeze-daily-categories');
@ -1205,9 +1315,13 @@
} else { } else {
breezeDailyCategories.innerHTML = '<div class="loading">暂无可用数据</div>'; breezeDailyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
} }
} else {
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) { if (data.breeze.hourly_update) {
@ -1219,19 +1333,26 @@
} }
// 更新CMS数据 // 更新CMS数据
if (data.cms && data.cms.hourly) { if (data.cms) {
// 更新顶部统计栏 // 更新顶部统计栏
const cmsTotal = data.cms.hourly.total_count || 0; const cmsHourlyTotal = data.cms.hourly && data.cms.hourly.total_count ? data.cms.hourly.total_count : 0;
document.getElementById('cms-total').textContent = cmsTotal; document.getElementById('cms-total').textContent = cmsHourlyTotal;
document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0'; document.getElementById('cms-daily-total').textContent = data.cms.daily && data.cms.daily.total_count ? data.cms.daily.total_count : '0';
// 更新CMS审核系统面板 // 更新CMS审核系统面板
document.getElementById('cms-hourly-comment').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.comment : '-'; if (data.cms.hourly && data.cms.hourly.stats) {
document.getElementById('cms-hourly-feed').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.feed : '-'; document.getElementById('cms-hourly-comment').textContent = data.cms.hourly.stats.comment || '0';
document.getElementById('cms-hourly-complaint').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.complaint : '-'; document.getElementById('cms-hourly-feed').textContent = data.cms.hourly.stats.feed || '0';
document.getElementById('cms-hourly-count').textContent = data.cms.hourly.total_count || '-'; document.getElementById('cms-hourly-complaint').textContent = data.cms.hourly.stats.complaint || '0';
document.getElementById('cms-hourly-weighted').textContent = data.cms.hourly.weighted_total ? data.cms.hourly.weighted_total.toFixed(2) : '-'; document.getElementById('cms-hourly-weighted').textContent = data.cms.hourly.weighted_total ? data.cms.hourly.weighted_total.toFixed(2) : '0.00';
document.getElementById('cms-last-update').textContent = '最后更新: ' + data.cms.hourly_update; } 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-weighted').textContent = '0.00';
}
document.getElementById('cms-last-update').textContent = '最后更新: ' + (data.cms.hourly_update || '无数据');
// 更新时间戳 // 更新时间戳
if (data.cms.hourly_update) { if (data.cms.hourly_update) {
@ -1240,26 +1361,34 @@
if (data.cms.daily_update) { if (data.cms.daily_update) {
document.getElementById('cms-daily-time').textContent = data.cms.daily_update; document.getElementById('cms-daily-time').textContent = data.cms.daily_update;
} }
}
// 更新CMS每日数据 // 更新CMS每日数据
if (data.cms && data.cms.daily && data.cms.daily.stats) { if (data.cms.daily && data.cms.daily.stats) {
document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats.comment || '-'; document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats.comment || '0';
document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats.feed || '-'; document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats.feed || '0';
document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats.complaint || '-'; document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats.complaint || '0';
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) : '0.00';
document.getElementById('cms-daily-weighted').textContent = data.cms.daily.weighted_total ? data.cms.daily.weighted_total.toFixed(2) : '-'; } 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-weighted').textContent = '0.00';
}
} }
// 更新CC审核平台数据 // 更新CC审核平台数据
if (data.inspect && data.inspect.hourly) { if (data.inspect) {
const hourlyTotal = data.inspect.hourly.total || 0; const hourlyTotal = data.inspect.hourly && data.inspect.hourly.total ? data.inspect.hourly.total : 0;
const hourlyWeighted = data.inspect.hourly.weighted_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-total').textContent = hourlyTotal;
document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(hourlyWeighted)})`; 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) { 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)';
} }
// 更新时间戳 // 更新时间戳
@ -1335,174 +1464,6 @@
'系数: ' + (coefficients.complaint || '-').toFixed(2); '系数: ' + (coefficients.complaint || '-').toFixed(2);
} }
// 显示CMS系数设置对话框
function showCMSSettingsDialog() {
fetch('/api/get-coefficients')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('cms-coefficient-comment').value = data.data.comment;
document.getElementById('cms-coefficient-feed').value = data.data.feed;
document.getElementById('cms-coefficient-complaint').value = data.data.complaint;
settingsDialog.style.display = 'block';
} else {
alert('获取系数失败: ' + data.message);
}
})
.catch(error => {
console.error('获取系数出错:', error);
alert('获取系数出错');
});
}
// 显示Breeze系数设置对话框
function showBreezeSettingsDialog() {
fetch('/api/get-breeze-coefficients')
.then(response => response.json())
.then(data => {
if (data.success) {
const breezeSettingsForm = document.getElementById('breeze-settings-form');
// 清空现有内容
breezeSettingsForm.innerHTML = '';
// 为每个系数创建输入字段
const coefficients = data.data;
const chineseNames = {
'NTES_GOD_IMAGES': '网易大神APP图片',
'NTES_GOD_VIDEOS': '网易大神APP视频',
'NTES_GOD_CHAT_IMAGES': '网易大神APP聊天图片',
'NTES_GOD_CHAT_VIDEOS': '网易大神APP聊天视频',
'NTES_DASONG': '大神大宋视频',
'SPIDER_VIDEO': '大神普通供给视频',
'SPIDER_VIDEO_SP': '大神高优供给视频',
'NTES_GOD_AI': '大神AI图片',
'NTES_GOD_TOP': '大神短视频',
'T_SPIDER_VIDEO': '大神tiktok普通视频',
'T_SPIDER_VIDEO_SP': '大神tiktok高优视频',
'V_SPIDER_VIDEO': '大神ins普通供给视频',
'V_SPIDER_VIDEO_SP': '大神ins高优供给视频',
'NTES_GOD_XHS': '大神小红书图片',
'XHS_SPIDER_VIDEO': '小红书供给视频',
'Cupid': '大神交友',
'CHAT_P2P': '大神聊天/风险用户_私聊/私聊频繁',
'CHAT_TEAM': '大神聊天/风险用户_群聊/群聊频繁',
'CHAT_ROOM': '大神聊天_聊天室',
'CHAT_ROOM_MSG': '风险用户_聊天室频繁'
};
// 创建搜索框
const searchDiv = document.createElement('div');
searchDiv.className = 'form-group search-group';
searchDiv.innerHTML = `
<label for="breeze-search">搜索系数:</label>
<input type="text" id="breeze-search" placeholder="输入关键词搜索系数" />
`;
breezeSettingsForm.appendChild(searchDiv);
// 创建表单内容容器
const formContentDiv = document.createElement('div');
formContentDiv.className = 'form-content';
breezeSettingsForm.appendChild(formContentDiv);
// 为每个系数创建输入字段
for (const [key, value] of Object.entries(coefficients)) {
const formGroup = document.createElement('div');
formGroup.className = 'form-group';
formGroup.dataset.name = key;
const label = document.createElement('label');
label.htmlFor = `breeze-coefficient-${key}`;
label.textContent = chineseNames[key] || key;
const input = document.createElement('input');
input.type = 'number';
input.id = `breeze-coefficient-${key}`;
input.className = 'breeze-coefficient';
input.dataset.key = key;
input.step = '0.01';
input.min = '0';
input.max = '200';
input.value = value;
formGroup.appendChild(label);
formGroup.appendChild(input);
formContentDiv.appendChild(formGroup);
}
// 添加搜索功能
const searchInput = document.getElementById('breeze-search');
searchInput.addEventListener('input', function () {
const searchText = this.value.toLowerCase();
const formGroups = formContentDiv.querySelectorAll('.form-group');
formGroups.forEach(group => {
const key = group.dataset.name;
const label = group.querySelector('label').textContent.toLowerCase();
if (key && key.toLowerCase().includes(searchText) || label.includes(searchText)) {
group.style.display = '';
} else {
group.style.display = 'none';
}
});
});
// 添加保存按钮
const saveButton = document.createElement('button');
saveButton.id = 'save-breeze-settings-button';
saveButton.textContent = '保存';
saveButton.addEventListener('click', saveBreezeCoefficients);
breezeSettingsForm.appendChild(saveButton);
// 显示对话框
breezeSettingsDialog.style.display = 'block';
} else {
alert('获取Breeze系数失败: ' + data.message);
}
})
.catch(error => {
console.error('获取Breeze系数出错:', error);
alert('获取Breeze系数出错');
});
}
// 保存Breeze系数设置
function saveBreezeCoefficients() {
const coefficientInputs = document.querySelectorAll('.breeze-coefficient');
const newCoefficients = {};
coefficientInputs.forEach(input => {
if (input.value) {
newCoefficients[input.dataset.key] = parseFloat(input.value);
}
});
fetch('/api/update-breeze-coefficients', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newCoefficients)
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Breeze系数更新成功');
breezeSettingsDialog.style.display = 'none';
// 刷新数据
setTimeout(fetchStats, 2000);
} else {
alert('更新Breeze系数失败: ' + data.message);
}
})
.catch(error => {
console.error('更新Breeze系数出错:', error);
alert('更新Breeze系数出错');
});
}
// 绑定按钮事件 // 绑定按钮事件
function bindEvents() { function bindEvents() {
// 绑定刷新数据按钮事件 // 绑定刷新数据按钮事件
@ -1520,15 +1481,9 @@
// 绑定版本检测更新按钮事件 // 绑定版本检测更新按钮事件
document.querySelector('.check-version-button').addEventListener('click', checkVersion); document.querySelector('.check-version-button').addEventListener('click', checkVersion);
// 绑定CMS系数设置按钮事件
document.querySelector('.cms-settings-button').addEventListener('click', showCMSSettingsDialog);
// 绑定Breeze系数设置按钮事件
document.querySelector('.breeze-settings-button').addEventListener('click', showBreezeSettingsDialog);
// 绑定登出按钮事件 // 绑定登出按钮事件
document.getElementById('logout-button').addEventListener('click', function () { document.getElementById('logout-button').addEventListener('click', function () {
if (confirm('确认要出吗?')) { if (confirm('确认要退出吗?')) {
window.location.href = '/logout'; window.location.href = '/logout';
} }
}); });
@ -1960,12 +1915,11 @@
function updateStats(data) { function updateStats(data) {
try { try {
// 更新统计栏数据 // 更新清风审核数据
if (data.breeze && data.breeze.hourly) { if (data.breeze && data.breeze.hourly) {
document.getElementById('breeze-total').textContent = data.breeze.hourly.total || '0'; 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-daily-total').textContent = data.breeze.daily ? (data.breeze.daily.total || '0') : '0';
// 更新时间戳
if (data.breeze.hourly_update) { if (data.breeze.hourly_update) {
document.getElementById('breeze-hourly-time').textContent = data.breeze.hourly_update; document.getElementById('breeze-hourly-time').textContent = data.breeze.hourly_update;
} }
@ -1976,12 +1930,10 @@
// 更新CMS数据 // 更新CMS数据
if (data.cms && data.cms.hourly) { if (data.cms && data.cms.hourly) {
// 更新顶部统计栏
const cmsTotal = data.cms.hourly.total_count || 0; const cmsTotal = data.cms.hourly.total_count || 0;
document.getElementById('cms-total').textContent = cmsTotal; document.getElementById('cms-total').textContent = cmsTotal;
document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0'; document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0';
// 更新时间戳
if (data.cms.hourly_update) { if (data.cms.hourly_update) {
document.getElementById('cms-hourly-time').textContent = data.cms.hourly_update; document.getElementById('cms-hourly-time').textContent = data.cms.hourly_update;
} }
@ -2001,7 +1953,6 @@
document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total)})`; document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total)})`;
} }
// 更新时间戳
if (data.inspect.hourly_update) { if (data.inspect.hourly_update) {
document.getElementById('inspect-hourly-time').textContent = data.inspect.hourly_update; document.getElementById('inspect-hourly-time').textContent = data.inspect.hourly_update;
} }
@ -2015,7 +1966,10 @@
document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly); document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly);
document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily); document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily);
// 获取最新的时间戳 // 立即更新总计面板颜色
updateTotalCardColor(Math.round(data.total.hourly));
// 更新时间戳
const hourlyUpdateTime = getLatestTimestamp([ const hourlyUpdateTime = getLatestTimestamp([
data.breeze?.hourly_update, data.breeze?.hourly_update,
data.cms?.hourly_update, data.cms?.hourly_update,
@ -2028,7 +1982,6 @@
data.inspect?.daily_update data.inspect?.daily_update
]); ]);
// 更新时间戳显示
if (hourlyUpdateTime) { if (hourlyUpdateTime) {
document.getElementById('total-hourly-time').textContent = hourlyUpdateTime; document.getElementById('total-hourly-time').textContent = hourlyUpdateTime;
} }
@ -2059,6 +2012,109 @@
return new Date(current) > new Date(latest) ? current : latest; return new Date(current) > new Date(latest) ? current : latest;
}, null); }, null);
} }
// 添加颜色判断函数
function updateWeightedTotalColor(value) {
const element = document.getElementById('weighted-total');
if (!element) return;
// 移除现有的状态类
element.classList.remove('status-red', 'status-orange', 'status-green');
// 根据阈值添加对应的颜色类
if (value < 200) {
element.classList.add('status-red');
} else if (value <= 682) {
element.classList.add('status-orange');
} else {
element.classList.add('status-green');
}
}
// 零值检测相关变量
let zeroValueStartTime = null;
let zeroAlertShown = false;
// 显示零值告警
function showZeroAlert() {
if (!zeroAlertShown) {
const alarmBanner = document.getElementById('alarm-banner');
const alarmType = document.getElementById('alarm-type');
const alarmMessage = document.getElementById('alarm-message');
alarmType.textContent = "断审预警";
alarmMessage.textContent = "已连续14分钟未产生审核记录再过1分钟将记为一次断审违纪每天累计两次将被记为违规。请立即处理";
alarmBanner.classList.add('active');
zeroAlertShown = true;
}
}
// 关闭零值告警
function dismissZeroAlert() {
const alarmBanner = document.getElementById('alarm-banner');
alarmBanner.classList.remove('active');
zeroAlertShown = false;
}
// 移除单独的零值告警弹窗
function checkZeroValue(value) {
const now = new Date();
if (value === 0) {
if (!zeroValueStartTime) {
zeroValueStartTime = now;
} else {
const duration = (now - zeroValueStartTime) / (1000 * 60); // 转换为分钟
if (duration >= 14) {
showZeroAlert();
}
}
} else {
// 如果值不为零,重置计时器并关闭告警
zeroValueStartTime = null;
if (zeroAlertShown) {
dismissZeroAlert();
}
}
}
// 更新总计面板的颜色
function updateTotalCardColor(value) {
const totalCard = document.querySelector('.stats-card.total');
if (!totalCard) return;
// 移除现有的状态类
totalCard.classList.remove('status-red', 'status-orange', 'status-green');
// 根据阈值添加对应的颜色类
if (value < 200) {
totalCard.classList.add('status-red');
} else if (value <= 682) {
totalCard.classList.add('status-orange');
} else {
totalCard.classList.add('status-green');
}
}
// 确保在页面加载完成后立即更新一次颜色
document.addEventListener('DOMContentLoaded', function() {
const hourlyTotal = parseInt(document.getElementById('total-weighted-hourly').textContent) || 0;
updateTotalCardColor(hourlyTotal);
});
// 添加定时检查
setInterval(function() {
const hourlyTotal = parseInt(document.getElementById('total-weighted-hourly').textContent) || 0;
console.log('定时检查,当前值:', hourlyTotal); // 添加调试日志
updateTotalCardColor(hourlyTotal);
}, 5000); // 每5秒检查一次
// WebSocket告警推送
socket.on('alarm', function(data) {
if (data && data.message) {
alert(data.message);
}
});
</script> </script>
</body> </body>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>网易大神审核数据监控看板 - 登录</title> <title>网易大神实时审核数据监控看板 - 登录</title>
<link rel="icon" href="/static/ds-favicon.ico" type="image/x-icon"> <link rel="icon" href="/static/ds-favicon.ico" type="image/x-icon">
<style> <style>
:root { :root {
@ -538,7 +538,7 @@
<div id="messageContainer" class="message-container"></div> <div id="messageContainer" class="message-container"></div>
<div class="login-container"> <div class="login-container">
<div class="login-banner"> <div class="login-banner">
<h1>网易大神审核数据监控看板</h1> <h1>网易大神实时审核数据监控看板</h1>
<ul class="features"> <ul class="features">
<li>实时监控审核数据,自动统计工作量</li> <li>实时监控审核数据,自动统计工作量</li>
<li>多系统数据整合,一目了然</li> <li>多系统数据整合,一目了然</li>
@ -552,7 +552,7 @@
<form id="loginForm"> <form id="loginForm">
<div class="form-group"> <div class="form-group">
<label>工号</label> <label>工号</label>
<input type="text" name="username" placeholder="请输入您的工号" required> <input type="text" name="username" placeholder="请输入您的工号" required oninput="this.value = this.value.toUpperCase()">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;"> <div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项 必填项
</div> </div>
@ -570,18 +570,18 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Breeze工单系统 Cookie</label> <label>Breeze工单系统 Cookie(可选)</label>
<input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie" required> <input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie(可选)">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;"> <div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项 此选项可填可不填适用于您需要监控Breeze系统工单的情况
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>CMS系统 Cookie</label> <label>CMS系统 Cookie(可选)</label>
<input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie" required> <input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie(可选)">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;"> <div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项 此选项可填可不填适用于您需要监控CMS系统操作的情况
</div> </div>
</div> </div>
@ -593,6 +593,10 @@
</div> </div>
</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"> <div class="cookie-guide">
<a href="http://cos.ui-beam.com/work_scripts/monitor/cookie-extension/README.html" target="_blank">如何获取Cookie点击查看详细指南</a> <a href="http://cos.ui-beam.com/work_scripts/monitor/cookie-extension/README.html" target="_blank">如何获取Cookie点击查看详细指南</a>
</div> </div>
@ -630,6 +634,16 @@
const formData = new FormData(this); 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', { fetch('/login', {
method: 'POST', method: 'POST',
body: formData body: formData
@ -653,5 +667,13 @@
}); });
}); });
</script> </script>
<script type="text/javascript">
(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "rb98rvt1la");
</script>
</body> </body>
</html> </html>