chat.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const common_assets = require("../../common/assets.js");
  4. const api_message = require("../../api/message.js");
  5. const api_student = require("../../api/student.js");
  6. const utils_chatSocket = require("../../utils/chatSocket.js");
  7. const utils_request = require("../../utils/request.js");
  8. const _sfc_main = {
  9. __name: "chat",
  10. setup(__props) {
  11. const loading = common_vendor.ref(true);
  12. const messages = common_vendor.ref([]);
  13. const inputValue = common_vendor.ref("");
  14. const inputMode = common_vendor.ref("text");
  15. const activePanel = common_vendor.ref("none");
  16. const lastMessageId = common_vendor.ref("bottom-anchor");
  17. const statusBarHeight = common_vendor.ref(20);
  18. const sessionId = common_vendor.ref(null);
  19. const fromUserId = common_vendor.ref(null);
  20. const sessionUserName = common_vendor.ref("");
  21. const jobName = common_vendor.ref("");
  22. const chatType = common_vendor.ref("job");
  23. const trainingTitle = common_vendor.ref("");
  24. const assessmentTitle = common_vendor.ref("");
  25. const assessmentCover = common_vendor.ref("");
  26. const assessmentLevel = common_vendor.ref("");
  27. const assessmentId = common_vendor.ref("");
  28. const assessmentPrice = common_vendor.ref("");
  29. const positionId = common_vendor.ref(null);
  30. const salaryRange = common_vendor.ref("");
  31. const companyName = common_vendor.ref("");
  32. const workCity = common_vendor.ref("");
  33. const workDistrict = common_vendor.ref("");
  34. const waiterAvatar = common_vendor.ref("/static/images/hr_avatar.svg");
  35. function resolveAvatarUrl(url) {
  36. if (!url || url === "" || url === "undefined")
  37. return "";
  38. const str = String(url).trim();
  39. if (str.startsWith("http://") || str.startsWith("https://"))
  40. return str;
  41. if (/^\d+$/.test(str)) {
  42. return `${utils_request.BASE_URL}/resource/oss/file/${str}`;
  43. }
  44. if (str.startsWith("/static/"))
  45. return "";
  46. return str;
  47. }
  48. const userAvatarUrl = common_vendor.ref("/static/images/user_avatar.png");
  49. const emojiList = ["😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "😊", "😇", "🙂", "🙃", "😉", "😌", "😍", "🥰", "😘", "😗", "😙", "😚", "😋", "😛", "😝", "😜", "🤪", "🤨", "🧐", "🤓", "😎", "🤩", "🥳"];
  50. let wsSubId = null;
  51. common_vendor.onLoad(async (options) => {
  52. try {
  53. const sysInfo = common_vendor.index.getSystemInfoSync();
  54. statusBarHeight.value = sysInfo.statusBarHeight || 20;
  55. } catch (e) {
  56. }
  57. if (options.sessionId)
  58. sessionId.value = options.sessionId;
  59. if (options.fromUserId)
  60. fromUserId.value = options.fromUserId;
  61. if (options.userName)
  62. sessionUserName.value = decodeURIComponent(options.userName);
  63. if (options.jobName)
  64. jobName.value = decodeURIComponent(options.jobName);
  65. if (options.type)
  66. chatType.value = options.type;
  67. if (options.title)
  68. trainingTitle.value = decodeURIComponent(options.title || "");
  69. if (options.title && options.type === "assessment") {
  70. assessmentTitle.value = decodeURIComponent(options.title || "");
  71. }
  72. if (options.cover)
  73. assessmentCover.value = decodeURIComponent(options.cover || "");
  74. if (options.level)
  75. assessmentLevel.value = decodeURIComponent(options.level || "");
  76. if (options.assessmentId)
  77. assessmentId.value = options.assessmentId;
  78. if (options.price)
  79. assessmentPrice.value = options.price;
  80. if (options.positionId)
  81. positionId.value = options.positionId;
  82. if (options.salaryRange)
  83. salaryRange.value = decodeURIComponent(options.salaryRange);
  84. if (options.companyName)
  85. companyName.value = decodeURIComponent(options.companyName);
  86. if (options.workCity)
  87. workCity.value = decodeURIComponent(options.workCity);
  88. if (options.workDistrict)
  89. workDistrict.value = decodeURIComponent(options.workDistrict);
  90. const storedInfo = common_vendor.index.getStorageSync("userInfo") || {};
  91. const rawUserAvatar = storedInfo.avatarUrl || storedInfo.avatar || "/static/images/user_avatar.png";
  92. userAvatarUrl.value = resolveAvatarUrl(rawUserAvatar) || "/static/images/user_avatar.png";
  93. if (!fromUserId.value && storedInfo.studentId)
  94. fromUserId.value = storedInfo.studentId;
  95. if (!sessionId.value) {
  96. loading.value = false;
  97. common_vendor.index.showToast({ title: "会话参数缺失", icon: "none" });
  98. return;
  99. }
  100. await loadHistory();
  101. connectWebSocket();
  102. if (chatType.value === "assessment") {
  103. setTimeout(async () => {
  104. try {
  105. const userInfo = common_vendor.index.getStorageSync("userInfo") || {};
  106. const res = await api_message.autoCreateOrderCard({
  107. sessionId: sessionId.value,
  108. studentId: userInfo.studentId || fromUserId.value,
  109. orderName: assessmentTitle.value || jobName.value + "-测评服务费",
  110. orderPrice: assessmentPrice.value || "0",
  111. orderType: "测评咨询"
  112. });
  113. if (res.code === 200 && res.data) {
  114. pushOrderCardMsg(res.data);
  115. } else {
  116. common_vendor.index.__f__("error", "at pages/chat/chat.vue:418", "自动创建结算单失败:", res);
  117. }
  118. } catch (err) {
  119. common_vendor.index.__f__("error", "at pages/chat/chat.vue:421", "自动创建结算单异常:", err);
  120. }
  121. }, 800);
  122. } else if (chatType.value === "job" && positionId.value) {
  123. try {
  124. const { getAssessmentList } = require("../../api/assessment.js");
  125. const evalRes = await getAssessmentList({ positionId: positionId.value, pageNum: 1, pageSize: 1 });
  126. if (evalRes.code === 200 && evalRes.rows && evalRes.rows.length > 0) {
  127. const firstEval = evalRes.rows[0];
  128. if (!assessmentId.value) {
  129. assessmentId.value = String(firstEval.id);
  130. common_vendor.index.__f__("log", "at pages/chat/chat.vue:435", "[Chat] 岗位关联测评ID:", assessmentId.value);
  131. }
  132. setTimeout(async () => {
  133. try {
  134. const userInfo = common_vendor.index.getStorageSync("userInfo") || {};
  135. const res = await api_message.autoCreateOrderCard({
  136. sessionId: sessionId.value,
  137. studentId: userInfo.studentId || fromUserId.value,
  138. orderName: (firstEval.evaluationName || jobName.value) + "-测评服务费",
  139. orderPrice: firstEval.price || assessmentPrice.value || "0",
  140. orderType: "岗位测评"
  141. });
  142. if (res.code === 200 && res.data) {
  143. pushOrderCardMsg(res.data);
  144. }
  145. } catch (err) {
  146. common_vendor.index.__f__("error", "at pages/chat/chat.vue:450", "岗位结算单异常:", err);
  147. }
  148. }, 800);
  149. } else {
  150. common_vendor.index.__f__("log", "at pages/chat/chat.vue:453", "[Chat] 该岗位无关联测评,不发送结算单");
  151. }
  152. } catch (e) {
  153. common_vendor.index.__f__("error", "at pages/chat/chat.vue:456", "[Chat] 查询关联测评失败:", e);
  154. }
  155. }
  156. });
  157. let orderTimer = null;
  158. function startOrderTimer() {
  159. if (orderTimer)
  160. return;
  161. orderTimer = setInterval(() => {
  162. messages.value.forEach((m) => {
  163. if (m.msgType === "order_card" && !m.isPaid && m.countdown > 0) {
  164. m.countdown--;
  165. }
  166. });
  167. }, 1e3);
  168. }
  169. common_vendor.onUnload(() => {
  170. if (wsSubId) {
  171. utils_chatSocket.unsubscribe(wsSubId);
  172. wsSubId = null;
  173. }
  174. utils_chatSocket.disconnectChat();
  175. if (orderTimer)
  176. clearInterval(orderTimer);
  177. });
  178. async function loadHistory() {
  179. try {
  180. const res = await api_message.getChatHistory({ sessionId: sessionId.value, pageNum: 1, pageSize: 50 });
  181. if (res.rows) {
  182. messages.value = res.rows.slice().reverse().map(normalizeMsg);
  183. scrollToBottom();
  184. const firstWaiterMsg = res.rows.find((m) => m.senderType === 2);
  185. if (firstWaiterMsg && firstWaiterMsg.senderAvatar) {
  186. const resolvedWaiterAvatar = resolveAvatarUrl(firstWaiterMsg.senderAvatar);
  187. if (resolvedWaiterAvatar) {
  188. waiterAvatar.value = resolvedWaiterAvatar;
  189. }
  190. }
  191. if (messages.value.length > 0) {
  192. const lastMsg = messages.value[messages.value.length - 1];
  193. if (lastMsg.id && !lastMsg.id.toString().startsWith("temp")) {
  194. api_message.markChatRead({ sessionId: sessionId.value, lastReadMsgId: lastMsg.id });
  195. }
  196. }
  197. }
  198. } catch (e) {
  199. common_vendor.index.__f__("error", "at pages/chat/chat.vue:508", "[Chat] 加载历史消息失败:", e);
  200. } finally {
  201. loading.value = false;
  202. }
  203. if (fromUserId.value) {
  204. try {
  205. const stuRes = await api_student.getStudent(fromUserId.value);
  206. if (stuRes.code === 200 && stuRes.data) {
  207. const stu = stuRes.data;
  208. const resolvedUrl = resolveAvatarUrl(stu.avatarUrl || stu.avatar);
  209. if (resolvedUrl) {
  210. userAvatarUrl.value = resolvedUrl;
  211. }
  212. }
  213. } catch (e) {
  214. common_vendor.index.__f__("warn", "at pages/chat/chat.vue:526", "[Chat] 获取学员头像失败:", e);
  215. }
  216. }
  217. }
  218. function connectWebSocket() {
  219. const token = common_vendor.index.getStorageSync("token");
  220. utils_chatSocket.connectChat({
  221. token,
  222. onConnect: () => {
  223. common_vendor.index.__f__("log", "at pages/chat/chat.vue:537", "[Chat] WebSocket 已连接,订阅会话消息");
  224. if (sessionId.value) {
  225. wsSubId = utils_chatSocket.subscribe(`/topic/session/${sessionId.value}`, (data) => {
  226. common_vendor.index.__f__("log", "at pages/chat/chat.vue:541", "[Chat] 收到 WebSocket 消息:", data);
  227. onWsMessage(data);
  228. });
  229. }
  230. },
  231. onDisconnect: () => {
  232. common_vendor.index.__f__("log", "at pages/chat/chat.vue:547", "[Chat] WebSocket 已断开");
  233. }
  234. });
  235. }
  236. function onWsMessage(data) {
  237. if (!data)
  238. return;
  239. const msgList = Array.isArray(data) ? data : [data];
  240. msgList.forEach((msgData) => {
  241. const normalized = normalizeMsg(msgData);
  242. const existIdx = messages.value.findIndex(
  243. (m) => m.id && normalized.id && m.id === normalized.id || m.msgNo && normalized.msgNo && m.msgNo === normalized.msgNo
  244. );
  245. if (existIdx >= 0) {
  246. messages.value[existIdx] = { ...messages.value[existIdx], ...normalized };
  247. } else {
  248. messages.value.push(normalized);
  249. }
  250. });
  251. scrollToBottom();
  252. const lastMsg = messages.value[messages.value.length - 1];
  253. if (lastMsg && lastMsg.id && !String(lastMsg.id).startsWith("temp")) {
  254. api_message.markChatRead({ sessionId: sessionId.value, lastReadMsgId: lastMsg.id });
  255. }
  256. }
  257. function normalizeMsg(msg) {
  258. let payload = null;
  259. if (msg.payload) {
  260. try {
  261. payload = typeof msg.payload === "string" ? JSON.parse(msg.payload) : msg.payload;
  262. } catch (e) {
  263. }
  264. }
  265. return {
  266. id: msg.msgId,
  267. msgNo: msg.msgNo,
  268. senderType: msg.senderType,
  269. // 1=用户 2=客服 3=系统
  270. senderName: msg.senderName,
  271. senderAvatar: msg.senderAvatar,
  272. msgType: msg.msgType || "text",
  273. content: msg.content,
  274. fileUrl: msg.fileUrl,
  275. fileName: msg.fileName,
  276. fileSize: msg.fileSize,
  277. payload,
  278. sendTime: msg.sendTime,
  279. isPaid: payload && (payload.status === "paid" || payload.status === "已支付" || payload.paid === true)
  280. };
  281. }
  282. async function sendMessage() {
  283. const content = inputValue.value.trim();
  284. if (!content || !sessionId.value)
  285. return;
  286. const msgNo = utils_chatSocket.generateMsgNo();
  287. const tempId = "temp_" + Date.now();
  288. messages.value.push({
  289. id: tempId,
  290. msgNo,
  291. senderType: 1,
  292. msgType: "text",
  293. content,
  294. sendTime: (/* @__PURE__ */ new Date()).toISOString(),
  295. payload: null
  296. });
  297. inputValue.value = "";
  298. scrollToBottom();
  299. try {
  300. if (utils_chatSocket.isSocketConnected()) {
  301. const sent = utils_chatSocket.sendTextByWs(sessionId.value, content, "text", msgNo, fromUserId.value);
  302. if (sent)
  303. return;
  304. }
  305. await api_message.sendTextMessage({
  306. sessionId: sessionId.value,
  307. msgNo,
  308. content,
  309. msgType: "text",
  310. senderId: fromUserId.value || void 0
  311. });
  312. } catch (e) {
  313. messages.value = messages.value.filter((m) => m.id !== tempId);
  314. common_vendor.index.showToast({ title: "发送失败,请重试", icon: "none" });
  315. }
  316. }
  317. async function chooseImage() {
  318. activePanel.value = "none";
  319. common_vendor.index.chooseImage({
  320. count: 1,
  321. success: async (res) => {
  322. const filePath = res.tempFilePaths[0];
  323. const tempId = "temp_img_" + Date.now();
  324. messages.value.push({
  325. id: tempId,
  326. senderType: 1,
  327. msgType: "image",
  328. fileUrl: filePath,
  329. sendTime: (/* @__PURE__ */ new Date()).toISOString(),
  330. payload: null
  331. });
  332. scrollToBottom();
  333. try {
  334. const msgNo = "MSG_" + Date.now() + "_" + Math.random().toString(36).slice(2, 6);
  335. await api_message.sendImageMessage({ sessionId: sessionId.value, msgNo, filePath, senderId: fromUserId.value });
  336. } catch (e) {
  337. messages.value = messages.value.filter((m) => m.id !== tempId);
  338. common_vendor.index.showToast({ title: "图片发送失败", icon: "none" });
  339. }
  340. }
  341. });
  342. }
  343. function sendMockOrderCard() {
  344. activePanel.value = "none";
  345. messages.value.push({
  346. id: "manual_order_" + Date.now(),
  347. msgNo: "ORDER_" + Date.now(),
  348. senderType: 2,
  349. msgType: "order_card",
  350. content: "为您推送测评费用结算单",
  351. payload: {
  352. id: 1,
  353. name: assessmentTitle.value || "测评费用",
  354. amount: assessmentPrice.value || "680.00"
  355. },
  356. sendTime: (/* @__PURE__ */ new Date()).toISOString(),
  357. isPaid: false
  358. });
  359. scrollToBottom();
  360. }
  361. function pushOrderCardMsg(card) {
  362. const hasOrderCard = messages.value.some(
  363. (m) => m.msgType === "order_card" && m.payload && m.payload.orderCardId === card.orderCardId
  364. );
  365. if (hasOrderCard) {
  366. common_vendor.index.__f__("log", "at pages/chat/chat.vue:698", "[Chat] 已存在相同结算单消息,跳过推送");
  367. return;
  368. }
  369. messages.value.push({
  370. id: "order_" + card.orderCardId,
  371. msgNo: "ORDER_" + Date.now(),
  372. senderType: card.senderType || 3,
  373. msgType: "order_card",
  374. content: "项目费用结算单",
  375. countdown: Math.floor(card.countdownSeconds || 1800),
  376. payload: {
  377. orderCardId: card.orderCardId,
  378. id: card.orderCardId,
  379. name: card.orderName || assessmentTitle.value || jobName.value,
  380. // 同时写入amount和price,兼容后端payload字段
  381. amount: card.orderPrice || assessmentPrice.value || "0",
  382. price: card.orderPrice || assessmentPrice.value || "0",
  383. status: "pending"
  384. },
  385. sendTime: (/* @__PURE__ */ new Date()).toISOString(),
  386. isPaid: false
  387. });
  388. scrollToBottom();
  389. startOrderTimer();
  390. }
  391. function confirmReg() {
  392. common_vendor.index.showLoading({ title: "预约中..." });
  393. setTimeout(() => {
  394. common_vendor.index.hideLoading();
  395. common_vendor.index.showToast({ title: "预约成功", icon: "success" });
  396. }, 1200);
  397. }
  398. async function handlePay(msg) {
  399. if (msg.isPaid)
  400. return;
  401. const orderCardId = msg.payload ? msg.payload.orderCardId || msg.payload.id : null;
  402. const userInfo = common_vendor.index.getStorageSync("userInfo") || {};
  403. common_vendor.index.__f__("log", "at pages/chat/chat.vue:740", "🔥 开始支付流程");
  404. common_vendor.index.__f__("log", "at pages/chat/chat.vue:741", "🔥 orderCardId:", orderCardId, "类型:", typeof orderCardId);
  405. common_vendor.index.__f__("log", "at pages/chat/chat.vue:742", "🔥 fromUserId:", fromUserId.value, "类型:", typeof fromUserId.value);
  406. common_vendor.index.__f__("log", "at pages/chat/chat.vue:743", "🔥 userInfo:", JSON.stringify(userInfo));
  407. common_vendor.index.__f__("log", "at pages/chat/chat.vue:744", "🔥 msg.payload:", JSON.stringify(msg.payload));
  408. if (!orderCardId) {
  409. common_vendor.index.showToast({ title: "无效的结算单", icon: "none" });
  410. return;
  411. }
  412. try {
  413. common_vendor.index.showLoading({ title: "创建支付订单..." });
  414. common_vendor.index.__f__("log", "at pages/chat/chat.vue:774", "🔥 调用支付接口,参数:", { orderCardId, userId: fromUserId.value });
  415. const payRes = await api_message.createWxPayOrder(orderCardId, fromUserId.value);
  416. common_vendor.index.__f__("log", "at pages/chat/chat.vue:776", "🔥 支付接口响应:", payRes);
  417. if (!(payRes.code === 200 || payRes.code === 0)) {
  418. common_vendor.index.hideLoading();
  419. common_vendor.index.showToast({ title: payRes.msg || "创建支付订单失败", icon: "none" });
  420. common_vendor.index.__f__("log", "at pages/chat/chat.vue:781", "🔥 支付接口调用失败:", payRes);
  421. return;
  422. }
  423. if (payRes.data && payRes.data.wechatPayParams) {
  424. const wxPayParams = payRes.data.wechatPayParams;
  425. common_vendor.index.hideLoading();
  426. common_vendor.index.showLoading({ title: "发起微信支付..." });
  427. common_vendor.index.requestPayment({
  428. provider: "wxpay",
  429. timeStamp: wxPayParams.timeStamp,
  430. nonceStr: wxPayParams.nonceStr,
  431. package: wxPayParams.package,
  432. signType: wxPayParams.signType || "RSA",
  433. paySign: wxPayParams.paySign,
  434. success: (res) => {
  435. common_vendor.index.hideLoading();
  436. common_vendor.index.__f__("log", "at pages/chat/chat.vue:802", "微信支付成功:", res);
  437. msg.isPaid = true;
  438. common_vendor.index.showToast({ title: "支付成功", icon: "success" });
  439. if (assessmentId.value) {
  440. const paidKey = `audit_paid_${assessmentId.value}`;
  441. common_vendor.index.setStorageSync(paidKey, true);
  442. common_vendor.index.__f__("log", "at pages/chat/chat.vue:813", "[Chat] 支付成功,写入 key:", paidKey);
  443. }
  444. if (chatType.value === "job" && positionId.value) {
  445. const fallbackKey = `audit_paid_pos_${positionId.value}`;
  446. common_vendor.index.setStorageSync(fallbackKey, true);
  447. common_vendor.index.__f__("log", "at pages/chat/chat.vue:819", "[Chat] 兜底写入 key:", fallbackKey);
  448. }
  449. msg.payload = {
  450. ...msg.payload || {},
  451. orderCardId,
  452. orderId: payRes.data.orderId,
  453. orderNo: payRes.data.orderNo || "",
  454. status: "paid"
  455. };
  456. common_vendor.index.$emit("payment_done", {
  457. orderCardId,
  458. orderId: payRes.data.orderId,
  459. assessmentId: assessmentId.value,
  460. positionId: positionId.value,
  461. paid: true
  462. });
  463. if (chatType.value === "assessment") {
  464. setTimeout(() => {
  465. common_vendor.index.navigateTo({ url: `/pages/assessment/training?title=${encodeURIComponent(assessmentTitle.value)}&assessmentId=${assessmentId.value}` });
  466. }, 1200);
  467. }
  468. },
  469. fail: (err) => {
  470. common_vendor.index.hideLoading();
  471. common_vendor.index.__f__("error", "at pages/chat/chat.vue:848", "微信支付失败:", err);
  472. if (err.errMsg && err.errMsg.includes("cancel")) {
  473. common_vendor.index.showToast({ title: "支付已取消", icon: "none" });
  474. } else {
  475. common_vendor.index.showToast({ title: "支付失败,请重试", icon: "none" });
  476. }
  477. }
  478. });
  479. } else {
  480. common_vendor.index.hideLoading();
  481. if (payRes.data && payRes.data.success) {
  482. msg.isPaid = true;
  483. common_vendor.index.showToast({ title: payRes.data.message || "支付成功", icon: "success" });
  484. } else {
  485. common_vendor.index.showToast({ title: "支付处理异常", icon: "none" });
  486. }
  487. }
  488. } catch (e) {
  489. common_vendor.index.hideLoading();
  490. common_vendor.index.__f__("error", "at pages/chat/chat.vue:871", "支付失败:", e);
  491. common_vendor.index.showToast({ title: "支付失败:" + (e.message || "网络错误"), icon: "none" });
  492. }
  493. }
  494. const chatBodyHeight = common_vendor.computed(() => {
  495. const navH = 100;
  496. const footerH = activePanel.value === "none" ? 120 : 520;
  497. return `calc(100vh - ${navH}rpx - ${footerH}rpx - env(safe-area-inset-top) - env(safe-area-inset-bottom))`;
  498. });
  499. function scrollToBottom() {
  500. common_vendor.nextTick$1(() => {
  501. lastMessageId.value = "";
  502. common_vendor.nextTick$1(() => {
  503. lastMessageId.value = "bottom-anchor";
  504. });
  505. });
  506. }
  507. function goBack() {
  508. common_vendor.index.navigateBack();
  509. }
  510. function toggleInputMode() {
  511. inputMode.value = inputMode.value === "text" ? "voice" : "text";
  512. activePanel.value = "none";
  513. }
  514. function togglePanel(panel) {
  515. activePanel.value = activePanel.value === panel ? "none" : panel;
  516. if (activePanel.value !== "none")
  517. inputMode.value = "text";
  518. scrollToBottom();
  519. }
  520. function onInputFocus() {
  521. activePanel.value = "none";
  522. scrollToBottom();
  523. }
  524. function addEmoji(e) {
  525. inputValue.value += e;
  526. }
  527. function previewImg(url) {
  528. common_vendor.index.previewImage({ urls: [url], current: url });
  529. }
  530. function formatFileSize(size) {
  531. if (!size)
  532. return "";
  533. if (size < 1024)
  534. return size + "B";
  535. if (size < 1024 * 1024)
  536. return (size / 1024).toFixed(1) + "KB";
  537. return (size / 1024 / 1024).toFixed(1) + "MB";
  538. }
  539. function formatTime(timeStr) {
  540. if (!timeStr)
  541. return "";
  542. const d = new Date(timeStr);
  543. if (isNaN(d))
  544. return timeStr;
  545. const pad = (n) => n.toString().padStart(2, "0");
  546. return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
  547. }
  548. function shouldShowTime(msg, index) {
  549. if (index === 0)
  550. return true;
  551. const prev = messages.value[index - 1];
  552. if (!prev.sendTime || !msg.sendTime)
  553. return false;
  554. return new Date(msg.sendTime) - new Date(prev.sendTime) > 5 * 60 * 1e3;
  555. }
  556. function formatAmount(amount) {
  557. if (!amount && amount !== 0)
  558. return "—";
  559. const num = typeof amount === "string" ? parseFloat(amount) : amount;
  560. if (isNaN(num))
  561. return "—";
  562. return num.toFixed(2).replace(/\.?0+$/, "");
  563. }
  564. const onVoiceStart = () => common_vendor.index.showToast({ title: "录音中...", icon: "none" });
  565. const onVoiceEnd = () => common_vendor.index.showToast({ title: "语音功能暂未开放", icon: "none" });
  566. return (_ctx, _cache) => {
  567. return common_vendor.e({
  568. a: statusBarHeight.value + "px",
  569. b: common_vendor.o(goBack),
  570. c: common_vendor.t(sessionUserName.value || "在线咨询"),
  571. d: loading.value
  572. }, loading.value ? {} : {}, {
  573. e: !loading.value
  574. }, !loading.value ? common_vendor.e({
  575. f: chatType.value === "assessment"
  576. }, chatType.value === "assessment" ? common_vendor.e({
  577. g: waiterAvatar.value,
  578. h: assessmentCover.value || "/static/images/assess_cover.svg",
  579. i: common_vendor.t(assessmentTitle.value || "测评咨询"),
  580. j: assessmentLevel.value
  581. }, assessmentLevel.value ? {
  582. k: common_vendor.t(assessmentLevel.value)
  583. } : {}, {
  584. l: common_vendor.t(assessmentPrice.value ? "¥" + assessmentPrice.value : "咨询获取")
  585. }) : chatType.value === "training" ? {
  586. n: waiterAvatar.value,
  587. o: common_vendor.t(trainingTitle.value || "审计员线下培训"),
  588. p: common_vendor.o(confirmReg)
  589. } : {
  590. q: waiterAvatar.value,
  591. r: common_vendor.t(jobName.value || "审计员"),
  592. s: common_vendor.t(salaryRange.value || "13K-23K"),
  593. t: common_assets._imports_0$2,
  594. v: common_assets._imports_1$1,
  595. w: common_assets._imports_2$3,
  596. x: common_vendor.t(companyName.value || "华财仁合"),
  597. y: common_assets._imports_2$1,
  598. z: common_vendor.t((workCity.value || "上海市") + "·" + (workDistrict.value || "黄浦区"))
  599. }, {
  600. m: chatType.value === "training"
  601. }) : {}, {
  602. A: !loading.value && messages.value.length === 0
  603. }, !loading.value && messages.value.length === 0 ? {} : {}, {
  604. B: common_vendor.f(messages.value, (msg, index, i0) => {
  605. return common_vendor.e({
  606. a: shouldShowTime(msg, index)
  607. }, shouldShowTime(msg, index) ? {
  608. b: common_vendor.t(formatTime(msg.sendTime))
  609. } : {}, {
  610. c: msg.senderType !== 1
  611. }, msg.senderType !== 1 ? {
  612. d: resolveAvatarUrl(msg.senderAvatar) || waiterAvatar.value
  613. } : {}, {
  614. e: msg.msgType === "text"
  615. }, msg.msgType === "text" ? {
  616. f: common_vendor.t(msg.content),
  617. g: common_vendor.n(msg.senderType === 1 ? "user-bubble" : "shadow")
  618. } : msg.msgType === "image" ? {
  619. i: msg.fileUrl,
  620. j: common_vendor.o(($event) => previewImg(msg.fileUrl), msg.id || index)
  621. } : msg.msgType === "file" ? {
  622. l: common_vendor.t(msg.fileName || "文件"),
  623. m: common_vendor.t(formatFileSize(msg.fileSize))
  624. } : msg.msgType === "order_card" ? common_vendor.e({
  625. o: !msg.isPaid && msg.countdown > 0
  626. }, !msg.isPaid && msg.countdown > 0 ? {
  627. p: common_vendor.t(msg.countdown)
  628. } : {}, {
  629. q: msg.isPaid
  630. }, msg.isPaid ? {} : {}, {
  631. r: common_vendor.t(msg.payload && msg.payload.name || "—"),
  632. s: common_vendor.t(formatAmount(msg.payload && msg.payload.amount)),
  633. t: common_vendor.t(msg.isPaid ? "已支付" : "立即支付"),
  634. v: msg.isPaid ? 1 : "",
  635. w: common_vendor.o(($event) => handlePay(msg), msg.id || index)
  636. }) : msg.msgType === "job_card" ? common_vendor.e({
  637. y: common_vendor.t(msg.payload && msg.payload.title || "岗位推荐"),
  638. z: common_vendor.t(msg.payload && msg.payload.salaryRange || ""),
  639. A: msg.payload && msg.payload.workCity
  640. }, msg.payload && msg.payload.workCity ? {
  641. B: common_vendor.t(msg.payload.workCity)
  642. } : {}) : msg.senderType === 3 ? {
  643. D: common_vendor.t(msg.content)
  644. } : {
  645. E: common_vendor.t(msg.content || "[消息]")
  646. }, {
  647. h: msg.msgType === "image",
  648. k: msg.msgType === "file",
  649. n: msg.msgType === "order_card",
  650. x: msg.msgType === "job_card",
  651. C: msg.senderType === 3,
  652. F: msg.senderType === 1
  653. }, msg.senderType === 1 ? {
  654. G: resolveAvatarUrl(msg.senderAvatar) || userAvatarUrl.value
  655. } : {}, {
  656. H: "msg-" + (msg.id || index),
  657. I: common_vendor.n(msg.senderType === 1 ? "right" : "left"),
  658. J: msg.id || index
  659. });
  660. }),
  661. C: lastMessageId.value,
  662. D: chatBodyHeight.value,
  663. E: inputMode.value === "text" ? "/static/icons/audio_thin.svg" : "/static/icons/keyboard.svg",
  664. F: common_vendor.o(toggleInputMode),
  665. G: inputMode.value === "text"
  666. }, inputMode.value === "text" ? {
  667. H: common_vendor.o(sendMessage),
  668. I: common_vendor.o(onInputFocus),
  669. J: inputValue.value,
  670. K: common_vendor.o(($event) => inputValue.value = $event.detail.value)
  671. } : {
  672. L: common_vendor.o(onVoiceStart),
  673. M: common_vendor.o(onVoiceEnd)
  674. }, {
  675. N: common_assets._imports_4,
  676. O: activePanel.value === "emoji" ? 1 : "",
  677. P: common_vendor.o(($event) => togglePanel("emoji")),
  678. Q: activePanel.value === "plus" ? "/static/icons/plus_active.svg" : "/static/icons/plus_thin.svg",
  679. R: common_vendor.o(($event) => togglePanel("plus")),
  680. S: activePanel.value === "emoji"
  681. }, activePanel.value === "emoji" ? {
  682. T: common_vendor.f(emojiList, (e, k0, i0) => {
  683. return {
  684. a: common_vendor.t(e),
  685. b: e,
  686. c: common_vendor.o(($event) => addEmoji(e), e)
  687. };
  688. })
  689. } : {}, {
  690. U: activePanel.value === "plus"
  691. }, activePanel.value === "plus" ? {
  692. V: common_assets._imports_5,
  693. W: common_vendor.o(chooseImage),
  694. X: common_assets._imports_6,
  695. Y: common_vendor.o(sendMockOrderCard)
  696. } : {}, {
  697. Z: activePanel.value !== "none" ? 1 : "",
  698. aa: activePanel.value !== "none" ? 1 : ""
  699. });
  700. };
  701. }
  702. };
  703. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-0a633310"]]);
  704. wx.createPage(MiniProgramPage);
  705. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/chat/chat.js.map