From 21e9e9b08bf6046ce5cff21f32653bef21caae7f Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Fri, 21 Nov 2025 09:26:50 +0800 Subject: [PATCH 1/6] update --- kgadget/src/baidu_sms_kafka_consumer.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kgadget/src/baidu_sms_kafka_consumer.py b/kgadget/src/baidu_sms_kafka_consumer.py index 90d2153..fbc1202 100644 --- a/kgadget/src/baidu_sms_kafka_consumer.py +++ b/kgadget/src/baidu_sms_kafka_consumer.py @@ -110,7 +110,7 @@ async def baidu_sms_kafka_consumer(ns={}): 'auto.offset.reset': 'latest', 'fetch.message.max.bytes': '1024*512', }) - + print('开始创建文件夹') # 订阅的主题名称 consumer.subscribe(['kaiyuanyun_msg_topic']) @@ -125,10 +125,10 @@ async def baidu_sms_kafka_consumer(ns={}): # total_count = 0 while True: i = 0 - if i == 0: - # 写入文件记录轮询开始时间 时间格式: YYYY-MM-DD HH:MM:SS - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(f"轮询开始时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") + # if i == 0: + # # 写入文件记录轮询开始时间 时间格式: YYYY-MM-DD HH:MM:SS + # with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: + # f.write(f"轮询开始时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") msg = consumer.poll(0.1) # 单次轮询获取消息 @@ -251,6 +251,10 @@ async def baidu_sms_kafka_consumer(ns={}): } except Exception as e: print(f"处理异常: {str(e)}") + import traceback + with open('baidu_kafka_error.txt', 'w') as f: + f.write(str(e)+ traceback.format_exc()) + traceback.print_exc() return { 'status': False, 'msg': f"处理异常: {str(e)}" @@ -272,5 +276,6 @@ if __name__ == '__main__': two_levels_up = '/'.join(path_parts[:-2]) config = getConfig(two_levels_up) DBPools(config.databases) + print(config.databases) loop = asyncio.get_event_loop() print(loop.run_until_complete(baidu_sms_kafka_consumer())) From 3491eed86a7c5a2440a7bd86fb2072f1fe561c8b Mon Sep 17 00:00:00 2001 From: hrx <18603305412@163.com> Date: Fri, 21 Nov 2025 11:16:24 +0800 Subject: [PATCH 2/6] updata --- f/web-kboss/src/main.js | 2 +- .../src/views/homePage/detail/img/1.png | Bin 2158 -> 8517 bytes .../src/views/homePage/detail/img/4.png | Bin 2508 -> 8948 bytes .../src/views/homePage/detail/img/5.png | Bin 2052 -> 8500 bytes .../src/views/homePage/detail/img/6.png | Bin 2309 -> 8542 bytes .../src/views/homePage/detail/img/7.png | Bin 2237 -> 8539 bytes .../src/views/homePage/detail/index.vue | 4 ++-- .../src/views/product/mainPage/index.vue | 12 ++++++------ 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/f/web-kboss/src/main.js b/f/web-kboss/src/main.js index 7cab792..9796b5d 100644 --- a/f/web-kboss/src/main.js +++ b/f/web-kboss/src/main.js @@ -100,7 +100,7 @@ Vue.use(HappyScroll) // }); // // 禁止F12和开发者工具快捷键 -// document.addEventListener('keydown', function(e) { +// document.addEventListener('keydown', function(e ) { // // 禁止F12 // if (e.key === 'F12') { // e.preventDefault(); diff --git a/f/web-kboss/src/views/homePage/detail/img/1.png b/f/web-kboss/src/views/homePage/detail/img/1.png index 85e5a4a3c9b234ab76e89fd8982ac5945e540e1c..3c1d090d40a969a86fb76aebbf7bf57984d37bcb 100644 GIT binary patch literal 8517 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 literal 2158 zcmV-!2$A=RP)r^B9HCar!^G;ZDwF8M*OGctrGOo*iAr3!}I2^om=!bhw1_{Vs`I zT_cBu%vQ%iI|v7%um_AoiqRfz{a zk>WpAtYeX2SV;}btBF-_DRwKDuOSyqF7I<})Fd7!5~5!vkB?;J9?f(#9)g$*CypA9 zQ?vuuDv#%r2k0R0NIa|-z4;im7_8Pu>1g61HC=QE;c2kPw@zG-a-;jSd06Bqq8Gr7 zn8#hGwpy!;1#S6-nyWmdWmL%@iP~Z|7n2Q(oJ{9+6xM_=x`qnC9y%$^ATK?2D7(RQ z{}s9DZCp}yhrh0REicOexqL>ZO@hM8vuyw%biRoIU{4qQt zy|&_c4jS1|c}Q|IXR@uku!>lPNJ9gDCJ2|hC*_OmQejrwwocUT?jDyPq;@w?(E)zJ zbU;PWUN#n|jo!ED4Hg$xaD%#M8Khz4gXJN~eKZ!=3!@TQy%>zwntv5|-2gQ&r49t` z8|0m1iXe!P{chdf)IaN=>wUIvU$Pyc)KQtvfRIc10iN~BEJ_={x4vONM;4thK`m0_ z>JOyqF+?(UMb%X+`O37$Y={NJKi%>u{VCrtzL<_#0nDI~jIAp#eHhoUt8RjaQd#35 z`Ftv*r!+4PoXGc!Ewc9!_zaX{U-QD5FLNkgpI=w`jr=-mOc$l#AlcqyJ(aJ^)=$iH z4#ye-rLeG_N&gGvpJS51mcA#};EYVn4aT#!`K7X)XP7mcj-N|)P0ZKj*Cl>_v#(xp zBL_K+$r>`5jMHa!QD>i~$S;wO%?_-O%?Vx=n-eOJn{sw&3y8Rgbw+f2KAk0^50nIe zWzPdMWfTQJMakKtah0(XB|+oQrhd7z4BYF6n+-TM&v%Y4hOdeVbsA%o0{KAash#ve zF`G-3#TNwQ@=-`Au;V&c7Q<6Tg(-}ZUa_q(_;eO?{FE}yeut75kF~m@m}^mTzQPDG zrc??&Qhs(1sm%80Q?jgBkfP*3I4{O*5jv#&%pOHZX=t$DN3t+bQF3orVo%2fY-z2) z(}fO~vt8NdJW=8Xe%^feXD=7SElLheq)SV&B>Fbqi7w|)8+t&w zcu)?FopO#-asr-QwTk;~Nrj+=?W)z>DmYPifaRi#f-sm52&Tb@;8yo~I9juW1NpxF z$R!!~u*>7+#6j$0{TIGS<*hsD?!*pS7bYqfut(q#i@vVR%gl_x#%Vy z2ai4S81VEiqb$q@SORULFl6+|tc8Up1KJeg5(p*-{re4>0R~N^$@BjpxPr-bHBB7J z+T_UDZqhZxBrrI_A7u>+OI0d5IR#T#=X?uo`nAKXD9l6=Hfv`;RkoobssqMGrZ*Yr zaC7o(#VQZHPhm2{5BUJ*XXOLRAm2f*mT9HT>OMeUAdq`Rx00ZCiMp*o^`EB8GmMQ4 z&e?a8k&m;AT<>EmsZ-`%hL_F7<@V~|^$s{^P2825Chx~onF5II{w&ClrN@7hppXyk zJGD=A#2@)?{iJf#`K~In|o_2HuETx>wn2tS8nI}+DFohsvhnho7UaS zr9&O2L*&w51anKx?~{|{IR6!c>3euVFoSaBzre1uMQG$6m8(gmd1>GTyR!IQ zA^w3Cp}5=w4w3vPA^~g(bV1qnjL~gKvxOzFXtL~$O9PZ%8*=p8l%;Q%`eJ6DY$>}j z@m@(Ag|I|?lY;9a$Q$esj>EyR45rH^(%D{Rrx(lJ}#Za!a>M1#TGa( z%9Pc!!~0>d@-jQLSMGQu(_CDP8($(v&UZ*_X;M^2%2)!#N1D>MfvR1MA-szKb>5$wJ{(5Q_oy*Gmm&Ea(mbD$f zmp*L$k^5fjI{GlahS~sP6iLT#ptC~gNNjH4HFK9JVv-XLNiJvgKdOAL$^9Du0RR6s k_tOsm000I_L_t&o0Q&0oZHg(A1poj507*qoM6N<$g0QzEkpKVy diff --git a/f/web-kboss/src/views/homePage/detail/img/4.png b/f/web-kboss/src/views/homePage/detail/img/4.png index 64172fc860fd3817dc1ccde02a9efbfe04b35590..4363d65d1cffc0f41b2e0534852361113373cd31 100644 GIT binary patch literal 8948 zcmVXn@+{G^O<6`$rmmC9sO;815-g}rM7gzrB#w*PPMV}} zixv@zn2lQ(sL=*Z>&SIg6lu{W7Aw~Q+*(0hl(7@XD8ks0P3p%diBu?3v7&-*(wyL*%p{KfH#Ht-hXmfgEq7ZBN|$+Nm5^;YXV<0=v7>xnk$qq z4(FhSh!7X^&xXEW3z(rCx3wL&EeC*O&>>8PEVuOSzGGHf_L9`2dKK)IlLmf;S=h`m zHN{4c4N_?_VNlru(e`NpG)VAC3qDD*5yL#vj+H#fx(0uchSy_JWbPn8H-ChP3v*1l zt!G(Y5xv3%a(PfQ&~Sk$;uwHaJJ@N4eBe>#Q9gA%3{N+rO*|5K9IfP~YG?F|n}L^V zeX3Ag)i2p@yv-oQ%c57XK;FS)97c`B(#I%BkBcz5#AqP-#bqbdhKjn`j>;Nt#8Jjc zi!tIN*%TwXT8@74n^9PP$(HMQ$a{);WfK=cI%mPlJ6_%bb?4MnXdpaol10|XQM*3p za+J+RV^xkeape$67DjZnEL|kuaV|=-Vnniui)5EB&TaAxPx!z_hh$+j6V;b`zVrni zEmEl9ORXgQLS=zF>9SobEu3)RLj^71T4P=acY=RZXto!^?BIK83#=Ac;4(x^dfUyE z$+w;IiK@okd|IxyMSrwME_;-#T(Stafy)C-M&Ob~R0n5Om%MPop2Fw!9DA$II7ssR z!nH3@iLHUFmPOl%6D&Y(!$eM#PHQyU#AOs0Rb>uf*s3kcCBN-92^Fg5kU9Egk0iTp zuyn}?pc5wms~7E6u32$y$F(g`31b1}l^ptD7c@u~QAFej$B7fBOG!EX@_eC2gxGrd>olRnSlNiClC(S2K50+*UWhF3d`4KfQ zI(br7Bep|c>he)Do8(Apj&_L0Je_b8j!;L$Q4X1gSNVg6;UPS+h{U`D3~h=rFy#SP zjEIJloX0Sw9_1tS@m7SZ&CVT|w)5o$7kK3FAyt?qEeokh(~sCyZll4%s0p*N#N|*P zoQfwMAq{LVC=Bx}pP)mFwCz;QE1boYwIs{7ErLGT%|_WcF9TbY%NP5=4bGZT78gaF`74*I zuPRp{P(A7LN0J^%xn+-fl#O#2(S9}Gd4c*-xf{vhn*j}dT2WjKNS2Ux$q=W{mPMaz zhpFonE|Tn`)8|o~2D1svSZkU~l~34s!=$sakdVv>rGzljjc8GCWU%@Yl(*#OqaI^o zj);{WF$w{1m~4_QhJyLoC%6k>=T~{>1)dMD?&(v^!t?OWVJ%vyibOkII8>icR7i+{ zUk;LC$z>O5@R*C{u$;0+ycy!c8WB{@D<4fbw0GVqm-V3~#hbukRZ}rwUUBJ)5m}$a zZnH7Q?3__}%S*5@mY=en&+{rjcY*rmVN+^WL-ek|^{%jCW|1tL1~{}AP6bA14i(}m zC_iC#N;jdrD2HN7)mT+mtaRm)EI?0-;()TLuGy)pruq}97u8a%`4vcvY^TYEkx8UH zvMX1>&)W>LTP*SNiR6zlrq}sPM7xo(LeE_wkSh2P7pKGldx&>Ed?{EV95S6vIbaT9eg=ifY}B~2P!>j_Nb)>|;6DU$*~Dpv`jRXzVr8?52#EQoLl% zfPj#m0#DhbN1_Q?=Zp(HJe`sw&CwTQWXn2mb0omzd-o>R?@xsJ@qy1`3w2Mcd;!Ng(Gxp2Z*?!syBN{G{-@J28zUQ=R_&I_zHk65z zXhxLPNJby#=J0y@&a_a-R>jDtJZc~#Mm~|6$rLN)j4tK9X0D7l<(Vt}(gOm#S>Yzh zAMIzZgt~K#6RyTSlpk}%(IpogXXb|!Cib|E6EDnMiJPMi_S=PaH2g*$ zE>PdREG$qggvwzFqCPhV@C1)DXDBK;=AeS0j(E(?!Qv{mOxQWburZKlq|ITU-tiWcGt}Jk|KGK z-=TktMfok~C?+S10{@ouDfs-CP!yjB+#j<7ck1focVZM@X};S((!3%2M`L?7_p0ZZ zTQYcL>;tjq>2ogQ9N-}yi7IMSEJ;B&;Pvd0uQsvLMReII*+_ZIFO#r9zP_1^*W-DE zl_4vWN)8l?1v$hXGZQ{J)8dH)hCj7_OtwO;fsIm3OwTq?Xo!NYVKESyK0Y29L^q? z`mufQ0S_&b%udx7X)!VcSyCYB*<@H)ueLuNnCB5)3H`nka z?cr3OAlbG1upUVSCiq8~#($mv#?f-N=Y9-Nk= ztl^nU^Mbt&02IO;u(_&uy2|qcdbq&dad9{r9z``Txw z@Ih9Nu?!>WBEI50eu=N#7#EinaQ~a~-Du)%on6UiyB=r3L$M-?ydAp2Ze)-or) zJq)Mem(Jn*(&M$yUU(usjJ~@Y1s(!e1x`=p&$n;tKh)fdn(~Wq)uC*%S4s0qPga=i zD!f$f2kM949SO>Jd3FtMcI~2@ZNe$3fY(Z4Z9}y3r0cke<$v5cIC?JjNATlo*Wu{u zK0MUn6GWTcVR6+KuhMgR*k4wOoZu>EbOZU~sq`WDjVnisjpFUD@cc|=?F4@%c}xFh z!e8>KC02u^i>$8tIFB?rR7awv33!p0i@fAoBo|7R@5)6N^_;dS%O{e4j`o;CI`-_r z`V^il_+ig)P{H=p`o&i#&f{0d7I9s~%Aw_5p5Usf$S$%R)K!m+J#Y~e4a=`(g|Rcwu+#$5zqAdy2&UKRF%T>zv1@MteB5 zbr#1bmvH;o#?pweYDT#(S|dX5v0Tb4pDg0?U$o9bE!oD#mPV#;%5R^!Ir|^3?jCk2 z?sX_;p?l)-&0fdf(SHNDn1oMwu8;Nk7FWwNliD4p0-h$|+Nbl@WR3n@uv5Izhw z2;-2gFF0}TrL1Y24fPD9(9#9+;HJb=GK0kgZM+Fjuk68{zK-{Dp09GKEk2bsSK$5B zkB|1+r*?VzH^aK2NXWx9&_2aQv|6z}RJ82LH{rnUTe5q{ub=!ASHtnb6}Q82 zeFeX+oICC|{T&w{9=Uz#2cu8UOu$*ZE^1D^B&Opks8CSPB5GD!^|dT<*|ZbF%r`T! z$9`8P=hpVQnTZ8Av(Dc_Bm-72EU4i!`XWyHpb)W=Man^yHz71^Ha0(U9lo6&#D{&$ z-AvD?f#PW{P|*GSU3ahZ#rJ)G_V}(2KG5r9OnFpK4J(Iks^n&lTHeZUpWT%muaD$^ z!mq!3`F#;yRU}XN44>J&Jo2VXr)nR)_;~%B%HwroSV>D%F7@u&6HUA!V6O|q<HABcTYh@s zl6qGk{L$2!Ie&#l3)7>+34WIl_60v<5^_&EX)RBSk-QsQYZ%Wi`%k(R{|i$WaErw;mms^Dz`YS)Pj0}6 z^9lD>IQMBrJxv0i%$cIVNBCIWU%2G|rlKVIkA=fe(b+CBPr?_U@f-dxW#^VYbZI_) zXlxTXEI&JDk@QG*OKo@WlZ^w}-=Dp4cgx~v7gsML$wpG><7uj0q>!{UrbP*%81hrF zn~(^+s{ywlgcJtJsSixqCGTonb|T4~ogeU*UCx-CcGD>%D-^GC6bk3axH>g|#D%{f^$^Av{?pW`n zKYHou+UL+8J-fIuTg2YPlQ&~edVT*RMe0A`k|c%qu2-z(co}HS000mGNklNceg$S`OK|)5zT07XQf4;yyQ$e4Ve=N&=S6(BkWOYtqHf zVJSbFuJsR%deoE?<;bd`9LgV??iWbX85~Mqmml@@>=Q0YZ*{;F66P$hROHDwYL{yF z^-tITaKue}#am8Zw#l4VB1QbaX7fHshU0gI5 zOb!h3vSV=(p}6cNjzLn@W<|8uq=eiFeoA*(VbCqbQ0)d_}c3GWWR8YR9`*YG1tggW4Z- z*09CWp;rpZC8B6HlR1NN8r8SSv{5z8fNQP>oXt_n@`=((6v^l)yp)$ri+XCg%owQR zqEhdzBTY}@PMpl|>_3Yph_^)(oZu6*0v_be)VX&gx&Nurb^oc_ zmjAm+>VI||lm8$Y^*@6o`>PJg6nGH3> zU5z*O?#%LKKAsHP;jAvs-0V->>=LANaT2Y6%37xU$@;k>sdZ48v%L83k`qadTymsn z^J7b#Ay|DE79%c;FzGo=7T&)#L3;D(1^g_o;IQoSi-g^pTO}<43T;V5@4cs+ycKV~~Q@BY_C$L1^M2C91AX@`f2n@i`sR%mUOg&Sy^G7o7OWTP@=Fh?*`wlE zCfF&^Dcos(B_=p_TVBqh+$Axn4%@VrWCaw*#rW>BGd!k|jJNspPGc$Tg0TciW&y?c zAHz4?c<;A;E#VJ(510Er#g_lc@$>j(dU^8J#G$2JYKG|)h586G??#^NP2<~}NPoBA zO8-w6oj=^{;Hh5H%9PiDETx#SeVD2r%x|5#vH5XVD?V5h*+J$7pS&w>1HaWhmwwao zE2xZ-XvBGp>r$0DLs*s^+)`aL(AQ*#)0U21+5R3HgCG z@6@vMN{WzN3FW6sUx*7>VC$yt)3qD$U;UW>UDT2*!Vu9)`{}KH&T>YMf*#?ll0pu z&@!d)gtaj_s)Vw%Y1Jvtq)ar7TZV?0SGIOrez-Q;7;7NUZmfNG^NqOQk0lQjN$~?# zW=)^)bMg?f^zQLz{3pj(+kd^0x48)LXp@-9m}&!KV`w+V+kb7M?mwQ?+})1f#QY*j z_^IR_+<9s6NV{#e?U!I{w`Jv}-Iidqyi7)QSws=!;E`RAr?w8JUoK|w zg(C64#}@1xn4Prv9=yYK{U;h-|I=gr{BP8I*^l&>@t2!v`)@Wz{ZA+0;*jxopPzEp zIaYk(en0PIUtD`8eXz^dd?e*ZA8RcyvsgT-OZ0jWD7V|xL}b1TzG-?usDQV--G&`x z?RFbHO&wm^CZ1bGUqWc({V0##c)Lfl4cuu=6|D{3l_}`)Xw~6bY{HX*Jk(`ViWZBv z=$D=|R$Rj>siJbMHe(qe6s!P`PxP7)6E ziR5c>4v~Dqi@-y>BC|6*ffUd4ztnjKXkZ0(_!&YoPktov1e=*6>0Gh3n$i3!rZ`MR z8_fg?KSi7JnM|AVM6YD|M6$Ienp-37+QVzp_@CXW+80Jzwa=|JI-jf6Yrl~?{LTpI zbK$QHaPwtIM307f=vair=vCJWxNH%dJ+LcZe z>q%x9bMna;U3FSi6|20e;pL;klUc%>BD?B|)2LCHhZ&gAZ>(}@K+>2jR6{ufj!pyf zLQysmHH#G=5dG_G@OW2vePtgmkXo{ZO(kxzITaK|oo;K$^A5-_U4GG$nqzXwYA#ZX zb`7YQh}YAmCqkH*Tlu7Gc-gcZlNlsgc*|im^ct?ZxCq55-r`tKvf=qQ1s)d1RFJN` z!icM1$s*;Eu35xIiV+QZV1Cpq!SZ)uq$8aZ;HO5O&g<^3IY`R^{Ju%|k)TH!qlMG1J?mBtYBhNQFe3eUw z#nB^`q{YTQX|??7CGoElmq2)&wqW>dB*U9~{q+&yk% zeFR=j=M0X`7>|)m7W`qM(Kk^pIQYOP640`O-f_Z7P8lPTS|Y^=W5gVh%NKi|uvtUTQzb_Egw?lt=kiK%=A&rSzKBTw^Ls$(-ezW5|UoYWyiW5d; zehS;L(iv}YQ7-pF)oR2zVTQ3S`pSNYpP%Osc?Il1&$~bzbAD?A_ShK&Jk}?< z{IQ3DY&|HaUP;DLSAD@1FMNDL)St!i;mKCGJnllco#^=&Nc8+2ZmU*nZBm34V9&!Q zW##SB#F6CR0E@_1tj?mVpN~9 z&Y`bmYm%+0IOZ^)up)WM%_fkDy37(I$uAn%2N()Gg{%5arm@M-af>N2G}(QWUpH3V zY`jPoWi|8{?s020z2Nzx3sm%X&ti3xzigD)^F!Mj!UTT|b72I?CSTH+D73`*=pcn z1lh^ik75-gihXJh$#qQRPoB2NMeY}*Yg!=q8F23O<(#&QF2FnSU&`XfP-NszPN)}%$?UE-d z^MHSfAwP8*%izqohU3~6s6PIAnyx^UUK0RqNn_ddzo8gHy8}Z|O zx=I(sbMw<7K*?k`TxnB{RmPc(3oj_k6>bhC+7u(w4aw;jHsU19-m&}>kSlszkYQY35cEry zOZM@2LugkG*_v{e6l+>e_7m~4i*mjN_A`R<3W@$zVwFodwK!q4yhlISS^{Sj_FCzs zEl^o`cOHETOXH&x{8wyli#9c|&dHl>bev6VQR31it4YGJ&VLIMmt6~6=Pv~58pd+) zqBt$2$$a3p3gr`sy5b1oJ4^#>six(oEWCV0c_V^PIFe3c#0*a%;PpFg4Smk?=)?bJ z36B5nP2Wp7U-|--olE@Q2i%ey!)7Dp&y%t_4It95N58r5M1pG(qKGvNm!pNq7Wldo zMlsTTO5K8?bXX^Toq_Ucc)6OiHH71hp-U#n7I3CAINW4HEr)6-N8ms$o!EGqv*6gV z@X=I;T`Nnj6}S_QzY|y2CYviZAvqHd02 zbrh?Q-Bo_q$@wzq6)jNp&b-TQKJh_Z?)Sl0T9!zh1|pzgOKjSnHH;{{hr*T^JxNrB z)$+vo_|T&Gb*C61#bpeBSpvx(ZIahnO~EkEMgkb#HmiH(h#K0ku|@zh?O%Rbl3bdB}6{|_0?Hmng7g3-RArqZecM&XR}xS z+$rbM0>Yr+4{AP9+)#rHmW}h;XP46WEj=ZY0#1G{)o<}LRm2#1O_$94NxfMphpc&)?BnP>=GxTJ)+eFgA7mPS@2Umwj_}v$y886b&5x;#yvOG=_d| zgRh>j8b0`&kS=+HivpSoFNr=rts#E6_|nP0Kbx6);782D>3d$MU)a(0s`1xkfw8-= z$kqbpu(&ze+}Oxa6#T%)I2UCEn9QY7LXmbI^teTz+4-oJx?XL=NH-j#x+I=m!#1&1 zYkJk}+>6=~e$@jRGr|z1#*!Sa$y$y6p_J1K1TV1E6 zid=o13)T|LNG?it!w^?mVY)3F&_a7|Ew8y|x970*#QWSO)#5*b4F20~jC(Ek4`qSX z#`$V*kyc3yr*DHTbi|FXZl&X0{`an4e|$XK$k&T*cb$uZ!}vH{y(l*McX$S53C6dC zy}Y{K!2%W^dEfZ6`fOu9<=m>)`eDd_1^@v6|LlgnNdN!<21!IgR09CWe_KFxrAOre O0000G-?y8@1Oi&CBX))olikf`eZM+tMW-@4S_B$2qr9~;3J4}@NQ9;ndB{^9 zF@U@bOnijLlwvE7DQfG`Ixs@A&wy2C1mzJa2?@LVefOT8Z#UT{0o#Pysef?iobTRy z&bjCOzH{$A-zEZn!0i&ai`|?{nft$FZonc+&;PAC#Qmy#CI2l)qSQb}y6V z`BmoNJ6V6R!0dIs-qw37NcWV}ZSI+}HtURPBNQJXLL~tW2T=Dg4;PAF1;9VGWXLw} zo8}VVy7(PXLA{RE;|1=ibah^dHQ{(01(l+|f`TFh0AgZ32}GX)!Y4fb8zG!z73&x> z;$%g**E>)~d>gG_x!!8N+}8Dk|1CIAAvs)A=w|n1s^u`p1c}v*<+=nY#1nv2had_< z<=U0OQvLQ|v3^%@ntn%cihd>A-3Nd>0icE0kmorBP^UZ6PZiX~*ZMZcZz_C`G}eD7 zT@ajSEM1lNG>upNDGV0vQ$UX=JRn#A7*K!{!jkujuUq>)Vmp5-8i z*uNrTmx!~YXdS*`ck8V@OHc|NXu#P(;M7Zg?2rby!YhR<{06R1SbonB|1d|jf2bpu z()3(F{E*#qXqBzdsOE8kQs5B4&Xm208X!1Of}^mIw1n0F=#ldWa$+=|A%OZNLof<} zcybINItHBC5j<{YW}^F0QK+Fmoy?m^Puwt-vRU}Ok!wry<-RRuNt!875MYA>@Ue3Q z#M2gUH;)sP0@qlJpK5Wq1`y^0;#uGvGWP>P8={g<4*B4?F0xM7QgV8$V($EE>nJ)UX9Z@l?=<$opfE}ZRhReE(;J34uMG}$e8##9Qqm!- z@woB`DqASu7E zlunRQ0xifV`f4CT1XR4H$&@m$;c-19Q0SQS;b7!~&eC=&_%rppez#fd+Y|G)i+Fka z2qipB3bL(qD0YpeJKM!wy3j&n7Z>3x%&SE@Aim2{!A>QBV6cF;u|2SRn;AX=ibei$ zn!!c*itw1UMqA#UeSb9X$EY=h5Hdj`fA*3Vsmw93?MV@U67YcQDOsBHYZ}xc>)aon zg0WB~7IA8{zL_EekX{0ykNGTp%y!#2SE`6oGD=AklH7O`l&sB>f9}ZZpTX zyCfgqfUSpWV7_L-Dq@hf5&<-&sT=tx(+qcsoSI)sIZ5l@J$-BAH+gEzVoh14nh<%s z{fPq4**;~Ri!DF+3uEQ}N3gB4S37>^Iq()xXd`|dxfT{^5|$~VFKi=rCP<0CQmH3g zWi;JgVLh6-rSRP?k)=0dMc#F?OlkOtK**8=$hU(?selRkqQJw(8{y%7n(VmUJ=t-S zGA^!NZYpm{U=4oTSgpU+)-2{qfZqWrlNTV@CkI;E^*ktbRmx)TY-@N&=`QM<93`I| zD>=wBV3K7(aqigm-)>29;`!xzj2?O&4}|-Qxt0{mg`m&*5Zf13@PWy)2n!qzW0WK2 zoDc=;G15f=JI>^nK&2E&rRq`Fm-vhHx&FtqKM#(?)c4a4aPJ<{eLLb~GKDqOyX)L| zTV^x+usZ-EXa#$yAkRIPUcT;Wy1|}yVa{gbLOd0mt#54B#e8X*Z<_?)wA)a7VIttt zq7)sGQePK8r_T*daBgjQ0#A3&Qu`X<+j@6X%qnIC18tdxMyuW1oC2p?P@@2Xwve|l zjqBdf+=(*$71*WvLwhTzC71VYYeKA_dWlfGRcMgG z3E|zB#{r_%2k$p_?!N`ic5_Hz=$HVYYOKMdjc1`65!Qnc$LzBOq#UdoXn`8n&^X`^=7e@)?>VV0|fB};mEx8f7e>g)&7T^E9-}3o#^h8O}dMCUWYQY z29GqZfYnA!ECUjINQuN7@!9Odr~DpQxh(U{w8pt+6W>N&(~UgU@f*D>tO;>pl@e&T z+hs)9(GV;KwLR+87yE}fHXIz8aTGe;*v@Wj^Um{bVFUvt-UZO7G7A@Rl0u_nxUn5C^QGx0JbcbsCIGSHroLT(79Y(0Sc}H;6ErCJUzp}D4thAbC~zs?d{!D~WgPXFV|}31*x@h6?SZMrj^HE= zd^QF7UlPbQFJ;~9!G8y?*Wr4%;1amrU%4{? diff --git a/f/web-kboss/src/views/homePage/detail/img/5.png b/f/web-kboss/src/views/homePage/detail/img/5.png index de53a08d50da2ec5ab69be036650984f9571a4aa..8e1a5f170d7ef1d2bad83ae1e6c7b83b0bd293c2 100644 GIT binary patch literal 8500 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 diff --git a/f/web-kboss/src/views/homePage/detail/img/7.png b/f/web-kboss/src/views/homePage/detail/img/7.png index e838b200183a98582ddd832766339e9202c4a485..15e949bd2735a0f90db5b9a28ef5be13f2687ad8 100644 GIT binary patch literal 8539 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 LNkvXXu0mjfrpQ8& diff --git a/f/web-kboss/src/views/homePage/detail/index.vue b/f/web-kboss/src/views/homePage/detail/index.vue index eeaa2e4..88278a0 100644 --- a/f/web-kboss/src/views/homePage/detail/index.vue +++ b/f/web-kboss/src/views/homePage/detail/index.vue @@ -550,8 +550,8 @@ export default Vue.extend({ } .function-icon { - width: 30px; - height: 30px; + width: 100%; + height: 100%; } .function-content { diff --git a/f/web-kboss/src/views/product/mainPage/index.vue b/f/web-kboss/src/views/product/mainPage/index.vue index 130f0a9..30ed540 100644 --- a/f/web-kboss/src/views/product/mainPage/index.vue +++ b/f/web-kboss/src/views/product/mainPage/index.vue @@ -83,7 +83,7 @@ v-for="(item, index) in todoList" :key="index" class="todo-item" - @click="handleTodoClick(item.name)" + @click="handleTodoClick(item.name)" > {{ item.name }} {{ item.count }} @@ -142,9 +142,9 @@ export default Vue.extend({ } }, created() { - // 移除 initMybalance 调用,因为现在使用 computed 的 mybalance - this.initMybalance(); // ❌ 删除这一行 - this.getUnreadMsgCount(); + + this.initMybalance(); + this.getUnreadMsgCount(); this.fetchTodoCount(); }, mounted() { @@ -186,8 +186,8 @@ export default Vue.extend({ const iconIndex = index % this.navIcons.length; return this.navIcons[iconIndex]; }, - // 移除 initMybalance 方法,因为现在使用 computed 的 mybalance - async initMybalance() { // ❌ 删除这个方法 + + async initMybalance() { const res = await editReachargelogAPI() if (res.status) { this.mybalance = res.data From e9b0e01a5337c92a94369f50ba0fd40517d6cd73 Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Fri, 21 Nov 2025 15:12:47 +0800 Subject: [PATCH 3/6] =?UTF-8?q?baidu=5Fsms=5Fkafka=5Fconsumer=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kgadget/src/baidu_sms_kafka_consumer.py | 285 +++++++----------------- 1 file changed, 86 insertions(+), 199 deletions(-) diff --git a/kgadget/src/baidu_sms_kafka_consumer.py b/kgadget/src/baidu_sms_kafka_consumer.py index fbc1202..399c421 100644 --- a/kgadget/src/baidu_sms_kafka_consumer.py +++ b/kgadget/src/baidu_sms_kafka_consumer.py @@ -4,8 +4,8 @@ import os import json import asyncio -import datetime -from sqlor.dbpools import DBPools +# import datetime +# from sqlor.dbpools import DBPools # from appPublic.jsonConfig import getConfig from appPublic.uniqueID import getID as uuid from confluent_kafka import Consumer as BaiduKafKaConsumer @@ -18,76 +18,78 @@ from appPublic.Singleton import SingletonDecorator from appPublic.folderUtils import ProgramPath from appPublic.argsConvert import ArgsConvert -from baiDuSmsClient import send_baidu_vcode as send_vcode +# from baiDuSmsClient import send_baidu_vcode as send_vcode + +from aiohttp import client as aiohttp_client -def key2ansi(dict): - # print dict - return dict - a = {} - for k, v in dict.items(): - k = k.encode('utf-8') - # if type(v) == type(u" "): - # v = v.encode('utf-8') - a[k] = v +# def key2ansi(dict): +# # print dict +# return dict +# a = {} +# for k, v in dict.items(): +# k = k.encode('utf-8') +# # if type(v) == type(u" "): +# # v = v.encode('utf-8') +# a[k] = v - return a +# return a -class JsonObject(DictObject): - """ - JsonObject class load json from a json file - """ +# class JsonObject(DictObject): +# """ +# JsonObject class load json from a json file +# """ - def __init__(self, jsonholder, keytype='ansi', NS=None): - jhtype = type(jsonholder) - if jhtype == type("") or jhtype == type(u''): - f = open(jsonholder, 'r') - else: - f = jsonholder - try: - a = json.load(f) - except Exception as e: - print("exception:", self.__jsonholder__, e) - raise e - finally: - if type(jsonholder) == type(""): - f.close() +# def __init__(self, jsonholder, keytype='ansi', NS=None): +# jhtype = type(jsonholder) +# if jhtype == type("") or jhtype == type(u''): +# f = open(jsonholder, 'r') +# else: +# f = jsonholder +# try: +# a = json.load(f) +# except Exception as e: +# print("exception:", self.__jsonholder__, e) +# raise e +# finally: +# if type(jsonholder) == type(""): +# f.close() - if NS is not None: - ac = ArgsConvert('$[', ']$') - a = ac.convert(a, NS) - a['__jsonholder__'] = jsonholder - a['NS'] = NS - DictObject.__init__(self, **a) +# if NS is not None: +# ac = ArgsConvert('$[', ']$') +# a = ac.convert(a, NS) +# a['__jsonholder__'] = jsonholder +# a['NS'] = NS +# DictObject.__init__(self, **a) -@SingletonDecorator -class JsonConfig(JsonObject): - pass +# @SingletonDecorator +# class JsonConfig(JsonObject): +# pass -def getConfig(path=None, NS=None): - pp = ProgramPath() - if path == None: - path = os.getcwd() - cfname = os.path.abspath(os.path.join(path, "conf", "config.prod.json")) - # print __name__,cfname - ns = { - 'home': str(Path.home()), - 'workdir': path, - 'ProgramPath': pp - } - if NS is not None: - ns.update(NS) - a = JsonConfig(cfname, NS=ns) - return a +# def getConfig(path=None, NS=None): +# pp = ProgramPath() +# if path == None: +# path = os.getcwd() +# cfname = os.path.abspath(os.path.join(path, "conf", "config.prod.json")) +# # print __name__,cfname +# ns = { +# 'home': str(Path.home()), +# 'workdir': path, +# 'ProgramPath': pp +# } +# if NS is not None: +# ns.update(NS) +# a = JsonConfig(cfname, NS=ns) +# return a -async def time_convert(resoucetime=None): - if not resoucetime: - return - utc_time = datetime.datetime.strptime(resoucetime, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc) - beijing_time = utc_time.astimezone(datetime.timezone(datetime.timedelta(hours=8))) - return beijing_time.strftime("%Y-%m-%d %H:%M:%S") +# async def time_convert(resoucetime=None): +# if not resoucetime: +# return +# utc_time = datetime.datetime.strptime(resoucetime, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc) +# beijing_time = utc_time.astimezone(datetime.timezone(datetime.timedelta(hours=8))) +# return beijing_time.strftime("%Y-%m-%d %H:%M:%S") async def baidu_sms_kafka_consumer(ns={}): import os @@ -110,158 +112,44 @@ async def baidu_sms_kafka_consumer(ns={}): 'auto.offset.reset': 'latest', 'fetch.message.max.bytes': '1024*512', }) - print('开始创建文件夹') + # 订阅的主题名称 consumer.subscribe(['kaiyuanyun_msg_topic']) - - files = ["baidu_kafka_msg.txt", "baidu_kafka_id.txt", "baidu_kafka_error.txt"] - for filename in files: - if not os.path.exists(filename): - with open(filename, 'w', encoding='utf-8') as f: # 'w' 模式会覆盖已有文件,但检查后使用是安全的 - pass # 创建空文件 - else: - pass - - # total_count = 0 while True: - i = 0 - # if i == 0: - # # 写入文件记录轮询开始时间 时间格式: YYYY-MM-DD HH:MM:SS - # with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - # f.write(f"轮询开始时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") - - msg = consumer.poll(0.1) # 单次轮询获取消息 + msg = consumer.poll(2) # 单次轮询获取消息 if msg is None: - if i == 10: - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(f"轮询第10次消息为None,{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") continue elif msg.error(): - # 写入日志文件记录错误信息 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n") + pass else: - # total_count += 1 try: - # 解析消息内容为字典(避免变量名冲突) - msg_data_ori = json.loads(msg.value().decode('utf-8')) - msg_data = msg_data_ori['messages'][0] - messageid = msg_data.get('id') - taskid = msg_data.get('taskId') - - # 读取文件内容进行检查 - with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f: - content = f.read() - - if messageid in content: - print(f"文件中已存在 '{messageid}',跳过写入") - continue - else: - # 追加写入目标内容 - with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f: - f.write(messageid + '\n') - print(f"已写入 '{messageid}' 到文件") - - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(str(msg_data) + '\n') - - db = DBPools() - async with db.sqlorContext('kboss') as sor: - # 1. 去重检查(messageid和taskid) - exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid}) - if exist_msg: - print(f"消息id {messageid} 已存在,跳过处理") - continue - # consumer.close() - # return - - # 2. 构建小写key的ns字典(完整映射所有字段) - ns_msg = { - 'id': uuid(), - 'messageid': messageid, - 'taskid': taskid, - 'userid': msg_data.get('userId'), - 'accountid': msg_data.get('accountId'), - 'usertype': msg_data.get('userType'), - 'receiverid': msg_data.get('receiverId'), - 'contentvar': msg_data.get('contentVar'), - 'sendchannel': msg_data.get('sendChannel'), - 'content': msg_data.get('content'), - 'messagetemplateid': msg_data.get('messageTemplateId'), - 'isvirtualstore': msg_data.get('isVirtualStore'), - 'channelmessageid': msg_data.get('channelMessageId'), - 'channelstatus': msg_data.get('channelStatus'), - 'majorcategory': msg_data.get('majorCategory'), - 'minorcategory': msg_data.get('minorCategory'), - 'status': msg_data.get('status'), - 'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None, - 'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None, - 'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None, - 'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None, - 'valid': msg_data.get('valid'), - 'complete': msg_data.get('complete'), - 'disturbhold': msg_data.get('disturbHold'), - 'sendcomplete': msg_data.get('sendComplete') - } - - # 3. 执行存库 - await sor.C('baidu_kafka_msg', ns_msg) - # print(f"消息id {messageid} 存储成功") - - # 4. 触发短信发送(当sendChannel为MOBILE时) - send_channel = msg_data.get('sendChannel') - if send_channel == 'MOBILE': - msg_content = msg_data.get('content') - - # 判断验证码类短信 | 通知类短信 - if '验证码' in msg_content: - sms_stype = '百度kafka普通验证码' - else: - sms_stype = '百度kafka普通通知' - - # 查询用户手机号 - account_id = msg_data.get('accountId') - user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id}) - if user_local_id_li: - user_local_id = user_local_id_li[0]['user_id'] - user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'}) - mobile = user_mobile_li[0]['mobile'] - - # 调用短信发送接口 - kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content}) - if kyy_send_status.get('status'): - await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'}) - else: - # 记录错误日志 短信发送失败 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n") - print(f"短信发送失败至 {mobile},状态: {kyy_send_status}") - else: - # 记录错误日志 用户未找到 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n") - print(f"未找到百度用户ID {account_id} 对应的本地用户") + method = "POST" + url = 'https://www.opencomputing.cn/baiduc/baidu_sms_kafka_consumer.dspy' + header = { + "Host": "www.opencomputing.cn", + "Content-Type": "application/json" + } + data = { + 'msg': msg + } + async with aiohttp_client.request( + method=method, + url=url, + headers=header, + json=data) as res: + data_ = await res.json() except json.JSONDecodeError: - print("错误:消息内容非有效JSON") return { 'status': False, 'msg': '错误:消息内容非有效JSON' } except Exception as e: - print(f"处理异常: {str(e)}") - import traceback - with open('baidu_kafka_error.txt', 'w') as f: - f.write(str(e)+ traceback.format_exc()) - traceback.print_exc() return { 'status': False, 'msg': f"处理异常: {str(e)}" } - # 记录total_count - # with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - # f.write(f"本次轮询共处理消息数:{total_count}\n") consumer.close() # 确保消费者关闭 return { @@ -271,11 +159,10 @@ async def baidu_sms_kafka_consumer(ns={}): if __name__ == '__main__': # p = os.getcwd() - current_dir = os.getcwd() - path_parts = current_dir.split('/') - two_levels_up = '/'.join(path_parts[:-2]) - config = getConfig(two_levels_up) - DBPools(config.databases) - print(config.databases) + # current_dir = os.getcwd() + # path_parts = current_dir.split('/') + # two_levels_up = '/'.join(path_parts[:-2]) + # config = getConfig(two_levels_up) + # DBPools(config.databases) loop = asyncio.get_event_loop() print(loop.run_until_complete(baidu_sms_kafka_consumer())) From fcbbb6056faf7f0bda59579af4f0f95f5d24e1f1 Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Fri, 21 Nov 2025 15:25:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E7=99=BE=E5=BA=A6kafka=20=E6=8E=A5?= =?UTF-8?q?=E6=94=B6=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- b/baiduc/baidu_sms_kafka_consumer.dspy | 303 ++++++++++++------------- 1 file changed, 145 insertions(+), 158 deletions(-) diff --git a/b/baiduc/baidu_sms_kafka_consumer.dspy b/b/baiduc/baidu_sms_kafka_consumer.dspy index d73988d..74271e0 100644 --- a/b/baiduc/baidu_sms_kafka_consumer.dspy +++ b/b/baiduc/baidu_sms_kafka_consumer.dspy @@ -6,29 +6,30 @@ async def time_convert(resoucetime=None): return beijing_time.strftime("%Y-%m-%d %H:%M:%S") async def baidu_sms_kafka_consumer(ns={}): - import os - consumer = BaiduKafKaConsumer({ - # 接入点 - 'bootstrap.servers': '120.48.10.223:9095,180.76.96.108:9095,180.76.147.36:9095', - # 接入协议 - 'security.protocol': 'SASL_SSL', - 'ssl.endpoint.identification.algorithm': 'none', - # 证书文件路径 - 'ssl.ca.location': 'baidu_kafka_ca.pem', - # SASL 机制 - 'sasl.mechanism': 'SCRAM-SHA-512', - # SASL 用户名 - 'sasl.username': 'kaiyuanyun', - # SASL 用户密码 - 'sasl.password': 'Kyy250609#', - # 消费组id - 'group.id': 'kaiyuanyun_msg_group', - 'auto.offset.reset': 'latest', - 'fetch.message.max.bytes': '1024*512', - }) + # consumer = BaiduKafKaConsumer({ + # # 接入点 + # 'bootstrap.servers': '120.48.10.223:9095,180.76.96.108:9095,180.76.147.36:9095', + # # 接入协议 + # 'security.protocol': 'SASL_SSL', + # 'ssl.endpoint.identification.algorithm': 'none', + # # 证书文件路径 + # 'ssl.ca.location': 'baidu_kafka_ca.pem', + # # SASL 机制 + # 'sasl.mechanism': 'SCRAM-SHA-512', + # # SASL 用户名 + # 'sasl.username': 'kaiyuanyun', + # # SASL 用户密码 + # 'sasl.password': 'Kyy250609#', + # # 消费组id + # 'group.id': 'kaiyuanyun_msg_group', + # 'auto.offset.reset': 'latest', + # 'fetch.message.max.bytes': '1024*512', + # }) - # 订阅的主题名称 - consumer.subscribe(['kaiyuanyun_msg_topic']) + # # 订阅的主题名称 + # consumer.subscribe(['kaiyuanyun_msg_topic']) + + import os files = ["baidu_kafka_msg.txt", "baidu_kafka_id.txt", "baidu_kafka_error.txt"] for filename in files: @@ -38,143 +39,129 @@ async def baidu_sms_kafka_consumer(ns={}): else: pass - total_count = 0 - for i in range(10): - # if i == 0: - # # 写入文件记录轮询开始时间 时间格式: YYYY-MM-DD HH:MM:SS - # with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - # f.write(f"轮询开始时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") - - msg = consumer.poll(0.01) # 单次轮询获取消息 - - if msg is None: - if i == 10: - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(f"轮询第10次消息为None,{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") - continue - elif msg.error(): - # 写入日志文件记录错误信息 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n") - else: - total_count += 1 - try: - # 解析消息内容为字典(避免变量名冲突) - msg_data_ori = json.loads(msg.value().decode('utf-8')) - msg_data = msg_data_ori['messages'][0] - messageid = msg_data.get('id') - taskid = msg_data.get('taskId') - - # 读取文件内容进行检查 - with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f: - content = f.read() - - if messageid in content: - print(f"文件中已存在 '{messageid}',跳过写入") - continue - else: - # 追加写入目标内容 - with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f: - f.write(messageid + '\n') - print(f"已写入 '{messageid}' 到文件") - - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(str(msg_data) + '\n') - - db = DBPools() - async with db.sqlorContext('kboss') as sor: - # 1. 去重检查(messageid和taskid) - exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid}) - if exist_msg: - print(f"消息id {messageid} 已存在,跳过处理") - continue - # consumer.close() - # return - - # 2. 构建小写key的ns字典(完整映射所有字段) - ns_msg = { - 'id': uuid(), - 'messageid': messageid, - 'taskid': taskid, - 'userid': msg_data.get('userId'), - 'accountid': msg_data.get('accountId'), - 'usertype': msg_data.get('userType'), - 'receiverid': msg_data.get('receiverId'), - 'contentvar': msg_data.get('contentVar'), - 'sendchannel': msg_data.get('sendChannel'), - 'content': msg_data.get('content'), - 'messagetemplateid': msg_data.get('messageTemplateId'), - 'isvirtualstore': msg_data.get('isVirtualStore'), - 'channelmessageid': msg_data.get('channelMessageId'), - 'channelstatus': msg_data.get('channelStatus'), - 'majorcategory': msg_data.get('majorCategory'), - 'minorcategory': msg_data.get('minorCategory'), - 'status': msg_data.get('status'), - 'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None, - 'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None, - 'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None, - 'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None, - 'valid': msg_data.get('valid'), - 'complete': msg_data.get('complete'), - 'disturbhold': msg_data.get('disturbHold'), - 'sendcomplete': msg_data.get('sendComplete') - } - - # 3. 执行存库 - await sor.C('baidu_kafka_msg', ns_msg) - print(f"消息id {messageid} 存储成功") - - # 4. 触发短信发送(当sendChannel为MOBILE时) - send_channel = msg_data.get('sendChannel') - if send_channel == 'MOBILE': - msg_content = msg_data.get('content') - - # 判断验证码类短信 | 通知类短信 - if '验证码' in msg_content: - sms_stype = '百度kafka普通验证码' - else: - sms_stype = '百度kafka普通通知' - - # 查询用户手机号 - account_id = msg_data.get('accountId') - user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id}) - if user_local_id_li: - user_local_id = user_local_id_li[0]['user_id'] - user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'}) - mobile = user_mobile_li[0]['mobile'] - - # 调用短信发送接口 - kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content}) - if kyy_send_status.get('status'): - await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'}) - else: - # 记录错误日志 短信发送失败 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n") - print(f"短信发送失败至 {mobile},状态: {kyy_send_status}") - else: - # 记录错误日志 用户未找到 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n") - print(f"未找到百度用户ID {account_id} 对应的本地用户") - - except json.JSONDecodeError: - print("错误:消息内容非有效JSON") - return { - 'status': False, - 'msg': '错误:消息内容非有效JSON' - } - except Exception as e: - print(f"处理异常: {str(e)}") - return { - 'status': False, - 'msg': f"处理异常: {str(e)}" - } - # 记录total_count - # with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - # f.write(f"本次轮询共处理消息数:{total_count}\n") + msg = ns.get('msg') - consumer.close() # 确保消费者关闭 + if msg.error(): + # 写入日志文件记录错误信息 + with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n") + else: + try: + # 解析消息内容为字典(避免变量名冲突) + msg_data_ori = json.loads(msg.value().decode('utf-8')) + msg_data = msg_data_ori['messages'][0] + messageid = msg_data.get('id') + taskid = msg_data.get('taskId') + + # 读取文件内容进行检查 + with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f: + content = f.read() + + if messageid in content: + print(f"文件中已存在 '{messageid}',跳过写入") + return + else: + # 追加写入目标内容 + with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f: + f.write(messageid + '\n') + print(f"已写入 '{messageid}' 到文件") + + with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: + f.write(str(msg_data) + '\n') + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 1. 去重检查(messageid和taskid) + exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid}) + if exist_msg: + print(f"消息id {messageid} 已存在,跳过处理") + return + + # 2. 构建小写key的ns字典(完整映射所有字段) + ns_msg = { + 'id': uuid(), + 'messageid': messageid, + 'taskid': taskid, + 'userid': msg_data.get('userId'), + 'accountid': msg_data.get('accountId'), + 'usertype': msg_data.get('userType'), + 'receiverid': msg_data.get('receiverId'), + 'contentvar': msg_data.get('contentVar'), + 'sendchannel': msg_data.get('sendChannel'), + 'content': msg_data.get('content'), + 'messagetemplateid': msg_data.get('messageTemplateId'), + 'isvirtualstore': msg_data.get('isVirtualStore'), + 'channelmessageid': msg_data.get('channelMessageId'), + 'channelstatus': msg_data.get('channelStatus'), + 'majorcategory': msg_data.get('majorCategory'), + 'minorcategory': msg_data.get('minorCategory'), + 'status': msg_data.get('status'), + 'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None, + 'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None, + 'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None, + 'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None, + 'valid': msg_data.get('valid'), + 'complete': msg_data.get('complete'), + 'disturbhold': msg_data.get('disturbHold'), + 'sendcomplete': msg_data.get('sendComplete') + } + + # 3. 执行存库 + await sor.C('baidu_kafka_msg', ns_msg) + print(f"消息id {messageid} 存储成功") + + # 4. 触发短信发送(当sendChannel为MOBILE时) + send_channel = msg_data.get('sendChannel') + if send_channel == 'MOBILE': + msg_content = msg_data.get('content') + + # 判断验证码类短信 | 通知类短信 + if '验证码' in msg_content: + sms_stype = '百度kafka普通验证码' + else: + sms_stype = '百度kafka普通通知' + + # 查询用户手机号 + account_id = msg_data.get('accountId') + user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id}) + if user_local_id_li: + user_local_id = user_local_id_li[0]['user_id'] + user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'}) + mobile = user_mobile_li[0]['mobile'] + + # 调用短信发送接口 + kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content}) + if kyy_send_status.get('status'): + await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'}) + else: + # 记录错误日志 短信发送失败 + with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n") + print(f"短信发送失败至 {mobile},状态: {kyy_send_status}") + else: + # 记录错误日志 用户未找到 + with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n") + print(f"未找到百度用户ID {account_id} 对应的本地用户") + + except json.JSONDecodeError: + print("错误:消息内容非有效JSON") + return { + 'status': False, + 'msg': '错误:消息内容非有效JSON' + } + except Exception as e: + print(f"处理异常: {str(e)}") + import traceback + with open('baidu_kafka_error.txt', 'w') as f: + f.write(str(e)+ traceback.format_exc()) + traceback.print_exc() + return { + 'status': False, + 'msg': f"处理异常: {str(e)}" + } + + # consumer.close() # 确保消费者关闭 return { 'status': True, 'msg': '获取信息执行结束' From 9cbda277fb6e27e596b3f9a3507dcbbc9e1a9a33 Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Fri, 21 Nov 2025 16:15:13 +0800 Subject: [PATCH 5/6] update --- b/baiduc/baidu_sms_kafka_consumer.dspy | 219 ++++++++++++------------ kgadget/src/baidu_sms_kafka_consumer.py | 15 +- 2 files changed, 120 insertions(+), 114 deletions(-) diff --git a/b/baiduc/baidu_sms_kafka_consumer.dspy b/b/baiduc/baidu_sms_kafka_consumer.dspy index 74271e0..dbefa7c 100644 --- a/b/baiduc/baidu_sms_kafka_consumer.dspy +++ b/b/baiduc/baidu_sms_kafka_consumer.dspy @@ -41,125 +41,126 @@ async def baidu_sms_kafka_consumer(ns={}): msg = ns.get('msg') - if msg.error(): - # 写入日志文件记录错误信息 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n") - else: - try: - # 解析消息内容为字典(避免变量名冲突) - msg_data_ori = json.loads(msg.value().decode('utf-8')) - msg_data = msg_data_ori['messages'][0] - messageid = msg_data.get('id') - taskid = msg_data.get('taskId') + # if msg.error(): + # # 写入日志文件记录错误信息 + # with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: + # f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 消费者错误: {msg.error()}\n") + # else: + try: + # 解析消息内容为字典(避免变量名冲突) + # msg_data_ori = json.loads(msg.value().decode('utf-8')) + msg_data_ori = json.loads(msg) + msg_data = msg_data_ori['messages'][0] + messageid = msg_data.get('id') + taskid = msg_data.get('taskId') - # 读取文件内容进行检查 - with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f: - content = f.read() + # 读取文件内容进行检查 + with open('baidu_kafka_id.txt', 'r', encoding='utf-8') as f: + content = f.read() - if messageid in content: - print(f"文件中已存在 '{messageid}',跳过写入") + if messageid in content: + print(f"文件中已存在 '{messageid}',跳过写入") + return + else: + # 追加写入目标内容 + with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f: + f.write(messageid + '\n') + print(f"已写入 '{messageid}' 到文件") + + with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: + f.write(str(msg_data) + '\n') + + db = DBPools() + async with db.sqlorContext('kboss') as sor: + # 1. 去重检查(messageid和taskid) + exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid}) + if exist_msg: + print(f"消息id {messageid} 已存在,跳过处理") return - else: - # 追加写入目标内容 - with open('baidu_kafka_id.txt', 'a', encoding='utf-8') as f: - f.write(messageid + '\n') - print(f"已写入 '{messageid}' 到文件") - - with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: - f.write(str(msg_data) + '\n') - db = DBPools() - async with db.sqlorContext('kboss') as sor: - # 1. 去重检查(messageid和taskid) - exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid}) - if exist_msg: - print(f"消息id {messageid} 已存在,跳过处理") - return + # 2. 构建小写key的ns字典(完整映射所有字段) + ns_msg = { + 'id': uuid(), + 'messageid': messageid, + 'taskid': taskid, + 'userid': msg_data.get('userId'), + 'accountid': msg_data.get('accountId'), + 'usertype': msg_data.get('userType'), + 'receiverid': msg_data.get('receiverId'), + 'contentvar': msg_data.get('contentVar'), + 'sendchannel': msg_data.get('sendChannel'), + 'content': msg_data.get('content'), + 'messagetemplateid': msg_data.get('messageTemplateId'), + 'isvirtualstore': msg_data.get('isVirtualStore'), + 'channelmessageid': msg_data.get('channelMessageId'), + 'channelstatus': msg_data.get('channelStatus'), + 'majorcategory': msg_data.get('majorCategory'), + 'minorcategory': msg_data.get('minorCategory'), + 'status': msg_data.get('status'), + 'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None, + 'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None, + 'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None, + 'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None, + 'valid': msg_data.get('valid'), + 'complete': msg_data.get('complete'), + 'disturbhold': msg_data.get('disturbHold'), + 'sendcomplete': msg_data.get('sendComplete') + } - # 2. 构建小写key的ns字典(完整映射所有字段) - ns_msg = { - 'id': uuid(), - 'messageid': messageid, - 'taskid': taskid, - 'userid': msg_data.get('userId'), - 'accountid': msg_data.get('accountId'), - 'usertype': msg_data.get('userType'), - 'receiverid': msg_data.get('receiverId'), - 'contentvar': msg_data.get('contentVar'), - 'sendchannel': msg_data.get('sendChannel'), - 'content': msg_data.get('content'), - 'messagetemplateid': msg_data.get('messageTemplateId'), - 'isvirtualstore': msg_data.get('isVirtualStore'), - 'channelmessageid': msg_data.get('channelMessageId'), - 'channelstatus': msg_data.get('channelStatus'), - 'majorcategory': msg_data.get('majorCategory'), - 'minorcategory': msg_data.get('minorCategory'), - 'status': msg_data.get('status'), - 'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None, - 'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None, - 'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None, - 'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None, - 'valid': msg_data.get('valid'), - 'complete': msg_data.get('complete'), - 'disturbhold': msg_data.get('disturbHold'), - 'sendcomplete': msg_data.get('sendComplete') - } + # 3. 执行存库 + await sor.C('baidu_kafka_msg', ns_msg) + print(f"消息id {messageid} 存储成功") - # 3. 执行存库 - await sor.C('baidu_kafka_msg', ns_msg) - print(f"消息id {messageid} 存储成功") + # 4. 触发短信发送(当sendChannel为MOBILE时) + send_channel = msg_data.get('sendChannel') + if send_channel == 'MOBILE': + msg_content = msg_data.get('content') - # 4. 触发短信发送(当sendChannel为MOBILE时) - send_channel = msg_data.get('sendChannel') - if send_channel == 'MOBILE': - msg_content = msg_data.get('content') + # 判断验证码类短信 | 通知类短信 + if '验证码' in msg_content: + sms_stype = '百度kafka普通验证码' + else: + sms_stype = '百度kafka普通通知' - # 判断验证码类短信 | 通知类短信 - if '验证码' in msg_content: - sms_stype = '百度kafka普通验证码' + # 查询用户手机号 + account_id = msg_data.get('accountId') + user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id}) + if user_local_id_li: + user_local_id = user_local_id_li[0]['user_id'] + user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'}) + mobile = user_mobile_li[0]['mobile'] + + # 调用短信发送接口 + kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content}) + if kyy_send_status.get('status'): + await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'}) else: - sms_stype = '百度kafka普通通知' - - # 查询用户手机号 - account_id = msg_data.get('accountId') - user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id}) - if user_local_id_li: - user_local_id = user_local_id_li[0]['user_id'] - user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'}) - mobile = user_mobile_li[0]['mobile'] - - # 调用短信发送接口 - kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content}) - if kyy_send_status.get('status'): - await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'}) - else: - # 记录错误日志 短信发送失败 - with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n") - print(f"短信发送失败至 {mobile},状态: {kyy_send_status}") - else: - # 记录错误日志 用户未找到 + # 记录错误日志 短信发送失败 with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: - f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n") - print(f"未找到百度用户ID {account_id} 对应的本地用户") - - except json.JSONDecodeError: - print("错误:消息内容非有效JSON") - return { - 'status': False, - 'msg': '错误:消息内容非有效JSON' - } - except Exception as e: - print(f"处理异常: {str(e)}") - import traceback - with open('baidu_kafka_error.txt', 'w') as f: - f.write(str(e)+ traceback.format_exc()) - traceback.print_exc() - return { - 'status': False, - 'msg': f"处理异常: {str(e)}" - } + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 短信发送失败至 {mobile},状态: {kyy_send_status}\n") + print(f"短信发送失败至 {mobile},状态: {kyy_send_status}") + else: + # 记录错误日志 用户未找到 + with open('baidu_kafka_error.txt', 'a', encoding='utf-8') as f: + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 错误: 未找到百度用户ID {account_id} 对应的本地用户\n") + print(f"未找到百度用户ID {account_id} 对应的本地用户") + + except json.JSONDecodeError: + print("错误:消息内容非有效JSON") + return { + 'status': False, + 'msg': '错误:消息内容非有效JSON' + } + except Exception as e: + print(f"处理异常: {str(e)}") + import traceback + with open('baidu_kafka_error.txt', 'w') as f: + f.write(str(e)+ traceback.format_exc()) + traceback.print_exc() + return { + 'status': False, + 'msg': f"处理异常: {str(e)}" + } # consumer.close() # 确保消费者关闭 return { diff --git a/kgadget/src/baidu_sms_kafka_consumer.py b/kgadget/src/baidu_sms_kafka_consumer.py index 399c421..03c6d48 100644 --- a/kgadget/src/baidu_sms_kafka_consumer.py +++ b/kgadget/src/baidu_sms_kafka_consumer.py @@ -100,7 +100,7 @@ async def baidu_sms_kafka_consumer(ns={}): 'security.protocol': 'SASL_SSL', 'ssl.endpoint.identification.algorithm': 'none', # 证书文件路径 - 'ssl.ca.location': 'baidu_kafka_ca.pem', + 'ssl.ca.location': 'D:/Code/kboss/kgadget/src/baidu_kafka_ca.pem', # SASL 机制 'sasl.mechanism': 'SCRAM-SHA-512', # SASL 用户名 @@ -124,21 +124,23 @@ async def baidu_sms_kafka_consumer(ns={}): pass else: try: + # print('Received message: {}'.format(msg.value().decode('utf-8'))) method = "POST" url = 'https://www.opencomputing.cn/baiduc/baidu_sms_kafka_consumer.dspy' header = { "Host": "www.opencomputing.cn", - "Content-Type": "application/json" + # "Content-Type": "application/json" } data = { - 'msg': msg + 'msg': msg.value().decode('utf-8') } async with aiohttp_client.request( method=method, url=url, headers=header, - json=data) as res: - data_ = await res.json() + data=data) as res: + data_ = await res.text() + # print("Response data:", data_) except json.JSONDecodeError: return { @@ -146,6 +148,9 @@ async def baidu_sms_kafka_consumer(ns={}): 'msg': '错误:消息内容非有效JSON' } except Exception as e: + import traceback + print(str(e)+ traceback.format_exc()) + traceback.print_exc() return { 'status': False, 'msg': f"处理异常: {str(e)}" From 1c16423a9879c6f4c565916a49a344b6468468b8 Mon Sep 17 00:00:00 2001 From: ping <1017253325@qq.com> Date: Fri, 21 Nov 2025 16:32:53 +0800 Subject: [PATCH 6/6] update --- kgadget/src/baidu_sms_kafka_consumer.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kgadget/src/baidu_sms_kafka_consumer.py b/kgadget/src/baidu_sms_kafka_consumer.py index 03c6d48..f79c419 100644 --- a/kgadget/src/baidu_sms_kafka_consumer.py +++ b/kgadget/src/baidu_sms_kafka_consumer.py @@ -113,6 +113,14 @@ async def baidu_sms_kafka_consumer(ns={}): 'fetch.message.max.bytes': '1024*512', }) + # 创建日志文件 + files = "baidu_kafka_msg.txt" + if not os.path.exists(filename): + with open(filename, 'w', encoding='utf-8') as f: # 'w' 模式会覆盖已有文件,但检查后使用是安全的 + pass # 创建空文件 + else: + pass + # 订阅的主题名称 consumer.subscribe(['kaiyuanyun_msg_topic']) while True: @@ -124,6 +132,9 @@ async def baidu_sms_kafka_consumer(ns={}): pass else: try: + with open('baidu_kafka_msg.txt', 'a', encoding='utf-8') as f: + f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}-{msg.value().decode('utf-8')}\n") + # print('Received message: {}'.format(msg.value().decode('utf-8'))) method = "POST" url = 'https://www.opencomputing.cn/baiduc/baidu_sms_kafka_consumer.dspy'