From cfd0d0f0f2dd60962079c966afaa4cdec1e1da5f Mon Sep 17 00:00:00 2001 From: yangzhe Date: Thu, 11 Dec 2025 09:57:48 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(admissions):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=97=A0=E5=80=BC=E7=8F=AD=E6=95=99=E5=B8=88=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E7=8A=B6=E6=80=81=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/home/admissions/index.vue | 76 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/pages/home/admissions/index.vue b/pages/home/admissions/index.vue index e129c48..b5f8510 100644 --- a/pages/home/admissions/index.vue +++ b/pages/home/admissions/index.vue @@ -18,31 +18,39 @@ - - - - - - {{ teacher.name }} - - - 在线 + + + + + + + {{ teacher.name }} + + + 在线 + + {{ + teacher.collegeName + }} + + + 立即提问 - {{ teacher.collegeName }} - - - 立即提问 + + + + @@ -74,20 +82,20 @@ export default { { id: 1, name: "迎新在线" }, ], teacherList: [ - { - id: 1, - name: "孙老师", - department: "招就处", - avatar: "/static/common/images/avatar.png", - online: true, - }, - { - id: 2, - name: "杨老师", - department: "电子信息学院", - avatar: "/static/common/images/student.png", - online: false, - }, + // { + // id: 1, + // name: "孙老师", + // department: "招就处", + // avatar: "/static/common/images/avatar.png", + // online: true, + // }, + // { + // id: 2, + // name: "杨老师", + // department: "电子信息学院", + // avatar: "/static/common/images/student.png", + // online: false, + // }, ], }; }, From f557d658e706d210178d3b17ed9e622bf88253da Mon Sep 17 00:00:00 2001 From: yangzhe Date: Thu, 11 Dec 2025 16:15:27 +0800 Subject: [PATCH 2/7] =?UTF-8?q?refactor(WebSocket):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=BF=83=E8=B7=B3=E6=9C=BA=E5=88=B6=E4=B8=8E=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 54 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/App.vue b/App.vue index c94eace..c908181 100644 --- a/App.vue +++ b/App.vue @@ -10,7 +10,7 @@ export default { // WebSocket 实例与连接控制 ws: null, // 当前 WebSocket 连接 lockReconnect: false, // 是否处于稳定连接,防止重复重连 - timeout: 30000, // 心跳间隔(毫秒) + // timeout: 30000, // 心跳间隔(毫秒) timeoutObj: null, // 心跳倒计时定时器 serverTimeoutObj: null, // 心跳响应等待定时器 timeoutnum: null, // 重连延时定时器 @@ -114,32 +114,29 @@ export default { // 启动心跳与超时处理 start() { this.timeoutObj = setTimeout(() => { - try { - if ( - this.ws && - this.ws.readyState === 1 && - this.vuex_user && - (this.vuex_user.id || this.vuex_user.Id) - ) { - this.ws.send("heartCheck"); - } else { - this.lockReconnect = false; - this.reconnect(); - } - } catch (err) { + //这里发送一个心跳,后端收到后,返回一个心跳消息 + if ( + this.ws && + this.ws.readyState === 1 && + this.vuex_user && + (this.vuex_user.Id || this.vuex_user.id) + ) { + //如果连接正常 + this.ws.send("heartCheck"); + } else { + //否则重连 this.lockReconnect = false; this.reconnect(); } // 心跳发送后等待后端响应,超时则断开重连 this.serverTimeoutObj = setTimeout(() => { - try { - this.ws && this.ws.close(); - } catch (e) {} + // console.log("[WebSocket] 心跳响应超时,断开重连"); + this.ws && this.ws.close(); this.lockReconnect = false; this.reconnect(); - }, this.timeout); - }, this.timeout); + }, 30000); + }, 30000); }, // 连接成功 handleWsOpen() { @@ -153,10 +150,12 @@ export default { // 收到任何消息都重置心跳 this.reset(); + console.log("[WebSocket] 收到消息:", e); + // 心跳消息不处理 - if (typeof e.data === "string" && e.data.indexOf("heartCheck") >= 0) { - return; - } + // if (typeof e.data === "string" && e.data.indexOf("heartCheck") >= 0) { + // return; + // } // 尝试解析为 JSON(与 oa-web-phone 保持一致的结构:{ Type, Data }) let msgData = null; @@ -169,6 +168,10 @@ export default { const type = msgData.Type; + console.log("收到消息类型:", type); + // 收到服务端心跳响应不处理 + if (type === "pong") return; + // 退出登录通知 if (type === "Exit") { try { @@ -209,14 +212,13 @@ export default { }, // 连接关闭 handleWsClose(e) { - console.log(`[WebSocket] 连接关闭: code=${e.code}, reason=${e.reason}`); + // console.log(`[WebSocket] 连接关闭: code=${e.code}, reason=${e.reason}`); this.lockReconnect = false; this.reconnect(); }, // 连接错误 handleWsError(e) { - console.log("[WebSocket] 连接错误:", e); - + // console.log("[WebSocket] 连接错误:", e); this.lockReconnect = false; this.reconnect(); }, @@ -237,7 +239,7 @@ export default { }, mounted() { // 使用与 oa-web-phone 相同的原生 WebSocket 通信方式 - // this.startLink(); // 现在一直断线重连,先注释 + this.startLink(); // 现在一直断线重连,先注释 }, }; From 4bbedf0eb5377877a398013cc1ee5b254c33aae0 Mon Sep 17 00:00:00 2001 From: yangzhe Date: Fri, 12 Dec 2025 11:36:22 +0800 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E7=8A=B6=E6=80=81=E5=92=8C=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 2 -- store/index.js | 2 -- types/global.d.ts | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/App.vue b/App.vue index c908181..abef9c0 100644 --- a/App.vue +++ b/App.vue @@ -84,8 +84,6 @@ export default { }, // 初始化原生 WebSocket 连接 initWebSocket() { - console.log(this.buildWsUrl()); - try { this.ws = new WebSocket(this.buildWsUrl()); this.ws.onopen = () => this.handleWsOpen(); diff --git a/store/index.js b/store/index.js index fd726f0..a326ea5 100644 --- a/store/index.js +++ b/store/index.js @@ -94,8 +94,6 @@ const store = new Vuex.Store({ // text: "我的" // } ], - vuex_education: [], - vuex_schoolName: "", }, mutations: { $uStore(state, payload) { diff --git a/types/global.d.ts b/types/global.d.ts index 42e5ec3..7094297 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -13,7 +13,7 @@ declare global { type __VLS_IsAny = 0 extends 1 & T ? true : false; type __VLS_PickNotAny = __VLS_IsAny extends true ? B : A; type __VLS_SpreadMerge = Omit & B; - type __VLS_WithComponent = + type __VLS_WithComponent = N1 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N1] } : N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } : N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } : From d670da4f3ca5fe29e7dde4221a9ba5e7f47e6c6b Mon Sep 17 00:00:00 2001 From: yangzhe Date: Fri, 12 Dec 2025 17:03:54 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat(=E8=81=8A=E5=A4=A9=E9=A1=B5=E9=9D=A2):?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E6=95=99=E5=B8=88=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=8D=A1=E7=89=87=E5=B9=B6=E5=A2=9E=E5=BC=BA=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/chat/index.vue | 90 +++++++++++++++++++++++++++++++++++++++++++- store/index.js | 11 +++++- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/pages/chat/index.vue b/pages/chat/index.vue index 1edfe4b..6fac02a 100644 --- a/pages/chat/index.vue +++ b/pages/chat/index.vue @@ -15,6 +15,30 @@ :scroll-into-view="scrollToView" scroll-with-animation > + +
+ +
+
{{ vuex_msgUser.receiverName }}
+ +
+ + {{ vuex_msgUser.collegeName }} +
+ +
+ + {{ vuex_msgUser.collegeName }} +
+
+
+ @@ -168,6 +192,14 @@ export default { }, computed: { + receiverHeadSculptureUrl() { + if (this.vuex_msgUser.receiverHeadSculptureUrl) { + return this.baseUrl + "/" + this.vuex_msgUser.receiverHeadSculptureUrl; + } + + return "/static/common/images/avatar_default.jpg"; + }, + headSculptureUrl() { if (this.vuex_user.HeadSculptureUrl) { return this.baseUrl + "/" + this.vuex_user.HeadSculptureUrl; @@ -399,6 +431,62 @@ export default { // padding: 10rpx 0; // } + .teacher-info-card { + background-color: #ffffff; + padding: 30rpx; + border-radius: 16rpx; + margin: 30rpx 0; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); + + display: flex; + align-items: center; + margin-bottom: 36rpx; + + .teacher-avatar { + width: 120rpx; + height: 120rpx; + border-radius: 10rpx; + margin-right: 30rpx; + object-fit: cover; + } + + .teacher-info { + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 8rpx; + flex: 1; + + .teacher-name { + font-family: PingFang SC; + font-weight: bold; + font-size: 32rpx; + color: #333333; + } + + .teacher-school, + .teacher-college { + display: flex; + align-items: center; + + .school-icon, + .college-icon { + margin-right: 16rpx; + width: 24rpx; + height: 24rpx; + display: inline-block; + text-align: center; + } + + .school-text, + .college-text { + font-size: 24rpx; + color: #666666; + } + } + } + } + .message-time { text-align: center; font-size: 24rpx; diff --git a/store/index.js b/store/index.js index a326ea5..417e216 100644 --- a/store/index.js +++ b/store/index.js @@ -282,7 +282,16 @@ const store = new Vuex.Store({ (i) => i && (i.receiverId === friendId || i.friendId === friendId) ); if (target) { - commit("set_MsgUser", target); + // 获取消息接收方用户信息 + Vue.prototype.$u.api + .GetReceiverUserInfoApi({ Id: friendId }) + .then((res) => { + if (res.succeed && res.data) { + commit("set_MsgUser", { ...target, ...res.data }); + } else { + commit("set_MsgUser", target); + } + }); // 跳转到对话页,参数按需调整 uni.navigateTo({ From a4876b3ef69063a8190d71e4ef81b726d66b062a Mon Sep 17 00:00:00 2001 From: yangzhe Date: Mon, 15 Dec 2025 10:39:55 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix(=E8=81=8A=E5=A4=A9):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E9=BB=98=E8=AE=A4=E5=A4=B4=E5=83=8F=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B6=88=E6=81=AF=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/chat/index.vue | 4 +++- static/common/images/avatar_default2.png | Bin 0 -> 6589 bytes store/index.js | 6 ++---- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 static/common/images/avatar_default2.png diff --git a/pages/chat/index.vue b/pages/chat/index.vue index 6fac02a..e0f39f6 100644 --- a/pages/chat/index.vue +++ b/pages/chat/index.vue @@ -179,6 +179,8 @@ export default { onLoad(options) { console.log(this.vuex_msgList); + console.log(this.vuex_msgUser,'this.vuex_msgUser'); + this.baseUrl = this.$u.http.config.baseUrl; @@ -197,7 +199,7 @@ export default { return this.baseUrl + "/" + this.vuex_msgUser.receiverHeadSculptureUrl; } - return "/static/common/images/avatar_default.jpg"; + return "/static/common/images/avatar_default2.png"; }, headSculptureUrl() { diff --git a/static/common/images/avatar_default2.png b/static/common/images/avatar_default2.png new file mode 100644 index 0000000000000000000000000000000000000000..b3db9915e971bfa891e49a07d1eed6b60fcce049 GIT binary patch literal 6589 zcmXw82UJr{(@sJNL;>jp1Pr~G08*qFiU=>=Mu!+clwOn$CiE_dNH3xyy-N|0P(qa; zpwgsQkq*)X^56G+&!2O0&fdE_v$L}^yU#N>#@O&S?In&&AP|UFS4Zm(2n418{vc`? z@TTDwlLH7u57O0Azvl*)9UvpdCG z4W*^mRX@kX#2f{sfRDiL+Y~7&DbEjcy+L?LA;A=IGu;?0 zCW2!s35SOY!(cw5cX`2LKfbj0*z> z(sdMy)l#Rw1{BtDJE-wvl0ifQucAC3c$C_hM*p|TiY9~=ZcHN{YA0JuEqzt(XZT+b zJc*zNPNX?h_fUt}2%%9sr`&`yT}&Q`h`9!3TcO7Y{s4r_Jnh67r4s>tjgk%;{Fnrw z#i3Bo3tj{|f0kFto#a~Fn#R9muRRs&@$`j z*5=1>1G4_X{qZ^kMxZ6&^5{BNo*xMq0j2z`i-URz!+yeba8Nb+d_)j|Kn9w^u*gjc z{U~S|;59RW9v^-T0+4*j)&Eq7APThZdu28Z3=U2Y3=CMpqdI;2`}-et-6@On8oX{V@1J9n)q6*LYUHykNa)8nFK9&wYwAo)0R^%Cdj`{+-nYZjB8Ks;a9ycxqxY z9D_!B&^TUzzdgavd$pvr_TN%9vHefO)yQd<=uTf278W*RN2v@3x6wF2Tjj+muSMG| z`BP!x3ikPPGL*FLJUBS0`NsG$C(FQ2{US?*V$js&eW z*$Yt?OejVxo7aY+A^O_yDR@bZ83Pb4w{Gy-AZ{meo-kDqS4&Gvjpi}2#L~9`8PS$q zQhNlg)hi`Ezn71NVXOhOF@ovLXPTOtot43AwoyzM8;3l5Xu}>$3k$)G!&`s@dKfwJJ(nZXL2W--?_7=;CAfOFSOTruj8x1 zhqGa$0HFVuXH6?>~Qj+PGv>;Vb2RINX7$JKRH-`sq{*dkTcqPV1FeY>Qzv~B{Wo1R7$Rt$3wite|p{}mQ zz&hc&J&?}5ycr#&WWL*y%*@R3g+<+iQPk8np;K>oL+buLwzM0m3O&g|l@%2g8>iIwQK;POkI-gY|R8_KvG@`}S!s3R@ z+si}gteliaL;M>W1 z3TC7ls=7qMI~!DEV-Kckt-SyrF9nIamlqYK-&(xXa`N(aepyY;%UPFKJ^M_0%wa|z zy_Url6(K@H91>jgIK)nm%@vG}%^ezk3YHb=zpYVy72w?r_a-ReqvlSkbLtN-91aVj zuCZNSUS8JhU*gQ<{4!s|f7n5x%CTMkIYn0D>GphOE?x$xn_=)e+Z3V65!| zPLUH^rZM%^R@`6@n^eby*H9p<^O3vOW@hP9!<+^JNHhsfus6|1^+Ie~3jO{4=lzz& zQ}l4z%X`c}gkhnfT@AC_QmKy<3mNHmXjY*oQ^43H{qL*$_jToUy*;Uuyg7xxY2XorRP^)E$>rB_<0hNaoqF19h?`OCuH}nahXT1D@{o4CEF~RUWwuNVy-#|dHs(MJ- zlh&;-8VEN&t75V3%}rH3>$vMR0?1VF`gX)fE*9Cu=j-cB%;VRq|HnIz3As8HW8Y?o z>dl=OVwHYsO@4WJ|krcEh{gYO!Iq zBS_u!%s_lF5?I#N0QltA=4M1geZ3%)%Og)#s0Z8p)3hIIau&1}XrE=zI#Ve<(I z2{$L!I%EqeZ?})i!kd$XiG)XM`}_L~c%kfr{>1%5wVsW#s%LkAtbFHJGkd%;m__>d z@#D3chIdJnQJM^A(A!bd0VFOW0WaBOUVeW5_ehVfQHB&TCwR=BmL3W>q2XL({(>8; zC@cHvK}hwKgetTTHFh!UM`P!VKZuKq#{-5>`}F28xIv}b2czxfbV7k1p@%(m5|WY? zic6Bg3YW%$&W?9q&J}t@Ye#6KJgSs=U_G`ieyI6;Jy&Z9DJk+%ijYxAxhsSNW{C1= z9Nqfa-sy zu}a&#@rjAzVHH}}&JT#j@n=%DpIrh@4}QInjLeUB)~^UT0z78d4_#_U3&SLRPs6CL zeC{YaA%EhGEZs_b{W`?&U~Rae0;ayI#7sfy6B>2p+QkYW^8AdS`9;~!X5a0@j*bq` z7w<}+W&*ePCr99B845Z5^}#%RAK@<5VnZ4nRJAcTe{!Tzb7M&dWn7ddFE0-(EG*oc zZ4LC*epB@>D)em2(8%boO- z$G5nhw1~otz?H_&`_`;UF}+J&fKJjgNrZJqXg>P*e-P$K=xS2|fQr-$trxw5Jw0N= z^f_G?@--Dp{YrNNBo`PwV}OC8P$FUkfZ#fLsdugu+Xd-94Wvn}s`~BBEv&2*`Wc3f zc2q&yW`~A`^4L71{j{w9!DFSL0IcC%!aswt&CSh3qdYaP=72xz)p2Z6+FP@2H^ZiU z7jD~bGDfn*gFZJ09&J$`i$%@4=c)$!Ks>d+@pl!C06x-5djI}e4YV-5&w79c;6e9wEquFvqGnZwL!CL&o9oL=cTwb%idCf z-Q)1w!S+i1-@kuX|4C9#s68435VK~Qq_tB=J7;EQWbjg^gUXpx{M_8M#b zDsHnNw@7L-=CFfqgVvHRk~S6af=6SVlarGbSv@r;C+7~$pD7;5+ZWubH^2;v0{;oo z*`0J)J3IfLkh)}!5d&_ga=+&&?ij5tx+_;^4qaXRFfuY?X=i6= zBq}Ouh#z$V0`Que+Y*%}z=&LkSt%)bdE}ag2H#IW)?Am8s`Q?<&MzCd0iHV7%2M->EtorN7Q|wH*%qs0)3UGSzBttRa;IW$` zry7Tp$}2LRW4kg!0C6rs^lQ2%31HS{85x-x7`JBBz!f!3VOVBXRvQ;5r%GIMSmRx< zsu;Z(09Z0U zO{k_rNz3KSmyI6INhdONDFxZ+-_M(p1tPaM-gIPAF|3tH3aBqGe!`gsZPgWfUXNmo zITL`|mz0&ctk)WJmoE@zDc^c47R80OW4dRtUDOLp1OlOXecfqH$j)G$GZz1Drb}H# zRZi~d<<9ZD4-7QWkyBGsQJ(cJIC$N_gUzBz()LlCn~RG|oL*=%LNzB`_?1Nhi|fOZ zT|ZynBPEYOhwpS#=Nf1O)Ukk?gxb9PI6G(8?drRS1Jnq|fy#&8(0$sp7o197>X8Nt zt{9!R@E{V+l`Cys6KBlY##}WEB9fA7aE6e0y&An5mw@kdL}XlUPoiQJ*DfPz;X|!- zN|nf#m(_b_5D5P0-&%lHyqug|P=ao^Wjb0p?$2^~D$7rhNmh?lFT4KP36w8;@ahIN z)56H~$cRj=o}7_U*Q0^gSWGffu$6>~wlFm|mUbG}njG|?e>V4HQY4<)tEw}PczwUT z?rO7f^}BaVu<`89WkZ1#jd0__Y|d8s`|Q!*t?+WLT@Y? z-t4JlRBk!`8%{^l^n87N{l*LDZ4s-uN=qG03#RN0Tf6j&=kz7p3}Y-^-y=*?{7OvB zGE?Me)w7A&1M-T~Mz!$LO{OYannSLPnzi4*|0>Yl1FRq*!0#V9}Nxu-|#LXfr)P>H3_VLO0B*KfEK7S68G*@-| z`wB#yyUPt9^EeEQa6U5sd6hgBp89jj7HbNgbf z7hZ&eo`_6H#DlDQCMuzh*?75{0g;ldIp~MpJWB@+gS`q)d%D6pE3PEJX5etHi2v0*{KuG$I8^{wtNvxduH920JFa(o{7-jYr}CE>{Kw242an zsIL;$8&#C!vFb&u2~V-9zl{AN^4Nx{v)jJ$-KX@ZrOTXW=eSAow3Yek1~vBu~GW z=tP&x8rI$2T}vbqZOtQke6$&gw%69i_y3-|C-jSk*{g`bl6CCsKYhy7NNOix1MdHP zhbQ%=4TLFc{AvBx{^k1(a6GTFXVVVhQ$(l4ck%{1stBl? zbOqb*CK>(-j9?H|M=B^Ze0u-hK|Kb;N!=lats49KmHsJC$Qq%I1fxx$D=t zPVM-|G^)Q>@BV9(gVkT93p?)mLyiPx!+gNCsyAQM7fBm6ePe}Wh9XpL$!sx@`%y2Sz7xS8 zbapQn9{1Jj{c8AHT3C&xk0bgVtY6YDrNE1xjq(_Zp*Tcf>0;^a_CqK!^mrunB?G}h z!}Qs+kIA!6a(8He?6MX7ZS2N}ccDhp)I6zhv0UsTY#&uJv#>l9(aXk9=n&XP@#r}} zVdhVZ@d~Rg2q74PC3@=SbrR1zAt}b9(o)$iF;aI7*o_?C(&#PY=m-ZE#c_1s?`>B; zaMH;L(dDQLx2)4Puun<*V!mk=m|$^w;j1>&N`nKI=kZ9`I#q^xcy~1TRX|f?W20)= zPxDl04KHR=s{n;HzI#`eLj5tR#CIYcD#MQ%`QOX?_lZ5Zj*Wb^0f*3kXft)>G-#x) zvc$y2m-q&2W*b~a_CE?~H&JU)d21*N0|DInwqq3S<*9b)6L~T2sUESs#|CGfk zPa5*1W}dq<@00CS9$Uv278@HYP#!I7#s}AWJ8Uq`G-^X5onrYWP)IuD93I{|FFIZO z)q=*uzbYBP38`B-gyTO#bNeS2DBr3wZ$XPVup~o#W83c;I;|lY_}m@!-~JTSM2y}e z#}QVzy(TEFta+l&x4HZW7Wca@dJ6O_4@yTJuJLBA-H|KJB2FCuUgXc{o>tP=bd>wo za&M=}SaoScHq|k2%gHGkM=nO^H#YhiMktnb<(DJ0c$065!E0&ZKyC-S=Jp_xv8Qw7Ob} z-JV<>+MbBg4>0`mcKv zFpF4qb@lehcth`QSgT(G=+H=ltZ$=-qK1W8kZBvo=;$h!=HC#eCz{nOoY#`$?@KIogf%0Y&t^p8knI?ak5r>#NXrg*AUAvlsQvzmQIS`QL!IuH6uIcFM z=Eu+hHYx@8>3`v!^OFZk>B*x!@FHEHl>VqqT9nZv8!*vx>8TFH326f0w}a=ejSsHegw>%v5R$O zlzt5;9ItS|@+Yz5$y6W^nOyXJz6AIP1N#?oQGgzEHkk(mF)9FWK)SaKwJJ0)q5lU_ C^C2_< literal 0 HcmV?d00001 diff --git a/store/index.js b/store/index.js index 417e216..cab4120 100644 --- a/store/index.js +++ b/store/index.js @@ -282,18 +282,16 @@ const store = new Vuex.Store({ (i) => i && (i.receiverId === friendId || i.friendId === friendId) ); if (target) { - // 获取消息接收方用户信息 + commit("set_MsgUser", target); + Vue.prototype.$u.api .GetReceiverUserInfoApi({ Id: friendId }) .then((res) => { if (res.succeed && res.data) { commit("set_MsgUser", { ...target, ...res.data }); - } else { - commit("set_MsgUser", target); } }); - // 跳转到对话页,参数按需调整 uni.navigateTo({ url: `/pages/chat/index`, }); From eab59c8259e1908243920c2ea52aeb331d3462d4 Mon Sep 17 00:00:00 2001 From: yangzhe Date: Mon, 15 Dec 2025 17:03:54 +0800 Subject: [PATCH 6/7] =?UTF-8?q?refactor(chat):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E4=BC=9A=E8=AF=9D=E9=80=BB=E8=BE=91=E5=92=8C?= =?UTF-8?q?API=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/http.api.js | 9 +++- pages/chat/index.vue | 27 ++++------- pages/home/admissions/index.vue | 10 +--- store/index.js | 83 ++++++++++++++------------------- 4 files changed, 53 insertions(+), 76 deletions(-) diff --git a/common/http.api.js b/common/http.api.js index 01596bd..c51c910 100644 --- a/common/http.api.js +++ b/common/http.api.js @@ -218,9 +218,12 @@ const install = (Vue, vm) => { // 获取教师列表(学生端-招办在线) let GetTeacherListApi = (params = {}) => vm.$u.get("api/Dialogue/GetTeacherList", params); - // 获取会话列表 + // 获取会话列表-教师 let GetDialogueListApi = (params = {}) => vm.$u.get("api/Dialogue/GetDialogueList", params); + // 获取会话列表-用户 + let GetDialogueList_UserApi = (params = {}) => + vm.$u.get("api/Dialogue/GetDialogueList_User", params); // 创建会话 let AddDialogueApi = (params = {}) => vm.$u.post("api/Dialogue/AddDialogue", params); @@ -236,6 +239,9 @@ const install = (Vue, vm) => { // 置顶一个会话 let OverheadOneDialogueApi = (params = {}) => vm.$u.post("api/Dialogue/OverheadOneDialogue", params); + // 删除会话 + let DeleteDialogueApi = (params = {}) => + vm.$u.post("api/Dialogue/DeleteDialogue", params); // 将各个定义的接口名称,统一放进对象挂载到vm.$u.api(因为vm就是this,也即this.$u.api)下 vm.$u.api = { @@ -297,6 +303,7 @@ const install = (Vue, vm) => { UpdateUserApi, GetTeacherListApi, GetDialogueListApi, + GetDialogueList_UserApi, AddDialogueApi, SendMessage_PrivateApi, GetChatHistoryDataApi, diff --git a/pages/chat/index.vue b/pages/chat/index.vue index e0f39f6..33e0711 100644 --- a/pages/chat/index.vue +++ b/pages/chat/index.vue @@ -2,7 +2,7 @@ @@ -19,7 +19,7 @@
-
{{ vuex_msgUser.receiverName }}
+
{{ vuex_msgUser.name }}
@@ -68,7 +68,7 @@ { const msgList = res.data.item1.reverse(); - // 注:现在的消息返回值缺少 interactMode 字段,先手动mock - for (var i = 0; i < msgList.length; i++) { - msgList[i].interactMode = msgList[i].interactMode || 0; - - // if (this.PageIndex != 1) { - // this.$store.commit("unshift_Msg", msgList[i]); - // } else { - // this.$store.commit("push_Msg", msgList[i]); - // } - } this.$store.commit("push_MsgList", msgList); }); }, diff --git a/pages/home/admissions/index.vue b/pages/home/admissions/index.vue index b5f8510..33ab4bb 100644 --- a/pages/home/admissions/index.vue +++ b/pages/home/admissions/index.vue @@ -114,14 +114,8 @@ export default { handleAskQuestion(teacher) { console.log("点击咨询:", teacher); - var msgUserData = { - avatar: teacher.headSculptureUrl, - friendId: teacher.id, - friendName: teacher.name, - }; - - // 进入对话会话 - this.$store.dispatch("openOrCreateDialogue", msgUserData); + // 点击立即提问,进入对话会话 + this.$store.dispatch("createDialogue", teacher); return; diff --git a/store/index.js b/store/index.js index cab4120..53ac51f 100644 --- a/store/index.js +++ b/store/index.js @@ -235,7 +235,7 @@ const store = new Vuex.Store({ // 获取聊天记录(私聊) async fetchChatRecord( { commit, state }, - { userId, friendId, chatType = 0, PageIndex = 1, PageSize = 20 } + { userId, friendId, PageIndex = 1, PageSize = 20 } ) { const params = { userId, friendId, PageIndex, PageSize }; @@ -260,65 +260,52 @@ const store = new Vuex.Store({ } }, - // 统一入口:打开或创建会话 - // 使用位置:所有需要进入聊天的入口调用该方法,避免各页面重复逻辑 - // 1) 获取最新会话列表 - // 2) 查找是否存在 friendId 对应的会话 - // 3) 有则设置当前会话并(可选)跳转;无则创建,成功后递归重试 - async openOrCreateDialogue({ commit, state, dispatch }, user) { - const { friendId, friendName, avatar, chatType = 0 } = user || {}; - const attempt = - user && typeof user.attempt === "number" ? user.attempt : 1; - if (!friendId) return Promise.reject(new Error("缺少 friendId")); + // 点击立即提问进入会话 + // 1) 创建新会话 + // 2) 获取接收者信息 + // 3) 进入会话 + async createDialogue({ commit, state, dispatch }, user) { + const { id, dialogueManagementId } = user || {}; + if (!id) return Promise.reject(new Error("缺少 id")); // 清空消息列表,避免旧消息干扰 commit("push_MsgList", []); - // 第一步:获取列表(复用现有 action,保证 state 同步更新) - const list = await dispatch("getUserlist"); - - // 第二步:查找是否存在该会话(兼容后端字段 friendId/receiverId) - const target = (list || []).find( - (i) => i && (i.receiverId === friendId || i.friendId === friendId) - ); - if (target) { - commit("set_MsgUser", target); - - Vue.prototype.$u.api - .GetReceiverUserInfoApi({ Id: friendId }) - .then((res) => { - if (res.succeed && res.data) { - commit("set_MsgUser", { ...target, ...res.data }); - } - }); - + if (dialogueManagementId) { + // 有会话ID,直接进入会话 + commit("set_MsgUser", { ...user }); uni.navigateTo({ url: `/pages/chat/index`, }); - - return target; + return; } - // 第二次调用时,无论成功与否均在第三步(创建)之前结束 - if (attempt >= 2) { - return false; - } - - // 第三步:不存在则创建,成功后重试本流程 - const res = await Vue.prototype.$u.api.AddDialogueApi({ - receiverId: friendId, - onlineConsultationType: 0, // 0:招生在线;1:迎新在线(可按业务传入) + // 没有会话id创建新会话 + const res1 = await Vue.prototype.$u.api.AddDialogueApi({ + receiverId: id, + onlineConsultationType: 1, // 创建在线咨询固定传1 }); - if (res && res.succeed === true) { - // 创建成功后,重新执行流程(再次获取列表并进入会话) - return dispatch("openOrCreateDialogue", { - friendId, - friendName, - avatar, - chatType, - attempt: attempt + 1, + + const resId = res1.data?.dialogueManagementId || ""; + + if (res1 && res1.succeed) { + // 获取接收者信息,这里没啥用(先注释) + // Vue.prototype.$u.api.GetReceiverUserInfoApi({ Id: id }).then((res) => { + // if (res.succeed && res.data) { + // commit("set_MsgUser", { ...res.data, dialogueManagementId }); + // uni.navigateTo({ + // url: `/pages/chat/index`, + // }); + // return; + // } + // }); + commit("set_MsgUser", { ...user, dialogueManagementId: resId }); + uni.navigateTo({ + url: `/pages/chat/index`, }); + return; } + return Promise.reject(new Error(res?.error || "创建会话失败")); }, }, From bedc1a65cdb713815aac4f18b3e32dea7a44cd1d Mon Sep 17 00:00:00 2001 From: yangzhe Date: Tue, 16 Dec 2025 11:44:35 +0800 Subject: [PATCH 7/7] =?UTF-8?q?feat(=E8=81=8A=E5=A4=A9):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=95=99=E5=B8=88=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=B9=B6=E5=88=86=E7=A6=BBAI/=E6=95=99?= =?UTF-8?q?=E5=B8=88=E8=81=8A=E5=A4=A9=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ChatHistory.vue | 56 ++++++++++++++++++++++---------------- pages/home/index/index.vue | 42 ++++++++++++++++++++++------ store/index.js | 23 +++++++++++++++- 3 files changed, 88 insertions(+), 33 deletions(-) diff --git a/components/ChatHistory.vue b/components/ChatHistory.vue index 5ec355f..c81f474 100644 --- a/components/ChatHistory.vue +++ b/components/ChatHistory.vue @@ -44,7 +44,7 @@ > @@ -63,7 +63,7 @@ 'chat-item-active': item.isActiveChat, }" @click.stop=" - selectChatItem(groupIndex, index, item.id, item.conversationId) + selectChatItem(item.id, item.conversationId, item.receiverId) " > @@ -90,12 +90,7 @@ [], + }, + chatHistoryTeacher: { type: Array, default: () => [], }, @@ -172,8 +171,6 @@ export default { return { baseUrl: "", showPopup: false, - currentActiveGroup: -1, - currentActiveIndex: -1, activeItemId: "", // 存储当前激活项的ID scrollToView: "", // 用于scroll-into-view属性 tabList: [ @@ -193,6 +190,12 @@ export default { }, computed: { + currentChatHistory() { + return this.currentTab === 0 + ? this.chatHistoryAI + : this.chatHistoryTeacher; + }, + headSculptureUrl() { if (this.vuex_user.HeadSculptureUrl) { return this.baseUrl + "/" + this.vuex_user.HeadSculptureUrl; @@ -224,7 +227,7 @@ export default { } }, // 监听聊天历史数据变化,找到激活项并滚动 - chatHistoryList3: { + chatHistoryAI: { handler() { this.$nextTick(() => { this.scrollToActiveItem(); @@ -308,10 +311,10 @@ export default { for ( let groupIndex = 0; - groupIndex < this.chatHistoryList3.length; + groupIndex < this.chatHistoryAI.length; groupIndex++ ) { - const group = this.chatHistoryList3[groupIndex]; + const group = this.chatHistoryAI[groupIndex]; for (let index = 0; index < group.conversation.length; index++) { const item = group.conversation[index]; if (item.isActiveChat) { @@ -326,16 +329,21 @@ export default { } }, - selectChatItem(groupIndex, index, id, conversationId) { - // this.currentActiveGroup = groupIndex; - // this.currentActiveIndex = index; - console.log("selectChatItem", groupIndex, index, id, conversationId); - - // 向父组件发送选中的对话信息 - this.$emit("select-conversation", { - id, - conversationId, - }); + selectChatItem(id, conversationId = null, receiverId = null) { + if (this.currentTab === 0) { + // 点击AI聊天项 + // 向父组件发送选中的对话信息 + this.$emit("select-conversation", { + id, + conversationId, + }); + } else { + // 点击教师聊天项 + this.$store.dispatch("selectTeacherChatItem", { + id, + receiverId, + }); + } }, handleCreateConversation() { diff --git a/pages/home/index/index.vue b/pages/home/index/index.vue index c32cd18..783d8c6 100644 --- a/pages/home/index/index.vue +++ b/pages/home/index/index.vue @@ -259,7 +259,8 @@ { - this.chatHistoryList3 = res.data; - if (this.chatHistoryList3.length > 0) { - this.chatHistoryList3 = res.data.map((group) => { + // 获取人工咨询历史记录 + async GetDialogueList_User() { + this.$u.api.GetDialogueList_UserApi().then((res) => { + this.chatHistoryTeacher = res.data; + if (this.chatHistoryTeacher.length > 0) { + this.chatHistoryTeacher = res.data.map((group) => { // 对每个组的conversation数组进行倒序排序 return { ...group, @@ -511,7 +515,29 @@ export default { }; }); } - console.log("this.chatHistoryList3", this.chatHistoryList3); + }); + }, + + // 获取ai历史记录 + async getChatHistoryList() { + this.$u.api.GetConversationPage().then((res) => { + this.chatHistoryAI = res.data; + if (this.chatHistoryAI.length > 0) { + this.chatHistoryAI = res.data.map((group) => { + // 对每个组的conversation数组进行倒序排序 + return { + ...group, + conversation: group.conversation.sort((a, b) => { + // 将日期字符串转换为时间戳并比较(倒序) + return ( + new Date(b.startTime).getTime() - + new Date(a.startTime).getTime() + ); + }), + }; + }); + } + console.log("this.chatHistoryAI", this.chatHistoryAI); }); }, diff --git a/store/index.js b/store/index.js index 53ac51f..75f9025 100644 --- a/store/index.js +++ b/store/index.js @@ -260,6 +260,24 @@ const store = new Vuex.Store({ } }, + // 点击聊天记录,切换到该会话 + selectTeacherChatItem({ commit, dispatch }, { id, receiverId }) { + // 清空消息列表,避免旧消息干扰 + commit("push_MsgList", []); + + Vue.prototype.$u.api + .GetReceiverUserInfoApi({ Id: receiverId }) + .then((res) => { + if (res.succeed && res.data) { + commit("set_MsgUser", { ...res.data, dialogueManagementId: id }); + uni.navigateTo({ + url: `/pages/chat/index`, + }); + return; + } + }); + }, + // 点击立即提问进入会话 // 1) 创建新会话 // 2) 获取接收者信息 @@ -271,7 +289,10 @@ const store = new Vuex.Store({ // 清空消息列表,避免旧消息干扰 commit("push_MsgList", []); - if (dialogueManagementId) { + if ( + dialogueManagementId && + dialogueManagementId !== "00000000-0000-0000-0000-000000000000" + ) { // 有会话ID,直接进入会话 commit("set_MsgUser", { ...user }); uni.navigateTo({