chat.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  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_request = require("../../utils/request.js");
  7. const POLL_INTERVAL = 3e3;
  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 pollTimer = 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. startPolling();
  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:417", "自动创建结算单失败:", res);
  117. }
  118. } catch (err) {
  119. common_vendor.index.__f__("error", "at pages/chat/chat.vue:420", "自动创建结算单异常:", 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:434", "[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:449", "岗位结算单异常:", err);
  147. }
  148. }, 800);
  149. } else {
  150. common_vendor.index.__f__("log", "at pages/chat/chat.vue:452", "[Chat] 该岗位无关联测评,不发送结算单");
  151. }
  152. } catch (e) {
  153. common_vendor.index.__f__("error", "at pages/chat/chat.vue:455", "[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. stopPolling();
  171. if (orderTimer)
  172. clearInterval(orderTimer);
  173. });
  174. async function loadHistory() {
  175. try {
  176. const res = await api_message.getChatHistory({ sessionId: sessionId.value, pageNum: 1, pageSize: 50 });
  177. if (res.rows) {
  178. messages.value = res.rows.slice().reverse().map(normalizeMsg);
  179. scrollToBottom();
  180. const firstWaiterMsg = res.rows.find((m) => m.senderType === 2);
  181. if (firstWaiterMsg && firstWaiterMsg.senderAvatar) {
  182. const resolvedWaiterAvatar = resolveAvatarUrl(firstWaiterMsg.senderAvatar);
  183. if (resolvedWaiterAvatar) {
  184. waiterAvatar.value = resolvedWaiterAvatar;
  185. }
  186. }
  187. if (messages.value.length > 0) {
  188. const lastMsg = messages.value[messages.value.length - 1];
  189. if (lastMsg.id && !lastMsg.id.toString().startsWith("temp")) {
  190. api_message.markChatRead({ sessionId: sessionId.value, lastReadMsgId: lastMsg.id });
  191. }
  192. }
  193. }
  194. } catch (e) {
  195. common_vendor.index.__f__("error", "at pages/chat/chat.vue:503", "[Chat] 加载历史消息失败:", e);
  196. } finally {
  197. loading.value = false;
  198. }
  199. if (fromUserId.value) {
  200. try {
  201. const stuRes = await api_student.getStudent(fromUserId.value);
  202. if (stuRes.code === 200 && stuRes.data) {
  203. const stu = stuRes.data;
  204. const resolvedUrl = resolveAvatarUrl(stu.avatarUrl || stu.avatar);
  205. if (resolvedUrl) {
  206. userAvatarUrl.value = resolvedUrl;
  207. }
  208. }
  209. } catch (e) {
  210. common_vendor.index.__f__("warn", "at pages/chat/chat.vue:521", "[Chat] 获取学员头像失败:", e);
  211. }
  212. }
  213. }
  214. function startPolling() {
  215. stopPolling();
  216. pollTimer = setInterval(() => {
  217. if (!sessionId.value)
  218. return;
  219. pollMessages();
  220. }, POLL_INTERVAL);
  221. }
  222. function stopPolling() {
  223. if (pollTimer) {
  224. clearInterval(pollTimer);
  225. pollTimer = null;
  226. }
  227. }
  228. async function pollMessages() {
  229. if (!sessionId.value)
  230. return;
  231. try {
  232. const res = await api_message.getChatHistory({
  233. sessionId: sessionId.value,
  234. pageNum: 1,
  235. pageSize: 50,
  236. timestamp: (/* @__PURE__ */ new Date()).getTime()
  237. });
  238. if (res.rows) {
  239. const newMessages = res.rows.slice().reverse().map(normalizeMsg);
  240. const newSig = newMessages.map((m) => String(m.id) + String(m.content)).join("|");
  241. const oldSig = messages.value.filter((m) => m.id && !String(m.id).startsWith("temp")).map((m) => String(m.id) + String(m.content)).join("|");
  242. if (newSig !== oldSig) {
  243. messages.value = newMessages;
  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. }
  251. } catch (e) {
  252. common_vendor.index.__f__("error", "at pages/chat/chat.vue:577", "[Chat] 轮询消息失败:", e);
  253. }
  254. }
  255. function normalizeMsg(msg) {
  256. let payload = null;
  257. if (msg.payload) {
  258. try {
  259. payload = typeof msg.payload === "string" ? JSON.parse(msg.payload) : msg.payload;
  260. } catch (e) {
  261. }
  262. }
  263. return {
  264. id: msg.msgId,
  265. msgNo: msg.msgNo,
  266. senderType: msg.senderType,
  267. // 1=用户 2=客服 3=系统
  268. senderName: msg.senderName,
  269. senderAvatar: msg.senderAvatar,
  270. msgType: msg.msgType || "text",
  271. content: msg.content,
  272. fileUrl: msg.fileUrl,
  273. fileName: msg.fileName,
  274. fileSize: msg.fileSize,
  275. payload,
  276. sendTime: msg.sendTime,
  277. isPaid: payload && (payload.status === "paid" || payload.status === "已支付" || payload.paid === true)
  278. };
  279. }
  280. async function sendMessage() {
  281. const content = inputValue.value.trim();
  282. if (!content || !sessionId.value)
  283. return;
  284. const msgNo = "MSG_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
  285. const tempId = "temp_" + Date.now();
  286. messages.value.push({
  287. id: tempId,
  288. msgNo,
  289. senderType: 1,
  290. msgType: "text",
  291. content,
  292. sendTime: (/* @__PURE__ */ new Date()).toISOString(),
  293. payload: null
  294. });
  295. inputValue.value = "";
  296. scrollToBottom();
  297. try {
  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:686", "[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:728", "🔥 开始支付流程");
  397. common_vendor.index.__f__("log", "at pages/chat/chat.vue:729", "🔥 orderCardId:", orderCardId, "类型:", typeof orderCardId);
  398. common_vendor.index.__f__("log", "at pages/chat/chat.vue:730", "🔥 fromUserId:", fromUserId.value, "类型:", typeof fromUserId.value);
  399. common_vendor.index.__f__("log", "at pages/chat/chat.vue:731", "🔥 userInfo:", JSON.stringify(userInfo));
  400. common_vendor.index.__f__("log", "at pages/chat/chat.vue:732", "🔥 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:762", "🔥 调用支付接口,参数:", { 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:764", "🔥 支付接口响应:", 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:769", "🔥 支付接口调用失败:", 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:790", "微信支付成功:", res);
  430. msg.isPaid = true;
  431. common_vendor.index.showToast({ title: "支付成功", icon: "success" });
  432. if (assessmentId.value) {
  433. const paidKey = `audit_paid_${assessmentId.value}`;
  434. common_vendor.index.setStorageSync(paidKey, true);
  435. common_vendor.index.__f__("log", "at pages/chat/chat.vue:801", "[Chat] 支付成功,写入 key:", paidKey);
  436. }
  437. if (chatType.value === "job" && positionId.value) {
  438. const fallbackKey = `audit_paid_pos_${positionId.value}`;
  439. common_vendor.index.setStorageSync(fallbackKey, true);
  440. common_vendor.index.__f__("log", "at pages/chat/chat.vue:807", "[Chat] 兜底写入 key:", fallbackKey);
  441. }
  442. msg.payload = {
  443. ...msg.payload || {},
  444. orderCardId,
  445. orderId: payRes.data.orderId,
  446. orderNo: payRes.data.orderNo || "",
  447. status: "paid"
  448. };
  449. common_vendor.index.$emit("payment_done", {
  450. orderCardId,
  451. orderId: payRes.data.orderId,
  452. assessmentId: assessmentId.value,
  453. positionId: positionId.value,
  454. paid: true
  455. });
  456. if (chatType.value === "assessment") {
  457. setTimeout(() => {
  458. common_vendor.index.navigateTo({ url: `/pages/assessment/training?title=${encodeURIComponent(assessmentTitle.value)}&assessmentId=${assessmentId.value}` });
  459. }, 1200);
  460. }
  461. },
  462. fail: (err) => {
  463. common_vendor.index.hideLoading();
  464. common_vendor.index.__f__("error", "at pages/chat/chat.vue:836", "微信支付失败:", err);
  465. if (err.errMsg && err.errMsg.includes("cancel")) {
  466. common_vendor.index.showToast({ title: "支付已取消", icon: "none" });
  467. } else {
  468. common_vendor.index.showToast({ title: "支付失败,请重试", icon: "none" });
  469. }
  470. }
  471. });
  472. } else {
  473. common_vendor.index.hideLoading();
  474. if (payRes.data && payRes.data.success) {
  475. msg.isPaid = true;
  476. common_vendor.index.showToast({ title: payRes.data.message || "支付成功", icon: "success" });
  477. } else {
  478. common_vendor.index.showToast({ title: "支付处理异常", icon: "none" });
  479. }
  480. }
  481. } catch (e) {
  482. common_vendor.index.hideLoading();
  483. common_vendor.index.__f__("error", "at pages/chat/chat.vue:859", "支付失败:", e);
  484. common_vendor.index.showToast({ title: "支付失败:" + (e.message || "网络错误"), icon: "none" });
  485. }
  486. }
  487. const chatBodyHeight = common_vendor.computed(() => {
  488. const navH = 100;
  489. const footerH = activePanel.value === "none" ? 120 : 520;
  490. return `calc(100vh - ${navH}rpx - ${footerH}rpx - env(safe-area-inset-top) - env(safe-area-inset-bottom))`;
  491. });
  492. function scrollToBottom() {
  493. common_vendor.nextTick$1(() => {
  494. lastMessageId.value = "";
  495. common_vendor.nextTick$1(() => {
  496. lastMessageId.value = "bottom-anchor";
  497. });
  498. });
  499. }
  500. function goBack() {
  501. common_vendor.index.navigateBack();
  502. }
  503. function toggleInputMode() {
  504. inputMode.value = inputMode.value === "text" ? "voice" : "text";
  505. activePanel.value = "none";
  506. }
  507. function togglePanel(panel) {
  508. activePanel.value = activePanel.value === panel ? "none" : panel;
  509. if (activePanel.value !== "none")
  510. inputMode.value = "text";
  511. scrollToBottom();
  512. }
  513. function onInputFocus() {
  514. activePanel.value = "none";
  515. scrollToBottom();
  516. }
  517. function addEmoji(e) {
  518. inputValue.value += e;
  519. }
  520. function previewImg(url) {
  521. common_vendor.index.previewImage({ urls: [url], current: url });
  522. }
  523. function formatFileSize(size) {
  524. if (!size)
  525. return "";
  526. if (size < 1024)
  527. return size + "B";
  528. if (size < 1024 * 1024)
  529. return (size / 1024).toFixed(1) + "KB";
  530. return (size / 1024 / 1024).toFixed(1) + "MB";
  531. }
  532. function formatTime(timeStr) {
  533. if (!timeStr)
  534. return "";
  535. const d = new Date(timeStr);
  536. if (isNaN(d))
  537. return timeStr;
  538. const pad = (n) => n.toString().padStart(2, "0");
  539. return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
  540. }
  541. function shouldShowTime(msg, index) {
  542. if (index === 0)
  543. return true;
  544. const prev = messages.value[index - 1];
  545. if (!prev.sendTime || !msg.sendTime)
  546. return false;
  547. return new Date(msg.sendTime) - new Date(prev.sendTime) > 5 * 60 * 1e3;
  548. }
  549. function formatAmount(amount) {
  550. if (!amount && amount !== 0)
  551. return "—";
  552. const num = typeof amount === "string" ? parseFloat(amount) : amount;
  553. if (isNaN(num))
  554. return "—";
  555. return num.toFixed(2).replace(/\.?0+$/, "");
  556. }
  557. const onVoiceStart = () => common_vendor.index.showToast({ title: "录音中...", icon: "none" });
  558. const onVoiceEnd = () => common_vendor.index.showToast({ title: "语音功能暂未开放", icon: "none" });
  559. return (_ctx, _cache) => {
  560. return common_vendor.e({
  561. a: statusBarHeight.value + "px",
  562. b: common_vendor.o(goBack),
  563. c: common_vendor.t(sessionUserName.value || "在线咨询"),
  564. d: loading.value
  565. }, loading.value ? {} : {}, {
  566. e: !loading.value
  567. }, !loading.value ? common_vendor.e({
  568. f: chatType.value === "assessment"
  569. }, chatType.value === "assessment" ? common_vendor.e({
  570. g: waiterAvatar.value,
  571. h: assessmentCover.value || "/static/images/assess_cover.svg",
  572. i: common_vendor.t(assessmentTitle.value || "测评咨询"),
  573. j: assessmentLevel.value
  574. }, assessmentLevel.value ? {
  575. k: common_vendor.t(assessmentLevel.value)
  576. } : {}, {
  577. l: common_vendor.t(assessmentPrice.value ? "¥" + assessmentPrice.value : "咨询获取")
  578. }) : chatType.value === "training" ? {
  579. n: waiterAvatar.value,
  580. o: common_vendor.t(trainingTitle.value || "审计员线下培训"),
  581. p: common_vendor.o(confirmReg)
  582. } : {
  583. q: waiterAvatar.value,
  584. r: common_vendor.t(jobName.value || "审计员"),
  585. s: common_vendor.t(salaryRange.value || "13K-23K"),
  586. t: common_assets._imports_0$2,
  587. v: common_assets._imports_1$1,
  588. w: common_assets._imports_2$3,
  589. x: common_vendor.t(companyName.value || "华财仁合"),
  590. y: common_assets._imports_2$1,
  591. z: common_vendor.t((workCity.value || "上海市") + "·" + (workDistrict.value || "黄浦区"))
  592. }, {
  593. m: chatType.value === "training"
  594. }) : {}, {
  595. A: !loading.value && messages.value.length === 0
  596. }, !loading.value && messages.value.length === 0 ? {} : {}, {
  597. B: common_vendor.f(messages.value, (msg, index, i0) => {
  598. return common_vendor.e({
  599. a: shouldShowTime(msg, index)
  600. }, shouldShowTime(msg, index) ? {
  601. b: common_vendor.t(formatTime(msg.sendTime))
  602. } : {}, {
  603. c: msg.senderType !== 1
  604. }, msg.senderType !== 1 ? {
  605. d: resolveAvatarUrl(msg.senderAvatar) || waiterAvatar.value
  606. } : {}, {
  607. e: msg.msgType === "text"
  608. }, msg.msgType === "text" ? {
  609. f: common_vendor.t(msg.content),
  610. g: common_vendor.n(msg.senderType === 1 ? "user-bubble" : "shadow")
  611. } : msg.msgType === "image" ? {
  612. i: msg.fileUrl,
  613. j: common_vendor.o(($event) => previewImg(msg.fileUrl), msg.id || index)
  614. } : msg.msgType === "file" ? {
  615. l: common_vendor.t(msg.fileName || "文件"),
  616. m: common_vendor.t(formatFileSize(msg.fileSize))
  617. } : msg.msgType === "order_card" ? common_vendor.e({
  618. o: !msg.isPaid && msg.countdown > 0
  619. }, !msg.isPaid && msg.countdown > 0 ? {
  620. p: common_vendor.t(msg.countdown)
  621. } : {}, {
  622. q: msg.isPaid
  623. }, msg.isPaid ? {} : {}, {
  624. r: common_vendor.t(msg.payload && msg.payload.name || "—"),
  625. s: common_vendor.t(formatAmount(msg.payload && msg.payload.amount)),
  626. t: common_vendor.t(msg.isPaid ? "已支付" : "立即支付"),
  627. v: msg.isPaid ? 1 : "",
  628. w: common_vendor.o(($event) => handlePay(msg), msg.id || index)
  629. }) : msg.msgType === "job_card" ? common_vendor.e({
  630. y: common_vendor.t(msg.payload && msg.payload.title || "岗位推荐"),
  631. z: common_vendor.t(msg.payload && msg.payload.salaryRange || ""),
  632. A: msg.payload && msg.payload.workCity
  633. }, msg.payload && msg.payload.workCity ? {
  634. B: common_vendor.t(msg.payload.workCity)
  635. } : {}) : msg.senderType === 3 ? {
  636. D: common_vendor.t(msg.content)
  637. } : {
  638. E: common_vendor.t(msg.content || "[消息]")
  639. }, {
  640. h: msg.msgType === "image",
  641. k: msg.msgType === "file",
  642. n: msg.msgType === "order_card",
  643. x: msg.msgType === "job_card",
  644. C: msg.senderType === 3,
  645. F: msg.senderType === 1
  646. }, msg.senderType === 1 ? {
  647. G: resolveAvatarUrl(msg.senderAvatar) || userAvatarUrl.value
  648. } : {}, {
  649. H: "msg-" + (msg.id || index),
  650. I: common_vendor.n(msg.senderType === 1 ? "right" : "left"),
  651. J: msg.id || index
  652. });
  653. }),
  654. C: lastMessageId.value,
  655. D: chatBodyHeight.value,
  656. E: inputMode.value === "text" ? "/static/icons/audio_thin.svg" : "/static/icons/keyboard.svg",
  657. F: common_vendor.o(toggleInputMode),
  658. G: inputMode.value === "text"
  659. }, inputMode.value === "text" ? {
  660. H: common_vendor.o(sendMessage),
  661. I: common_vendor.o(onInputFocus),
  662. J: inputValue.value,
  663. K: common_vendor.o(($event) => inputValue.value = $event.detail.value)
  664. } : {
  665. L: common_vendor.o(onVoiceStart),
  666. M: common_vendor.o(onVoiceEnd)
  667. }, {
  668. N: common_assets._imports_4,
  669. O: activePanel.value === "emoji" ? 1 : "",
  670. P: common_vendor.o(($event) => togglePanel("emoji")),
  671. Q: activePanel.value === "plus" ? "/static/icons/plus_active.svg" : "/static/icons/plus_thin.svg",
  672. R: common_vendor.o(($event) => togglePanel("plus")),
  673. S: activePanel.value === "emoji"
  674. }, activePanel.value === "emoji" ? {
  675. T: common_vendor.f(emojiList, (e, k0, i0) => {
  676. return {
  677. a: common_vendor.t(e),
  678. b: e,
  679. c: common_vendor.o(($event) => addEmoji(e), e)
  680. };
  681. })
  682. } : {}, {
  683. U: activePanel.value === "plus"
  684. }, activePanel.value === "plus" ? {
  685. V: common_assets._imports_5,
  686. W: common_vendor.o(chooseImage),
  687. X: common_assets._imports_6,
  688. Y: common_vendor.o(sendMockOrderCard)
  689. } : {}, {
  690. Z: activePanel.value !== "none" ? 1 : "",
  691. aa: activePanel.value !== "none" ? 1 : ""
  692. });
  693. };
  694. }
  695. };
  696. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-0a633310"]]);
  697. wx.createPage(MiniProgramPage);
  698. //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/chat/chat.js.map