chat.js 29 KB

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