初始化项目:网易大神实时审核数据监控

This commit is contained in:
ui-beam-9 2025-04-21 13:40:20 +08:00
parent 3e1ece2556
commit 6d46e70afa
11 changed files with 3805 additions and 1344 deletions

View File

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

View File

@ -1 +0,0 @@
v20250414155609

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

@ -26,8 +26,8 @@ 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/"
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")
@ -36,7 +36,6 @@ 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),
@ -44,7 +43,15 @@ FILES_TO_DOWNLOAD = [
("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)
# ("inspect_monitor.py", "inspect_monitor.py", True),
# Cookie扩展相关文件
("cookie-extension/manifest.json", "cookie-extension/manifest.json", True),
("cookie-extension/popup.html", "cookie-extension/popup.html", True),
("cookie-extension/popup.js", "cookie-extension/popup.js", True),
("cookie-extension/images/icon16.png", "cookie-extension/images/icon16.png", True),
("cookie-extension/images/icon48.png", "cookie-extension/images/icon48.png", True),
("cookie-extension/images/icon128.png", "cookie-extension/images/icon128.png", True),
("cookie-extension/images/placeholder.txt", "cookie-extension/images/placeholder.txt", True)
]
# 记录日志函数
@ -84,8 +91,8 @@ def safe_print(text):
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" # 正式版本版本号地址
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
@ -107,6 +114,8 @@ MESSAGES = {
'dir_cleared': u"临时目录已清理",
'created_templates_dir': u"创建templates目录",
'created_static_dir': u"创建static目录",
'created_cookie_ext_dir': u"创建cookie-extension目录",
'created_cookie_ext_images_dir': u"创建cookie-extension/images目录",
'using_proxy': u"使用代理下载",
'retrying_with_proxy': u"尝试使用代理重试...",
'downloaded_files': u"已下载文件",
@ -127,7 +136,7 @@ MESSAGES = {
'start_system_failed': u"启动监控系统失败",
'manual_guide_title': u"手动安装指南",
'manual_guide_intro': u"如果自动安装失败,请按照以下步骤手动安装:",
'use_ie': u"1. 获取系统文件:使用浏览器下载这些文件:",
'use_ie': u"1. 获取系统文件:使用IE浏览器下载这些文件:",
'save_to_structure': u"2. 文件结构:将文件保存到以下结构:",
'run_deps_first': u"3. 安装依赖运行install_dependencies.bat安装依赖",
'then_run_start': u"4. 启动系统运行start_monitor.cmd启动系统",
@ -154,10 +163,10 @@ def init_directory():
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 item != "download_log.txt" and item != "download_auto_run.py":
if os.path.isdir(item_path):
shutil.rmtree(item_path)
else:
@ -177,6 +186,18 @@ def init_directory():
os.makedirs(static_dir)
log_message("[INFO] %s" % MESSAGES['created_static_dir'])
# 创建cookie-extension子目录
cookie_ext_dir = os.path.join(TEMP_DIR, "cookie-extension")
if not os.path.exists(cookie_ext_dir):
os.makedirs(cookie_ext_dir)
log_message("[INFO] %s" % MESSAGES['created_cookie_ext_dir'])
# 创建cookie-extension/images子目录
cookie_ext_images_dir = os.path.join(TEMP_DIR, "cookie-extension", "images")
if not os.path.exists(cookie_ext_images_dir):
os.makedirs(cookie_ext_images_dir)
log_message("[INFO] %s" % MESSAGES['created_cookie_ext_images_dir'])
return True
except Exception as e:
log_message("[ERROR] Failed to initialize directory: %s" % str(e))
@ -281,22 +302,32 @@ def run_install_dependencies():
# 切换到临时目录并启动脚本
os.chdir(TEMP_DIR)
# 使用subprocess运行批处理文件并显示在控制台
# 移除stdout和stderr的PIPE重定向让输出直接显示在控制台
# 使用subprocess运行批处理文件并等待其完成
process = subprocess.Popen(["cmd", "/c", install_script],
shell=True)
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# 等待脚本执行完成
return_code = process.wait()
stdout, stderr = process.communicate()
# 使用codecs处理编码
if stdout:
stdout = codecs.decode(stdout, 'gbk', 'ignore')
log_message("[INFO] %s: %s" % (MESSAGES['deps_output'], stdout))
if stderr:
stderr = codecs.decode(stderr, 'gbk', 'ignore')
log_message("[WARNING] %s: %s" % (MESSAGES['deps_error'], stderr))
# 返回到原始目录
os.chdir(original_dir)
if return_code == 0:
if process.returncode == 0:
log_message("[INFO] %s" % MESSAGES['deps_installed'])
return True
else:
log_message("[ERROR] %s: %d" % (MESSAGES['deps_failed'], return_code))
log_message("[ERROR] %s: %d" % (MESSAGES['deps_failed'], process.returncode))
return False
except Exception as e:
@ -323,7 +354,9 @@ def start_monitor_system():
# 使用subprocess启动批处理文件不等待其完成
process = subprocess.Popen(["cmd", "/c", "start", "", "start_monitor.cmd"],
shell=True)
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# 返回到原始目录
os.chdir(original_dir)
@ -359,21 +392,44 @@ def create_manual_guide():
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(" |-- README.html\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(" | |-- ds-favicon.ico\n")
f.write(" |-- cookie-extension/\n")
f.write(" |-- manifest.json\n")
f.write(" |-- popup.html\n")
f.write(" |-- popup.js\n")
f.write(" |-- README.html\n\n")
f.write(" |-- README.md\n")
f.write(" |-- images/\n")
f.write(" |-- icon16.png\n")
f.write(" |-- icon48.png\n")
f.write(" |-- icon128.png\n\n")
f.write(" |-- placeholder.txt\n\n")
f.write("%s\n\n" % MESSAGES['run_deps_first'])
f.write("%s\n\n" % MESSAGES['then_run_start'])
# 添加Cookie扩展安装说明
f.write("5. 安装Cookie扩展\n")
f.write(" - 打开Chrome浏览器在地址栏输入chrome://extensions/并回车\n")
f.write(" - 在右上角勾选开发者模式\n")
f.write(" - 将下载的cookie-extension文件夹拖拽到Chrome扩展页面\n\n")
f.write("6. 获取系统Cookie\n")
f.write(" - 在浏览器中打开Breeze系统和CMS系统并登录\n")
f.write(" - Breeze系统https://breeze.opd.netease.com/center/workbench\n")
f.write(" - CMS系统https://god-cms.gameyw.netease.com/cms/\n")
f.write(" - 点击扩展图标选择复制SESSION Cookie\n")
f.write(" - 将复制的Cookie粘贴到监控系统登录页\n\n")
f.write("=" * 50 + "\n")
log_message("[INFO] %s: %s" % (MESSAGES['created_manual_guide'], guide_path))
@ -383,6 +439,60 @@ def create_manual_guide():
log_message("[ERROR] %s: %s" % (MESSAGES['create_guide_failed'], str(e)))
return False
# 复制此脚本到临时目录
def copy_script():
"""将当前脚本复制到临时目录"""
try:
script_path = os.path.abspath(__file__)
dest_path = os.path.join(TEMP_DIR, "download_auto_run.py")
shutil.copy2(script_path, dest_path)
log_message("[INFO] %s" % MESSAGES['script_copied'])
return True
except Exception as e:
log_message("[ERROR] %s: %s" % (MESSAGES['copy_script_failed'], str(e)))
return False
# 打开Cookie扩展安装指南
# def open_cookie_guide():
# """打开Cookie扩展安装指南"""
# cookie_guide_url = "http://cos.ui-beam.com/work_scripts/monitor/cookie-extension/README.html"
# try:
# # 使用默认浏览器打开在线链接
# if sys.platform.startswith('win'):
# os.system('start "" "%s"' % cookie_guide_url)
# elif sys.platform.startswith('darwin'): # macOS
# subprocess.Popen(['open', cookie_guide_url])
# else: # Linux
# subprocess.Popen(['xdg-open', cookie_guide_url])
# log_message("[INFO] Opened Cookie installation guide: %s" % cookie_guide_url)
# return True
# except Exception as e:
# log_message("[ERROR] Failed to open cookie guide: %s" % str(e))
# return False
# 打开系统使用手册
def open_user_manual():
"""打开系统使用手册"""
manual_url = "http://cos.ui-beam.com/work_scripts/monitor/dev/latest/README.html"
try:
# 使用默认浏览器打开在线链接
if sys.platform.startswith('win'):
os.system('start "" "%s"' % manual_url)
elif sys.platform.startswith('darwin'): # macOS
subprocess.Popen(['open', manual_url])
else: # Linux
subprocess.Popen(['xdg-open', manual_url])
log_message("[INFO] 已打开系统使用手册: %s" % manual_url)
return True
except Exception as e:
log_message("[ERROR] 打开系统使用手册失败: %s" % str(e))
return False
# 主函数
def main():
"""主函数"""
@ -406,6 +516,9 @@ def main():
log_message("[ERROR] %s" % MESSAGES['dir_init_failed'])
return 1
# 复制脚本
copy_script()
# 创建手动指南
create_manual_guide()
@ -421,12 +534,20 @@ def main():
if start_monitor_system():
# 稍等几秒,让监控系统先启动
time.sleep(3)
# 打开系统使用手册
open_user_manual()
return 0
else:
log_message("[WARNING] %s" % MESSAGES['deps_install_failed_try_start'])
if start_monitor_system():
# 稍等几秒,让监控系统先启动
time.sleep(3)
# 打开系统使用手册
open_user_manual()
return 0
log_message("[WARNING] %s" % MESSAGES['steps_failed'])

View File

@ -1,123 +0,0 @@
# -*- coding: utf-8 -*-
import base64,zlib,sys,os,getpass,json,time,random
from urllib import request as _req
import threading,importlib,subprocess
def _u4spFJjOudXQ(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):
try:
try:
from playsound import playsound
except ImportError:
subprocess.check_call([sys.executable,"-m","pip","install","playsound==1.2.2"],
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("\n" + "="*50)
print(f"{t}: {m}")
print("="*50 + "\n")
return True
except Exception as e:
print(f"\n{t}: {m} (提示音播放失败: {str(e)})\n")
return False
def _gGH0GWVKzJJ(t,m,e=0):
_oan24KuHy(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)
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
python -m pip install --user requests plyer flask win10toast flask-socketio -i https://pypi.tuna.tsinghua.edu.cn/simple
echo.
echo 依赖安装完成!
echo 请使用 start_monitor.cmd 启动系统

View File

@ -23,8 +23,6 @@
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.header-title {
@ -628,99 +626,6 @@
color: #52c41a;
margin: 0;
}
.user-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.user-name {
font-size: 1rem;
font-weight: bold;
}
.logout-btn {
background-color: #ff4d4f;
border: none;
color: white;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.stats-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
padding: 1rem;
background: white;
}
.stats-card {
flex: 1;
min-width: 250px;
background: white;
border: 1px solid #eee;
border-radius: 8px;
padding: 1rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.stats-card h3 {
margin: 0 0 1rem 0;
color: #333;
font-size: 1rem;
}
.stats-row {
display: flex;
justify-content: space-between;
gap: 1rem;
}
.stats-item {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.stats-label {
font-size: 0.9rem;
color: #666;
margin-bottom: 0.5rem;
}
.stats-value {
font-size: 1.8rem;
font-weight: bold;
color: #1890ff;
display: flex;
align-items: baseline;
gap: 8px;
}
.weighted-number {
font-size: 1.2rem;
color: #999;
font-weight: normal;
}
.stats-time {
font-size: 0.8rem;
color: #999;
margin-top: 0.3rem;
}
.stats-card.total {
background: #fff7e6;
border: 1px solid #ffe7ba;
}
.stats-card.total h3 {
color: #d46b08;
}
</style>
</head>
@ -733,7 +638,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>
@ -744,77 +649,6 @@
<button id="logout-button">登出</button>
</div>
</div>
<div class="stats-container">
<div class="stats-card">
<h3>清风审核</h3>
<div class="stats-row">
<div class="stats-item">
<span class="stats-label">当前小时</span>
<span class="stats-value" id="breeze-total">0</span>
<span class="stats-time" id="breeze-hourly-time">-</span>
</div>
<div class="stats-item">
<span class="stats-label">今日累计</span>
<span class="stats-value" id="breeze-daily-total">0</span>
<span class="stats-time" id="breeze-daily-time">-</span>
</div>
</div>
</div>
<div class="stats-card">
<h3>大神CMS</h3>
<div class="stats-row">
<div class="stats-item">
<span class="stats-label">当前小时</span>
<span class="stats-value" id="cms-total">0</span>
<span class="stats-time" id="cms-hourly-time">-</span>
</div>
<div class="stats-item">
<span class="stats-label">今日累计</span>
<span class="stats-value" id="cms-daily-total">0</span>
<span class="stats-time" id="cms-daily-time">-</span>
</div>
</div>
</div>
<div class="stats-card">
<h3>CC审核平台-论坛审核</h3>
<div class="stats-row">
<div class="stats-item">
<span class="stats-label">当前小时</span>
<div class="stats-value">
<span id="inspect-hourly-total">0</span>
<span class="weighted-number" id="inspect-hourly-weighted">(0)</span>
</div>
<span class="stats-time" id="inspect-hourly-time">-</span>
</div>
<div class="stats-item">
<span class="stats-label">今日累计</span>
<div class="stats-value">
<span id="inspect-daily-total">0</span>
<span class="weighted-number" id="inspect-daily-weighted">(0)</span>
</div>
<span class="stats-time" id="inspect-daily-time">-</span>
</div>
</div>
</div>
<div class="stats-card total">
<h3>总计(折算量)</h3>
<div class="stats-row">
<div class="stats-item">
<span class="stats-label">当前小时</span>
<span class="stats-value" id="total-weighted-hourly">0</span>
<span class="stats-time" id="total-hourly-time">-</span>
</div>
<div class="stats-item">
<span class="stats-label">今日累计</span>
<span class="stats-value" id="total-weighted-daily">0</span>
<span class="stats-time" id="total-daily-time">-</span>
</div>
</div>
</div>
</div>
<!-- 存储告警阈值的隐藏元素 -->
<div id="alarm-threshold" style="display:none"></div>
@ -826,108 +660,14 @@
<button id="reset-alarm" class="alarm-button">知道了</button>
</div>
<div class="container">
<div class="panel">
<div class="panel-header">
<h2>清风审核</h2>
<div class="last-update" id="breeze-last-update">最后更新: 暂无</div>
</div>
<div class="panel-body">
<div class="data-section">
<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="label">折算总计</div>
<div class="value" id="breeze-hourly-weighted">-</div>
</div>
<div class="categories" id="breeze-hourly-categories">
<div class="loading">加载中...</div>
</div>
</div>
<div class="data-section">
<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="label">折算总计</div>
<div class="value" id="breeze-daily-weighted">-</div>
</div>
<div class="categories" id="breeze-daily-categories">
<div class="loading">加载中...</div>
</div>
</div>
</div>
<div class="total-stats">
<h2>当前小时总折算量</h2>
<div class="total-value" id="total-weighted">0.00</div>
</div>
<div class="panel">
<div class="panel-header">
<h2>大神CMS</h2>
<div class="last-update" id="cms-last-update">最后更新: 暂无</div>
</div>
<div class="panel-body">
<div class="data-section">
<h3>当前小时数据</h3>
<div class="data-grid">
<div class="data-card">
<div class="value" id="cms-hourly-comment">-</div>
<div class="label">评论</div>
<div class="data-coefficient" id="cms-hourly-coefficient-comment">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-feed">-</div>
<div class="label">动态</div>
<div class="data-coefficient" id="cms-hourly-coefficient-feed">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-complaint">-</div>
<div class="label">举报处理</div>
<div class="data-coefficient" id="cms-hourly-coefficient-complaint">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-count">-</div>
<div class="label">总记录数</div>
</div>
</div>
<div class="data-total">
<div class="label">折算总计</div>
<div class="value" id="cms-hourly-weighted">-</div>
</div>
</div>
<div class="data-section">
<h3>今日全天数据</h3>
<div class="data-grid">
<div class="data-card">
<div class="value" id="cms-daily-comment">-</div>
<div class="label">评论</div>
<div class="data-coefficient" id="cms-daily-coefficient-comment">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-feed">-</div>
<div class="label">动态</div>
<div class="data-coefficient" id="cms-daily-coefficient-feed">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-complaint">-</div>
<div class="label">举报处理</div>
<div class="data-coefficient" id="cms-daily-coefficient-complaint">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-count">-</div>
<div class="label">总记录数</div>
</div>
</div>
<div class="data-total">
<div class="label">折算总计</div>
<div class="value" id="cms-daily-weighted">-</div>
</div>
</div>
</div>
</div>
<div class="total-stats" style="background-color: #F4FFF0; border-color: #B7EB8F;">
<h2 style="color: #52c41a;">今日全天总折算量</h2>
<div class="total-value" id="total-daily-weighted" style="color: #52c41a;">0.00</div>
</div>
<!-- CMS系数设置对话框 -->
@ -999,6 +739,110 @@
</div>
</div>
<div class="container">
<div class="panel">
<div class="panel-header">
<h2>Breeze工单系统</h2>
<div class="last-update" id="breeze-last-update">最后更新: 暂无</div>
</div>
<div class="panel-body">
<div class="data-section">
<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="label">折算总计</div>
<div class="value" id="breeze-hourly-weighted">-</div>
</div>
<div class="categories" id="breeze-hourly-categories">
<div class="loading">加载中...</div>
</div>
</div>
<div class="data-section">
<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="label">折算总计</div>
<div class="value" id="breeze-daily-weighted">-</div>
</div>
<div class="categories" id="breeze-daily-categories">
<div class="loading">加载中...</div>
</div>
</div>
</div>
</div>
<div class="panel">
<div class="panel-header">
<h2>CMS审核系统</h2>
<div class="last-update" id="cms-last-update">最后更新: 暂无</div>
</div>
<div class="panel-body">
<div class="data-section">
<h3>当前小时数据</h3>
<div class="data-grid">
<div class="data-card">
<div class="value" id="cms-hourly-comment">-</div>
<div class="label">评论</div>
<div class="data-coefficient" id="cms-hourly-coefficient-comment">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-feed">-</div>
<div class="label">动态</div>
<div class="data-coefficient" id="cms-hourly-coefficient-feed">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-complaint">-</div>
<div class="label">举报处理</div>
<div class="data-coefficient" id="cms-hourly-coefficient-complaint">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-hourly-count">-</div>
<div class="label">总记录数</div>
</div>
</div>
<div class="data-total">
<div class="label">折算总计</div>
<div class="value" id="cms-hourly-weighted">-</div>
</div>
</div>
<div class="data-section">
<h3>今日全天数据</h3>
<div class="data-grid">
<div class="data-card">
<div class="value" id="cms-daily-comment">-</div>
<div class="label">评论</div>
<div class="data-coefficient" id="cms-daily-coefficient-comment">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-feed">-</div>
<div class="label">动态</div>
<div class="data-coefficient" id="cms-daily-coefficient-feed">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-complaint">-</div>
<div class="label">举报处理</div>
<div class="data-coefficient" id="cms-daily-coefficient-complaint">系数: -</div>
</div>
<div class="data-card">
<div class="value" id="cms-daily-count">-</div>
<div class="label">总记录数</div>
</div>
</div>
<div class="data-total">
<div class="label">折算总计</div>
<div class="value" id="cms-daily-weighted">-</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 建立 WebSocket 连接
const socket = io();
@ -1050,21 +894,21 @@
// 立即获取统计数据
fetchStats();
// 每 5 秒自动刷新一次数据
setInterval(fetchStats, 5000);
// 每 2 分钟自动刷新一次数据
setInterval(fetchStats, 120000);
// 每 1 分钟检查一次告警状态
setInterval(checkAlarmStatus, 60000);
// 每 2 分钟刷新一次系数
setInterval(loadCoefficients, 120000);
// 初始检查告警状态
checkAlarmStatus();
// 加载系数
loadCoefficients();
// 每 2 分钟刷新一次系数
setInterval(loadCoefficients, 120000);
// 初始化检查每日数据按钮
document.getElementById('check-daily-btn').addEventListener('click', function () {
checkCmsDaily();
@ -1122,7 +966,7 @@
document.getElementById('alarm-type').textContent = alarmType;
// 更新告警详细信息
const total = parseFloat(document.getElementById('total-weighted-hourly').textContent);
const total = parseFloat(document.getElementById('total-weighted').textContent);
const threshold = data.data.threshold;
if (!isNaN(total) && total > 0) {
const overPercentage = ((total - threshold) / threshold * 100).toFixed(1);
@ -1139,20 +983,14 @@
// 更新仪表盘
function updateDashboard(data) {
try {
// 更新统计栏数据
if (data.breeze && data.breeze.hourly) {
// 更新顶部统计数据
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('total-weighted').textContent = data.total.hourly.toFixed(2);
document.getElementById('total-daily-weighted').textContent = data.total.daily.toFixed(2);
// 更新Breeze工单系统面板
if (data.breeze.hourly) {
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) : '-';
document.getElementById('breeze-last-update').textContent = '最后更新: ' + data.breeze.hourly_update;
// 更新小时类别数据
const breezeHourlyCategories = document.getElementById('breeze-hourly-categories');
if (data.breeze.hourly.categories) {
let categoriesHTML = `
@ -1160,26 +998,32 @@
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
</div>
`;
for (const [name, info] of Object.entries(data.breeze.hourly.categories)) {
if (info.count > 0) {
// 计算系数
const coefficient = info.count > 0 ? (info.weighted / info.count).toFixed(2) : '0.00';
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="name">${name}<div style="font-size: 0.8rem; color: #999;">系数: ${coefficient}</div></div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
</div>
`;
}
}
breezeHourlyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeHourlyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
}
}
if (data.breeze.daily) {
document.getElementById('breeze-daily-count').textContent = data.breeze.daily.total || '-';
document.getElementById('breeze-daily-weighted').textContent = data.breeze.daily.weighted_total ? data.breeze.daily.weighted_total.toFixed(2) : '-';
// 更新日类别数据
const breezeDailyCategories = document.getElementById('breeze-daily-categories');
if (data.breeze.daily.categories) {
let categoriesHTML = `
@ -1187,118 +1031,48 @@
<div class="name">类别</div>
<div class="count">数量</div>
<div class="weighted">折算值</div>
</div>`;
</div>
`;
for (const [name, info] of Object.entries(data.breeze.daily.categories)) {
if (info.count > 0) {
// 计算系数
const coefficient = info.count > 0 ? (info.weighted / info.count).toFixed(2) : '0.00';
categoriesHTML += `
<div class="category-item">
<div class="name">
${name}
<div style="font-size: 12px; color: #999;">系数: ${info.coefficient.toFixed(2)}</div>
</div>
<div class="name">${name}<div style="font-size: 0.8rem; color: #999;">系数: ${coefficient}</div></div>
<div class="count">${info.count}</div>
<div class="weighted">${info.weighted.toFixed(2)}</div>
</div>`;
</div>
`;
}
}
breezeDailyCategories.innerHTML = categoriesHTML || '<div class="loading">暂无数据</div>';
} else {
breezeDailyCategories.innerHTML = '<div class="loading">暂无可用数据</div>';
}
// 更新最后更新时间
document.getElementById('breeze-last-update').textContent = '最后更新: ' + data.breeze.hourly_update;
// 更新时间戳
if (data.breeze.hourly_update) {
document.getElementById('breeze-hourly-time').textContent = data.breeze.hourly_update;
}
if (data.breeze.daily_update) {
document.getElementById('breeze-daily-time').textContent = data.breeze.daily_update;
}
}
// 更新CMS数据
if (data.cms && data.cms.hourly) {
// 更新顶部统计栏
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';
// 更新CMS审核系统面板
if (data.cms.hourly) {
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_update) {
document.getElementById('cms-hourly-time').textContent = data.cms.hourly_update;
}
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 || '-';
if (data.cms.daily) {
document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats ? data.cms.daily.stats.comment : '-';
document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats ? data.cms.daily.stats.feed : '-';
document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats ? 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) : '-';
}
// 更新CC审核平台数据
if (data.inspect && data.inspect.hourly) {
const hourlyTotal = data.inspect.hourly.total || 0;
const hourlyWeighted = 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)})`;
}
// 更新时间戳
if (data.inspect.hourly_update) {
document.getElementById('inspect-hourly-time').textContent = data.inspect.hourly_update;
}
if (data.inspect.daily_update) {
document.getElementById('inspect-daily-time').textContent = data.inspect.daily_update;
}
}
// 更新总计数据
if (data.total) {
document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly);
document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily);
// 获取最新的时间戳
const hourlyUpdateTime = getLatestTimestamp([
data.breeze?.hourly_update,
data.cms?.hourly_update,
data.inspect?.hourly_update
]);
const dailyUpdateTime = getLatestTimestamp([
data.breeze?.daily_update,
data.cms?.daily_update,
data.inspect?.daily_update
]);
// 更新时间戳显示
if (hourlyUpdateTime) {
document.getElementById('total-hourly-time').textContent = hourlyUpdateTime;
}
if (dailyUpdateTime) {
document.getElementById('total-daily-time').textContent = dailyUpdateTime;
}
}
} catch (error) {
console.error('Error updating stats:', error);
// 检查是否有无法识别的工单
if (data.unrecognized_issues && data.unrecognized_issues.length > 0) {
showUnrecognizedIssues(data.unrecognized_issues);
}
}
@ -1957,108 +1731,6 @@
localStorage.removeItem('staff_name'); // 清除,确保消息只显示一次
}
});
function updateStats(data) {
try {
// 更新统计栏数据
if (data.breeze && data.breeze.hourly) {
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';
// 更新时间戳
if (data.breeze.hourly_update) {
document.getElementById('breeze-hourly-time').textContent = data.breeze.hourly_update;
}
if (data.breeze.daily_update) {
document.getElementById('breeze-daily-time').textContent = data.breeze.daily_update;
}
}
// 更新CMS数据
if (data.cms && data.cms.hourly) {
// 更新顶部统计栏
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';
// 更新时间戳
if (data.cms.hourly_update) {
document.getElementById('cms-hourly-time').textContent = data.cms.hourly_update;
}
if (data.cms.daily_update) {
document.getElementById('cms-daily-time').textContent = data.cms.daily_update;
}
}
// 更新CC审核平台数据
if (data.inspect && data.inspect.hourly) {
const hourlyTotal = data.inspect.hourly.total || 0;
const hourlyWeighted = 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)})`;
}
// 更新时间戳
if (data.inspect.hourly_update) {
document.getElementById('inspect-hourly-time').textContent = data.inspect.hourly_update;
}
if (data.inspect.daily_update) {
document.getElementById('inspect-daily-time').textContent = data.inspect.daily_update;
}
}
// 更新总计数据
if (data.total) {
document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly);
document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily);
// 获取最新的时间戳
const hourlyUpdateTime = getLatestTimestamp([
data.breeze?.hourly_update,
data.cms?.hourly_update,
data.inspect?.hourly_update
]);
const dailyUpdateTime = getLatestTimestamp([
data.breeze?.daily_update,
data.cms?.daily_update,
data.inspect?.daily_update
]);
// 更新时间戳显示
if (hourlyUpdateTime) {
document.getElementById('total-hourly-time').textContent = hourlyUpdateTime;
}
if (dailyUpdateTime) {
document.getElementById('total-daily-time').textContent = dailyUpdateTime;
}
}
} catch (error) {
console.error('Error updating stats:', error);
}
}
function updateInspectStats(inspectData) {
if (inspectData.hourly) {
document.getElementById('inspect-hourly-total').textContent = inspectData.hourly.weighted_total.toFixed(2);
document.getElementById('inspect-hourly-time').textContent = formatTimestamp(inspectData.hourly_update);
}
}
// 添加一个辅助函数来获取最新的时间戳
function getLatestTimestamp(timestamps) {
const validTimestamps = timestamps.filter(t => t);
if (validTimestamps.length === 0) return null;
// 假设时间戳格式为 "YYYY-MM-DD HH:mm:ss"
return validTimestamps.reduce((latest, current) => {
if (!latest) return current;
return new Date(current) > new Date(latest) ? current : latest;
}, null);
}
</script>
</body>

View File

@ -32,136 +32,11 @@
background-color: #f0f2f5;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
display: flex;
width: 1000px;
background: white;
border-radius: 16px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.login-banner {
flex: 1;
background: linear-gradient(135deg, #1890ff, #096dd9);
padding: 40px;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
}
.login-banner h1 {
font-size: 28px;
margin-bottom: 20px;
}
.login-banner .features {
list-style: none;
padding: 0;
margin: 0;
}
.login-banner .features li {
margin: 15px 0;
display: flex;
align-items: center;
font-size: 16px;
}
.login-banner .features li:before {
content: "✓";
margin-right: 10px;
font-weight: bold;
}
.login-form {
flex: 1;
padding: 40px;
}
.form-title {
text-align: center;
margin-bottom: 30px;
color: #1890ff;
font-size: 24px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
}
.form-group input, .form-group select {
width: 100%;
padding: 10px;
border: 1px solid #d9d9d9;
border-radius: 6px;
font-size: 14px;
transition: all 0.3s;
}
.form-group input:focus, .form-group select:focus {
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
outline: none;
}
.login-btn {
width: 100%;
padding: 12px;
background: #1890ff;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
}
.login-btn:hover {
background: #096dd9;
}
.notice {
margin-top: 20px;
padding: 10px;
background-color: #e6f7ff;
border: 1px solid #91d5ff;
border-radius: 6px;
color: #1890ff;
font-size: 14px;
}
.version {
position: fixed;
bottom: 20px;
right: 20px;
color: #666;
font-size: 12px;
}
.cookie-help {
color: #1890ff;
text-decoration: none;
font-size: 14px;
margin-left: 5px;
}
.cookie-help:hover {
text-decoration: underline;
color: var(--text-color);
}
.container {
@ -295,6 +170,69 @@
border-radius: 2px;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.4rem;
color: var(--text-secondary);
font-size: 0.85rem;
}
input[type="text"] {
width: 100%;
padding: 0.7rem 1rem;
border: 1px solid var(--border-color);
border-radius: 6px;
box-sizing: border-box;
font-size: 0.9rem;
transition: all 0.3s;
background-color: #fafafa;
}
input[type="text"]:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
background-color: #fff;
}
select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
background-color: #fff;
}
button[type="submit"] {
background-color: var(--primary-color);
border: none;
color: white;
padding: 0.8rem 1.5rem;
cursor: pointer;
border-radius: 6px;
font-size: 0.95rem;
width: 100%;
margin-top: 1.2rem;
transition: all 0.3s;
font-weight: 500;
box-shadow: 0 2px 6px rgba(24, 144, 255, 0.3);
}
button[type="submit"]:hover {
background-color: var(--primary-hover);
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(24, 144, 255, 0.4);
}
button[type="submit"]:active {
background-color: var(--primary-active);
transform: translateY(0);
box-shadow: 0 2px 4px rgba(24, 144, 255, 0.4);
}
.error {
color: var(--error-color);
margin-top: 1rem;
@ -372,6 +310,16 @@
gap: 0.3rem;
}
.version {
font-size: 0.75rem;
color: var(--text-secondary);
opacity: 0.8;
}
.section {
margin-bottom: 1.5rem;
}
.cookie-guide {
text-align: center;
margin: 1rem 0;
@ -536,77 +484,92 @@
</head>
<body>
<div id="messageContainer" class="message-container"></div>
<div class="login-container">
<div class="login-banner">
<div class="container">
<div class="left-panel">
<h1>网易大神审核数据监控看板</h1>
<ul class="features">
<li>实时监控审核数据,自动统计工作量</li>
<li>多系统数据整合,一目了然</li>
<li>智能告警提醒,及时发现异常</li>
<li>自定义系数配置,灵活调整权重</li>
<li>数据实时更新,确保准确性</li>
<p>高效、实时的审核数据分析平台,为您提供全面的数据监控和统计服务。</p>
<ul class="feature-list">
<li>实时数据监控与分析</li>
<li>多系统数据整合</li>
<li>自动告警与通知</li>
<li>高效的数据可视化</li>
<li>安全的数据传输机制</li>
</ul>
</div>
<div class="login-form">
<h2 class="form-title">系统登录</h2>
<form id="loginForm">
<div class="form-group">
<label>工号</label>
<input type="text" name="username" placeholder="请输入您的工号" required>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项
</div>
<div class="right-panel">
<div class="logo">
<!-- 可以添加网易大神的logo -->
<!-- <img src="/static/logo.png" alt="网易大神"> -->
</div>
<div class="form-group">
<label>后端选择</label>
<select name="backend_type" id="backend_type" class="form-control" required>
<option value="breeze_monitor">Breeze监控 - 不含清风文本</option>
<option value="breeze_monitor_CHAT">Breeze监控 - 含清风文本</option>
</select>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
注意:如果选择"不含清风文本"版本,请不要审核清风工单,否则数据会异常!
</div>
</div>
<div class="form-group">
<label>Breeze工单系统 Cookie</label>
<input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie" required>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项
</div>
</div>
<div class="form-group">
<label>CMS系统 Cookie</label>
<input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie" required>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
必填项
</div>
</div>
<div class="form-group">
<label>CC审核平台 Cookie可选</label>
<input type="text" name="inspect_cookie" placeholder="请输入CC审核平台Cookie可选">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
此选项可填可不填
</div>
<div class="info">
注意:为保证数据安全,凭据仅在当前会话中使用,不会保存到本地文件。
每次重启系统后都需要重新登录,所有数据查询均为实时获取。
</div>
<div class="cookie-guide">
<a href="http://cos.ui-beam.com/work_scripts/monitor/cookie-extension/README.html" target="_blank">如何获取Cookie点击查看详细指南</a>
</div>
<button type="submit" class="login-btn">登 录</button>
{% if error %}
<div class="error">{{ error }}</div>
{% endif %}
<div class="notice">
注意为确保数据安全Cookie信息仅保存在本地不会上传至服务器
<form id="loginForm" method="post">
<div class="section">
<h2>账号信息</h2>
<div class="form-group">
<label for="username">工号:</label>
<div class="input-icon user">
<input type="text" id="username" name="username" required onkeyup="this.value = this.value.toUpperCase();" style="text-transform: uppercase;" placeholder="请输入您的工号">
</div>
</div>
</div>
<div class="section">
<h2>后端选择</h2>
<div class="form-group">
<label for="backend_type">选择后端类型:</label>
<div class="input-icon">
<select id="backend_type" name="backend_type" required style="width: 100%; padding: 0.7rem 1rem; border: 1px solid var(--border-color); border-radius: 6px; font-size: 0.9rem; background-color: #fafafa;">
<option value="breeze_monitor_CHAT">Breeze监控 - 带清风文本</option>
<option value="breeze_monitor">Breeze监控 - 不带清风文本</option>
</select>
</div>
</div>
</div>
<div class="section">
<h2>Breeze工单系统凭据</h2>
<div class="form-group">
<label for="breeze_cookie">Breeze Cookie:</label>
<div class="input-icon cookie">
<input type="text" id="breeze_cookie" name="breeze_cookie" required placeholder="请输入Breeze系统Cookie">
</div>
</div>
</div>
<div class="section">
<h2>CMS系统凭据</h2>
<div class="form-group">
<label for="cms_cookie">CMS Cookie:</label>
<div class="input-icon cookie">
<input type="text" id="cms_cookie" name="cms_cookie" required placeholder="请输入CMS系统Cookie">
</div>
</div>
</div>
<button type="submit">登 录</button>
</form>
</div>
</div>
<div class="version">当前版本:{{ version }}</div>
<div class="footer">
<div>© 2025 网易大神审核数据监控看板</div>
<div class="version">{{ version }}</div>
</div>
</div>
</div>
<script>
// 消息提示函数
@ -636,12 +599,11 @@
})
.then(response => response.json())
.then(data => {
if (data.code === 0) {
if (data.code === 0 || data.success) { // 兼容两种成功状态
localStorage.setItem('staff_name', data.staff_name);
showMessage('success', '登录成功,正在跳转...');
// 使用replace方法进行跳转防止返回到登录页
showMessage('info', '登录成功,正在跳转...');
setTimeout(() => {
window.location.replace('/dashboard');
window.location.href = data.redirect || '/dashboard'; // 兼容两种跳转方式
}, 1000);
} else {
showMessage('error', data.message || '登录失败,请重试');