chat.js 30 KB

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