/******/ (function() { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ 4677: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); /* harmony import */ var _components_LoginView_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3727); /* harmony import */ var _components_ChatShell_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9531); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(926); /* harmony default export */ __webpack_exports__.A = ({ __name: 'App', setup(__props) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_4__/* .useSessionStore */ .B)(); (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .onMounted */ .sV)(() => { session.restore(); }); return (_ctx, _cache) => { return !(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .unref */ .R1)(session).isAuthenticated ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_components_LoginView_vue__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A, { key: 0 })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_components_ChatShell_vue__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A, { key: 1 })); }; } }); /***/ }), /***/ 2511: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); /* harmony import */ var _sidebar_NavigationRail_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8328); /* harmony import */ var _sidebar_ConversationList_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(371); /* harmony import */ var _sidebar_ContactList_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578); /* harmony import */ var _chat_ChatPanel_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7014); /* harmony import */ var _contacts_ContactPanel_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3351); /* harmony import */ var _favorites_FavoriteList_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(163); /* harmony import */ var _favorites_FavoritePanel_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(9123); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(7566); /* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(1414); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(9045); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(6384); const _hoisted_1 = { class: "app-shell" }; /* harmony default export */ __webpack_exports__.A = ({ __name: 'ChatShell', setup(__props) { const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_9__/* .useConversationStore */ .w)(); const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_10__/* .useNavigationStore */ .l)(); const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_11__/* .useContactStore */ .p)(); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_12__/* .useAutoDismiss */ .R)(() => conversations.actionError || conversations.actionNotice, value => { if ((conversations.actionError || conversations.actionNotice) === value) { conversations.actionError = ''; conversations.actionNotice = ''; } }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_12__/* .useAutoDismiss */ .R)(() => contacts.actionError || contacts.actionInfo, value => { if ((contacts.actionError || contacts.actionInfo) === value) { contacts.actionError = ''; contacts.actionInfo = ''; } }); (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .onMounted */ .sV)(() => { conversations.refreshRemoteConversations(); contacts.refreshContacts(); }); return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createElementBlock */ .CE)("main", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createVNode */ .bF)(_sidebar_NavigationRail_vue__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .unref */ .R1)(navigation).section === 'messages' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_sidebar_ConversationList_vue__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A, { key: 0 })) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .unref */ .R1)(navigation).section === 'favorites' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_favorites_FavoriteList_vue__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .A, { key: 1 })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_sidebar_ContactList_vue__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .A, { key: 2 })), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .unref */ .R1)(navigation).section === 'messages' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_chat_ChatPanel_vue__WEBPACK_IMPORTED_MODULE_5__/* ["default"] */ .A, { key: 3 })) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .unref */ .R1)(navigation).section === 'favorites' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_favorites_FavoritePanel_vue__WEBPACK_IMPORTED_MODULE_8__/* ["default"] */ .A, { key: 4 })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createBlock */ .Wv)(_contacts_ContactPanel_vue__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */ .A, { key: 5 }))]); }; } }); /***/ }), /***/ 8607: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5187); /* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(2387); /* harmony import */ var jr_qrcode__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2789); /* harmony import */ var jr_qrcode__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(jr_qrcode__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(2169); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(926); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5051); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(6384); const _hoisted_1 = { class: "login-page" }; const _hoisted_2 = { class: "login-panel" }; const _hoisted_3 = { class: "brand-lockup" }; const _hoisted_4 = ["src", "alt"]; const _hoisted_5 = { class: "login-tabs register-tabs", style: { gridTemplateColumns: 'repeat(3, minmax(0, 1fr))' } }; const _hoisted_6 = ["disabled"]; const _hoisted_7 = ["src"]; const _hoisted_8 = { key: 1 }; const _hoisted_9 = { key: 0, class: "qr-scan-user" }; const _hoisted_10 = ["src"]; const _hoisted_11 = { key: 1 }; const _hoisted_12 = { class: "qr-login-status" }; const _hoisted_13 = ["disabled"]; const _hoisted_14 = ["autocomplete", "inputmode", "placeholder"]; const _hoisted_15 = ["disabled"]; const _hoisted_16 = { key: 2, class: "form-error" }; const _hoisted_17 = { key: 3, class: "form-info" }; const _hoisted_18 = { class: "login-tabs register-tabs", style: { gridTemplateColumns: 'repeat(2, minmax(0, 1fr))' } }; const _hoisted_19 = ["autocomplete", "inputmode", "placeholder"]; const _hoisted_20 = { key: 0 }; const _hoisted_21 = { class: "code-row" }; const _hoisted_22 = ["disabled"]; const _hoisted_23 = ["disabled"]; const _hoisted_24 = { key: 1, class: "form-error" }; const _hoisted_25 = { key: 2, class: "form-info" }; const QR_CODE_PREFIX_PC_SESSION = 'wildfirechat://pcsession/'; const defaultPlatformLogo = '/favicon.ico'; /* harmony default export */ __webpack_exports__.A = ({ __name: 'LoginView', setup(__props) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_8__/* .useSessionStore */ .B)(); const view = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)('login'); const loginMode = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)('phone'); const loginAccount = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); const loginPassword = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); const registerType = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(1); const registerForm = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .reactive */ .Kh)({ number: '', code: '', password: '', confirmPassword: '', invitationCode: '' }); const sendingCode = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(false); const info = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_10__/* .useAutoDismiss */ .R)(() => session.error, value => { if (session.error === value) session.error = ''; }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_10__/* .useAutoDismiss */ .R)(info, value => { if (info.value === value) info.value = ''; }); const qrStatus = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)('idle'); const qrCodeImage = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); const qrSessionToken = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); const qrUserName = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); const qrUserPortrait = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(''); let qrGeneration = 0; let qrExpireTimer = null; const defaultPlatformName = _config__WEBPACK_IMPORTED_MODULE_7__/* .appConfig */ .U.appName; const platformName = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(defaultPlatformName); const platformLogo = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .ref */ .KR)(defaultPlatformLogo); const canSubmitLogin = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => loginAccount.value.length >= 3 && loginPassword.value.length >= 1); const canRequestEmailCode = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => registerType.value === 2 && /\S+@\S+\.\S+/.test(registerForm.number)); const canSubmitRegister = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => { if (registerForm.password.length < 1 || registerForm.password !== registerForm.confirmPassword) { return false; } if (registerType.value === 2) { return canRequestEmailCode.value && registerForm.code.length >= 1; } return registerForm.number.length >= 5; }); const qrUserInitial = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => String(qrUserName.value || 'U').slice(0, 1).toUpperCase()); const qrStatusTitle = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => { if (session.connecting || qrStatus.value === 'confirmed') { return '正在进入'; } if (qrStatus.value === 'loading') { return '正在生成二维码'; } if (qrStatus.value === 'scanned') { return qrUserName.value ? `${qrUserName.value} 已扫码` : '已扫码,待确认'; } if (qrStatus.value === 'expired') { return '二维码已过期'; } if (qrStatus.value === 'error') { return '二维码加载失败'; } return '扫码登录'; }); const qrStatusText = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => { if (session.connecting || qrStatus.value === 'confirmed') { return '登录信息已确认,正在建立连接'; } if (qrStatus.value === 'loading') { return '正在创建扫码登录会话'; } if (qrStatus.value === 'scanned') { return '请在手机 App 上确认登录'; } if (qrStatus.value === 'expired') { return '请刷新二维码后重新扫码'; } if (qrStatus.value === 'error') { return '请稍后重试'; } return '使用已登录的手机 App 扫描二维码'; }); const qrRefreshText = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => { if (qrStatus.value === 'loading') { return '生成中...'; } if (qrStatus.value === 'expired' || qrStatus.value === 'error') { return '重新生成二维码'; } return '刷新二维码'; }); (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .onMounted */ .sV)(() => { loadPlatformConfig(); }); (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .onBeforeUnmount */ .xo)(() => { stopQrLogin(); }); function clearFormMessage() { session.error = ''; info.value = ''; } function setLoginMode(mode) { loginMode.value = mode; loginAccount.value = ''; loginPassword.value = ''; clearFormMessage(); if (mode === 'qr') { startQrLogin(); return; } stopQrLogin(); } async function submitLogin() { clearFormMessage(); const type = loginMode.value === 'email' ? 2 : 1; await session.loginWithPassword(loginAccount.value, loginPassword.value, type); } function switchRegisterType(type) { registerType.value = type; registerForm.number = ''; registerForm.code = ''; registerForm.password = ''; registerForm.confirmPassword = ''; registerForm.invitationCode = ''; clearFormMessage(); } async function requestEmailCode() { clearFormMessage(); sendingCode.value = true; try { await _services_imClient__WEBPACK_IMPORTED_MODULE_9__/* .imClient */ .wD.requestAuthCode(registerForm.number); info.value = '邮箱验证码已发送,请在当前注册表单中填写后继续。'; } catch (error) { session.error = error.message || '验证码发送失败'; } finally { sendingCode.value = false; } } async function submitRegister() { clearFormMessage(); if (registerForm.password !== registerForm.confirmPassword) { session.error = '两次输入的密码不一致'; return; } const result = await session.register({ type: registerType.value, number: registerForm.number, code: registerType.value === 2 ? registerForm.code : '', password: registerForm.password, invitationCode: registerForm.invitationCode }); if (result) { info.value = '注册成功,正在进入系统。'; } } function openRegister() { clearFormMessage(); stopQrLogin(); view.value = 'register'; } function backToLogin() { clearFormMessage(); loginMode.value = 'phone'; stopQrLogin(); view.value = 'login'; } function resetQrState() { qrStatus.value = 'idle'; qrCodeImage.value = ''; qrSessionToken.value = ''; qrUserName.value = ''; qrUserPortrait.value = ''; } function clearQrExpireTimer() { if (qrExpireTimer) { window.clearTimeout(qrExpireTimer); qrExpireTimer = null; } } function stopQrLogin() { qrGeneration += 1; clearQrExpireTimer(); resetQrState(); } function refreshQrLogin() { startQrLogin(true); } async function startQrLogin(force = false) { if (loginMode.value !== 'qr') { return; } if (!force && qrSessionToken.value && qrCodeImage.value && !['expired', 'error'].includes(qrStatus.value)) { return; } qrGeneration += 1; const generation = qrGeneration; clearQrExpireTimer(); clearFormMessage(); qrStatus.value = 'loading'; qrCodeImage.value = ''; qrSessionToken.value = ''; qrUserName.value = ''; qrUserPortrait.value = ''; try { const pcSession = await _services_imClient__WEBPACK_IMPORTED_MODULE_9__/* .imClient */ .wD.createPcSession(); if (generation !== qrGeneration || loginMode.value !== 'qr') { return; } const token = String(pcSession.token || ''); if (!token) { throw new Error('服务端没有返回扫码 token'); } qrSessionToken.value = token; qrCodeImage.value = jr_qrcode__WEBPACK_IMPORTED_MODULE_6___default().getQrBase64(QR_CODE_PREFIX_PC_SESSION + token); qrStatus.value = 'waiting'; const expireMs = Math.max(30000, Math.min(Number(pcSession.expired || 300000), 300000)); qrExpireTimer = window.setTimeout(() => { if (generation === qrGeneration && qrStatus.value !== 'confirmed' && !session.isAuthenticated) { qrStatus.value = 'expired'; } }, expireMs); pollQrLogin(generation, token); } catch (error) { if (generation !== qrGeneration) { return; } qrStatus.value = 'error'; session.error = error.message || '二维码加载失败'; } } async function pollQrLogin(generation, token) { try { while (generation === qrGeneration && loginMode.value === 'qr' && !session.isAuthenticated) { const payload = await _services_imClient__WEBPACK_IMPORTED_MODULE_9__/* .imClient */ .wD.loginWithPcSession(token); if (generation !== qrGeneration || loginMode.value !== 'qr') { return; } const code = Number(payload.code); const data = payload.data || payload.result || {}; const status = Number(data.status); if (code === 0 && data.imToken) { qrStatus.value = 'confirmed'; clearQrExpireTimer(); await session.completePcSessionLogin(data); return; } if (code === 20042 || status === 1 || status === 3) { qrStatus.value = 'scanned'; qrUserName.value = data.userName || data.displayName || qrUserName.value; qrUserPortrait.value = data.portrait || qrUserPortrait.value; await delay(1000); continue; } if (status === 0 || code === 13) { qrStatus.value = 'waiting'; await delay(1000); continue; } if (status === 4) { qrStatus.value = 'expired'; session.error = payload.message || '扫码登录已取消'; return; } if (payload.message) { throw new Error(payload.message); } await delay(1000); } } catch (error) { if (generation === qrGeneration && loginMode.value === 'qr' && !session.isAuthenticated) { qrStatus.value = 'error'; session.error = error.message || '扫码登录失败'; } } } function delay(ms) { return new Promise(resolve => window.setTimeout(resolve, ms)); } async function loadPlatformConfig() { try { const response = await axios__WEBPACK_IMPORTED_MODULE_5__/* ["default"] */ .A.get(_config__WEBPACK_IMPORTED_MODULE_7__/* .appConfig */ .U.platformConfigApi, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '平台配置加载失败'); } const config = response.data?.result || {}; const name = String(config.platformName || '').trim(); const logo = String(config.logoUrl || config.logo || '').trim(); const version = String(config.version || '').trim(); platformName.value = name || defaultPlatformName; platformLogo.value = resolveBrandLogo(logo, version); } catch (error) { platformName.value = defaultPlatformName; platformLogo.value = defaultPlatformLogo; } applyDocumentBrand(); } function resolveBrandLogo(value, version = '') { const logo = String(value || '').trim(); if (!logo) { return defaultPlatformLogo; } if (/^(https?:|data:|blob:)/i.test(logo)) { return appendBrandVersion(logo, version); } if (logo.startsWith('//')) { return appendBrandVersion(`${window.location.protocol}${logo}`, version); } const base = logo.startsWith('/') ? _config__WEBPACK_IMPORTED_MODULE_7__/* .appConfig */ .U.adminServer : `${_config__WEBPACK_IMPORTED_MODULE_7__/* .appConfig */ .U.adminServer}/`; return appendBrandVersion(new URL(logo, base).toString(), version); } function appendBrandVersion(url, version) { if (!version || /^(data:|blob:)/i.test(url)) { return url; } const parsed = new URL(url, window.location.href); parsed.searchParams.set('v', version); return parsed.toString(); } function applyDocumentBrand() { if (typeof document === 'undefined') { return; } document.title = platformName.value || defaultPlatformName; let icon = document.querySelector('link[rel="icon"]'); if (!icon) { icon = document.createElement('link'); icon.setAttribute('rel', 'icon'); document.head.appendChild(icon); } icon.setAttribute('href', platformLogo.value || defaultPlatformLogo); } function handleBrandLogoError() { if (platformLogo.value !== defaultPlatformLogo) { platformLogo.value = defaultPlatformLogo; applyDocumentBrand(); } } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("main", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("section", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("img", { class: "brand-mark", src: platformLogo.value, alt: `${platformName.value} logo`, onError: handleBrandLogoError }, null, 40, _hoisted_4), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", null, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("h1", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(platformName.value), 1)])]), view.value === 'login' ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("form", { key: 0, class: "login-form", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .withModifiers */ .D$)(submitLogin, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)({ active: loginMode.value === 'qr' }), onClick: _cache[0] || (_cache[0] = $event => setLoginMode('qr')) }, "扫码登录", 2), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)({ active: loginMode.value === 'phone' }), onClick: _cache[1] || (_cache[1] = $event => setLoginMode('phone')) }, "手机号", 2), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)({ active: loginMode.value === 'email' }), onClick: _cache[2] || (_cache[2] = $event => setLoginMode('email')) }, "邮箱", 2)]), loginMode.value === 'qr' ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_2__/* .Fragment */ .FK, { key: 0 }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", { class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)(["qr-login-card", { scanned: qrStatus.value === 'scanned', expired: qrStatus.value === 'expired', error: qrStatus.value === 'error' }]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "qr-code-button", disabled: qrStatus.value === 'loading' || (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting, onClick: refreshQrLogin }, [qrCodeImage.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("img", { key: 0, src: qrCodeImage.value, alt: "扫码登录二维码" }, null, 8, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("span", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(qrStatus.value === 'loading' ? '生成中' : '点击刷新'), 1))], 8, _hoisted_6), qrStatus.value === 'scanned' ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("div", _hoisted_9, [qrUserPortrait.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("img", { key: 0, src: qrUserPortrait.value, alt: "" }, null, 8, _hoisted_10)) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("span", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(qrUserInitial.value), 1))])) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true)], 2), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(qrStatusTitle.value), 1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(qrStatusText.value), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-action", disabled: qrStatus.value === 'loading' || (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting, onClick: refreshQrLogin }, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(qrRefreshText.value), 9, _hoisted_13)], 64)) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_2__/* .Fragment */ .FK, { key: 1 }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(loginMode.value === 'phone' ? '手机号' : '邮箱'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => loginAccount.value = $event), autocomplete: loginMode.value === 'phone' ? 'username' : 'email', inputmode: loginMode.value === 'phone' ? 'tel' : 'email', placeholder: loginMode.value === 'phone' ? '请输入手机号' : '请输入邮箱' }, null, 8, _hoisted_14), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, loginAccount.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [_cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => loginPassword.value = $event), autocomplete: "current-password", type: "password", placeholder: "请输入密码" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, loginPassword.value]])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { class: "primary-action", disabled: (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting || !canSubmitLogin.value }, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting ? '登录中...' : '登录'), 9, _hoisted_15)], 64)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).error ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("p", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).error), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), info.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("p", _hoisted_17, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(info.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true)], 32)) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("form", { key: 1, class: "login-form", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .withModifiers */ .D$)(submitRegister, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_18, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)({ active: registerType.value === 1 }), onClick: _cache[5] || (_cache[5] = $event => switchRegisterType(1)) }, "手机号注册", 2), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)({ active: registerType.value === 2 }), onClick: _cache[6] || (_cache[6] = $event => switchRegisterType(2)) }, "邮箱注册", 2)]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(registerType.value === 1 ? '手机号' : '邮箱'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[7] || (_cache[7] = $event => registerForm.number = $event), autocomplete: registerType.value === 1 ? 'tel' : 'email', inputmode: registerType.value === 1 ? 'tel' : 'email', placeholder: registerType.value === 1 ? '请输入手机号' : '请输入邮箱' }, null, 8, _hoisted_19), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, registerForm.number, void 0, { trim: true }]])]), registerType.value === 2 ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("label", _hoisted_20, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "邮箱验证码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_21, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[8] || (_cache[8] = $event => registerForm.code = $event), autocomplete: "one-time-code", inputmode: "numeric", placeholder: "请输入邮箱验证码" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, registerForm.code, void 0, { trim: true }]]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "code-action", disabled: sendingCode.value || !canRequestEmailCode.value, onClick: requestEmailCode }, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(sendingCode.value ? '发送中' : '发送验证码'), 9, _hoisted_22)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [_cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[9] || (_cache[9] = $event => registerForm.password = $event), autocomplete: "new-password", type: "password", placeholder: "请输入密码" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, registerForm.password]])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [_cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "确认密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[10] || (_cache[10] = $event => registerForm.confirmPassword = $event), autocomplete: "new-password", type: "password", placeholder: "请再次输入密码" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, registerForm.confirmPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("label", null, [_cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "邀请码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[11] || (_cache[11] = $event => registerForm.invitationCode = $event), autocomplete: "off", placeholder: "没有可留空" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_1__/* .vModelText */ .Jo, registerForm.invitationCode, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { class: "primary-action", disabled: (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting || !canSubmitRegister.value }, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).connecting ? '注册中...' : '注册并登录'), 9, _hoisted_23), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).error ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("p", _hoisted_24, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(session).error), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), info.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("p", _hoisted_25, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(info.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true)], 32)), view.value === 'login' ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("button", { key: 2, class: "ghost-action", type: "button", onClick: openRegister }, " 新用户注册 ")) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("button", { key: 3, class: "ghost-action", type: "button", onClick: backToLogin }, " 返回登录 "))])]); }; } }); /***/ }), /***/ 7562: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5367); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(2731); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(7642); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_8__); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(8004); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_9__); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(3853); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_10__); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(5876); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_11__); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(2475); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(5024); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_13__); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(1698); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_14__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(5187); /* harmony import */ var _MessageList_vue__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(9847); /* harmony import */ var _MessageComposer_vue__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(1653); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(5051); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(7566); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(9045); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(926); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(6384); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(446); const _hoisted_1 = { class: "chat-header" }; const _hoisted_2 = ["src"]; const _hoisted_3 = { key: 1, class: "chat-title-avatar" }; const _hoisted_4 = { class: "chat-title-copy" }; const _hoisted_5 = ["src"]; const _hoisted_6 = { key: 1, class: "chat-title-avatar" }; const _hoisted_7 = { class: "chat-title-copy" }; const _hoisted_8 = { key: 2 }; const _hoisted_9 = { class: "header-actions chat-header-actions" }; const _hoisted_10 = { key: 0, class: "empty-chat" }; const _hoisted_11 = { class: "pinned-message-preview" }; const _hoisted_12 = ["src"]; const _hoisted_13 = { key: 3, class: "selection-toolbar" }; const _hoisted_14 = { class: "forward-dialog" }; const _hoisted_15 = ["onClick"]; const _hoisted_16 = { class: "conversation-avatar" }; const _hoisted_17 = { type: "submit" }; const _hoisted_18 = { class: "group-dialog message-detail-dialog" }; const _hoisted_19 = { key: 0, class: "group-loading" }; const _hoisted_20 = { class: "group-profile message-detail-meta" }; const _hoisted_21 = { key: 0 }; const _hoisted_22 = { key: 0, class: "inline-save-status error" }; const _hoisted_23 = { class: "message-detail-summary" }; const _hoisted_24 = { class: "message-detail-groups" }; const _hoisted_25 = { class: "message-detail-section" }; const _hoisted_26 = { key: 0, class: "message-detail-member-list" }; const _hoisted_27 = ["src", "onError"]; const _hoisted_28 = { key: 1, class: "conversation-avatar" }; const _hoisted_29 = { class: "message-detail-member-main" }; const _hoisted_30 = { class: "message-detail-member-time" }; const _hoisted_31 = { key: 2, class: "message-detail-role" }; const _hoisted_32 = { key: 1, class: "contact-picker-empty" }; const _hoisted_33 = { class: "message-detail-section" }; const _hoisted_34 = { key: 0, class: "message-detail-member-list" }; const _hoisted_35 = ["src", "onError"]; const _hoisted_36 = { key: 1, class: "conversation-avatar" }; const _hoisted_37 = { class: "message-detail-member-main" }; const _hoisted_38 = { class: "message-detail-member-time" }; const _hoisted_39 = { key: 2, class: "message-detail-role" }; const _hoisted_40 = { key: 1, class: "contact-picker-empty" }; const _hoisted_41 = { class: "message-detail-section" }; const _hoisted_42 = { key: 0, class: "message-detail-member-list" }; const _hoisted_43 = ["src", "onError"]; const _hoisted_44 = { key: 1, class: "conversation-avatar" }; const _hoisted_45 = { class: "message-detail-member-main" }; const _hoisted_46 = { key: 2, class: "message-detail-role" }; const _hoisted_47 = { key: 1, class: "contact-picker-empty" }; const _hoisted_48 = { class: "group-dialog single-profile-dialog" }; const _hoisted_49 = { class: "single-profile-summary" }; const _hoisted_50 = ["src"]; const _hoisted_51 = { key: 1, class: "profile-avatar" }; const _hoisted_52 = { class: "group-profile" }; const _hoisted_53 = { class: "single-profile-footer" }; const _hoisted_54 = { key: 0, class: "inline-save-status" }; const _hoisted_55 = { key: 1, class: "inline-save-status error" }; const _hoisted_56 = ["disabled"]; const _hoisted_57 = ["disabled"]; const _hoisted_58 = { key: 0, class: "group-dialog" }; const _hoisted_59 = { key: 0, class: "group-loading" }; const _hoisted_60 = { key: 1, class: "group-profile" }; const _hoisted_61 = { key: 0 }; const _hoisted_62 = ["disabled"]; const _hoisted_63 = ["disabled"]; const _hoisted_64 = ["disabled"]; const _hoisted_65 = { key: 1, class: "group-dialog" }; const _hoisted_66 = { key: 0, class: "group-loading" }; const _hoisted_67 = { key: 1, class: "group-member-list" }; const _hoisted_68 = ["src", "onError"]; const _hoisted_69 = { key: 1, class: "conversation-avatar" }; const _hoisted_70 = { key: 0, class: "contact-picker-empty" }; const _hoisted_71 = ["disabled"]; const _hoisted_72 = { key: 3, class: "group-dialog" }; const _hoisted_73 = { key: 0, class: "group-loading" }; const _hoisted_74 = { key: 1, class: "group-member-list" }; const _hoisted_75 = ["onClick"]; const _hoisted_76 = ["src", "onError"]; const _hoisted_77 = { key: 1, class: "conversation-avatar" }; const _hoisted_78 = { key: 0, class: "contact-picker-empty" }; const _hoisted_79 = ["disabled"]; const _hoisted_80 = { key: 4, class: "group-dialog group-management-dialog" }; const _hoisted_81 = { class: "group-management-tabs" }; const _hoisted_82 = { key: 0, class: "group-loading" }; const _hoisted_83 = { key: 1, class: "group-manage-section" }; const _hoisted_84 = { class: "group-member-list" }; const _hoisted_85 = ["checked", "onChange"]; const _hoisted_86 = ["src", "onError"]; const _hoisted_87 = { key: 1, class: "conversation-avatar" }; const _hoisted_88 = { key: 0, class: "contact-picker-empty" }; const _hoisted_89 = { key: 2, class: "group-manage-section" }; const _hoisted_90 = { key: 3, class: "group-manage-section" }; const _hoisted_91 = { class: "group-member-list" }; const _hoisted_92 = ["checked", "onChange"]; const _hoisted_93 = ["src", "onError"]; const _hoisted_94 = { key: 1, class: "conversation-avatar" }; const _hoisted_95 = { key: 0, class: "contact-picker-empty" }; const _hoisted_96 = ["disabled"]; const _hoisted_97 = { key: 4, class: "group-manage-section" }; const _hoisted_98 = { key: 0, class: "mute-time-grid" }; const _hoisted_99 = { key: 1, class: "mute-time-grid" }; const _hoisted_100 = { class: "mute-save-footer" }; const _hoisted_101 = { key: 0, class: "inline-save-status" }; const _hoisted_102 = { key: 1, class: "inline-save-status error" }; const _hoisted_103 = ["disabled"]; /* harmony default export */ __webpack_exports__.A = ({ __name: 'ChatPanel', setup(__props) { const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_22__/* .useConversationStore */ .w)(); const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_23__/* .useContactStore */ .p)(); const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_24__/* .useSessionStore */ .B)(); const activeConversation = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => conversations.activeConversation); const pinnedMessageIsImage = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { const message = conversations.activePinnedMessage; return message?.attachment?.url && (message.type === 'image' || message.attachment.type === 'image'); }); const pinnedMessageText = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { const message = conversations.activePinnedMessage; if (!message) return ''; const text = String(message.text || '').trim(); if (text && text !== '[消息]') return text; const attachment = message.attachment || {}; if (message.type === 'image' || attachment.type === 'image') return attachment.name || '图片'; if (message.type === 'video' || attachment.type === 'video') return attachment.name || '视频'; if (attachment.url) return attachment.name || '文件'; return '[消息]'; }); const groupMenuOpen = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(false); const singleProfileOpen = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(false); const singleAliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const singleProfileSaving = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(false); const singleProfileNotice = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const singleProfileError = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const groupPanel = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const groupBusy = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(false); const groupDetail = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(null); const groupMembers = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)([]); const groupAliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const manageSection = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const selectedAdminIds = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)([]); const selectedKickIds = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)([]); const transferTargetId = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const profileDraft = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)({ name: '', announcement: '', welcomeText: '' }); const muteDraft = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)({ mode: 'off', scheduleType: 'once', startsAtLocal: '', endsAtLocal: '', dailyStart: '09:00', dailyEnd: '18:00' }); const muteSaveNotice = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); const muteSaveError = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .ref */ .KR)(''); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_25__/* .useAutoDismiss */ .R)(() => singleProfileError.value || singleProfileNotice.value, value => { if ((singleProfileError.value || singleProfileNotice.value) === value) { singleProfileError.value = ''; singleProfileNotice.value = ''; } }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_25__/* .useAutoDismiss */ .R)(() => muteSaveError.value || muteSaveNotice.value, value => { if ((muteSaveError.value || muteSaveNotice.value) === value) { muteSaveError.value = ''; muteSaveNotice.value = ''; } }); const singlePeerId = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { if (!activeConversation.value || isGroupConversation.value) { return ''; } return String(activeConversation.value.target || activeConversation.value.raw?.target || activeConversation.value.id?.replace(/^single-/, '') || ''); }); const singleContact = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { const peerId = singlePeerId.value; if (!peerId) { return null; } return contacts.contacts.find(contact => String(contact.uid || contact.id || '') === peerId) || null; }); const singleProfile = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { const contact = singleContact.value; const conversation = activeConversation.value || {}; const rawUser = contact?.rawUser || {}; const displayName = contact?.alias || rawUser.displayName || rawUser.name || contact?.title || conversation.title || singlePeerId.value || '未知用户'; const rawName = rawUser.displayName || rawUser.name || contact?.title || conversation.title || ''; return { uid: singlePeerId.value, userId: rawUser.name || conversation.raw?.userId || singlePeerId.value, displayName, rawName, mobile: rawUser.mobile || conversation.raw?.mobile || '', address: rawUser.address || conversation.raw?.address || '', portrait: contact?.portrait || conversation.portrait || '', avatarText: String(displayName || '?').slice(0, 1).toUpperCase(), alias: contact?.alias || '' }; }); const groupDisplayId = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return String(groupDetail.value?.publicId || ''); }); const isGroupConversation = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return ['group', 'channel'].includes(activeConversation.value?.type) || activeConversation.value?.raw?.type === 'group'; }); const currentGroupRole = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return groupDetail.value?.myRole || activeConversation.value?.role || activeConversation.value?.raw?.role || ''; }); const isGroupOwner = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => currentGroupRole.value === 'owner'); const canManageGroup = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => ['owner', 'admin'].includes(currentGroupRole.value)); const adminCandidateMembers = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => groupMembers.value.filter(member => member.role !== 'owner')); const transferableMembers = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => groupMembers.value.filter(member => member.role !== 'owner')); const mentionCandidates = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { const members = new Map(); groupMembers.value.forEach(member => { const uid = String(member?.uid || '').trim(); if (uid && uid !== String(session.userId || '')) members.set(uid, member); }); conversations.activeMessages.forEach(message => { const uid = String(message?.from || '').trim(); if (!uid || uid === 'me' || uid === session.userId || members.has(uid)) return; members.set(uid, { uid, displayName: message?.senderName || uid, portrait: message?.senderPortrait || message?.portrait || '', role: message?.senderRole || 'member' }); }); return Array.from(members.values()); }); const messageDetail = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => conversations.messageDetail || null); const messageDetailGroup = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => messageDetail.value?.group || null); const isMessageDetailGroup = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return messageDetail.value?.conversationType === 'group' || Boolean(messageDetail.value?.group); }); const messageDetailCounts = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return messageDetailGroup.value?.counts || { read: 0, unread: 0, undelivered: 0, total: 0 }; }); const kickCandidateMembers = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { return groupMembers.value.filter(member => { if (member.uid === session.userId || member.role === 'owner') { return false; } if (currentGroupRole.value === 'admin') { return member.role === 'member'; } return currentGroupRole.value === 'owner'; }); }); const statusText = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .computed */ .EW)(() => { if (activeConversation.value?.type === 'channel' && !conversations.canSendActiveConversation) { return '公告群,仅管理员可发言'; } return session.connectionStatusText || (session.connected ? '已连接' : '未连接'); }); function formatDetailTime(value) { const timestamp = Number(value || 0); if (!timestamp) { return '暂无'; } return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone }).format(timestamp); } function detailMemberName(member) { return member?.name || member?.displayName || member?.rawName || member?.uid || '-'; } function detailMemberAvatar(member) { return String(detailMemberName(member) || '?').slice(0, 1).toUpperCase(); } function detailRoleLabel(role) { if (role === 'owner') { return '群主'; } if (role === 'admin') { return '管理员'; } return ''; } function closeGroupMenu() { groupMenuOpen.value = false; } function toggleGroupMenu() { if (!isGroupConversation.value) { return; } groupMenuOpen.value = !groupMenuOpen.value; } async function openSingleProfile() { if (!activeConversation.value || isGroupConversation.value) { return; } closeGroupMenu(); singleProfileNotice.value = ''; singleProfileError.value = ''; singleAliasDraft.value = singleProfile.value.alias || ''; singleProfileOpen.value = true; contacts.refreshContacts().then(() => { if (singleProfileOpen.value) { singleAliasDraft.value = singleProfile.value.alias || ''; } }).catch(() => {}); } function closeSingleProfile() { if (singleProfileSaving.value) { return; } singleProfileOpen.value = false; singleProfileNotice.value = ''; singleProfileError.value = ''; } async function saveSingleAlias() { const peerId = singleProfile.value.uid; if (!peerId || singleProfileSaving.value) { return; } singleProfileSaving.value = true; singleProfileNotice.value = ''; singleProfileError.value = ''; try { const ok = await contacts.updateContactAlias(peerId, singleAliasDraft.value); if (!ok) { singleProfileError.value = contacts.actionError || '备注名修改失败'; return; } await contacts.refreshContacts({ force: true }).catch(() => {}); const refreshedContact = contacts.contacts.find(contact => String(contact.uid || contact.id || '') === peerId) || singleContact.value; const nextTitle = refreshedContact?.title || singleAliasDraft.value || singleProfile.value.rawName || singleProfile.value.displayName || peerId; conversations.upsertConversation({ ...activeConversation.value, title: nextTitle, portrait: refreshedContact?.portrait || activeConversation.value?.portrait || '', avatarText: String(nextTitle || '?').slice(0, 1).toUpperCase(), raw: { ...(activeConversation.value?.raw || {}), target: peerId, mobile: refreshedContact?.rawUser?.mobile || activeConversation.value?.raw?.mobile || '', address: refreshedContact?.rawUser?.address || activeConversation.value?.raw?.address || '', alias: refreshedContact?.alias || singleAliasDraft.value } }); singleAliasDraft.value = refreshedContact?.alias || singleAliasDraft.value; singleProfileNotice.value = '备注名已保存'; } catch (error) { singleProfileError.value = error.message || '备注名修改失败'; } finally { singleProfileSaving.value = false; } } function handleSenderProfileUpdated() { contacts.refreshContacts({ force: true }).catch(() => {}); conversations.syncActiveMessages({ allowReadReceipt: true }); if (groupPanel.value === 'members') { loadGroupMembers(); } } function closeGroupPanel() { groupPanel.value = ''; groupBusy.value = false; clearMuteSaveFeedback(); } async function loadGroupDetail() { if (!session.userId || !activeConversation.value?.target) { return null; } const requestedConversationId = activeConversation.value.id; const requestedTarget = activeConversation.value.target; groupBusy.value = true; try { const detail = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.getGroupDetail(session.userId, requestedTarget); if (activeConversation.value?.id !== requestedConversationId) return null; groupDetail.value = detail; return groupDetail.value; } catch (error) { if (activeConversation.value?.id === requestedConversationId) { conversations.setActionError(error.message || '群资料加载失败'); } return null; } finally { if (activeConversation.value?.id === requestedConversationId) groupBusy.value = false; } } async function openGroupOverview() { if (!isGroupConversation.value) { return; } closeGroupMenu(); groupPanel.value = 'overview'; await loadGroupDetail(); } async function openGroupMembers() { closeGroupMenu(); groupPanel.value = 'members'; await loadGroupMembers(); } async function loadGroupMembers({ silent = false } = {}) { const requestedConversationId = activeConversation.value?.id; const requestedTarget = activeConversation.value?.target; if (!session.userId || !requestedConversationId || !requestedTarget) return []; groupBusy.value = true; try { const members = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.getGroupMembers(session.userId, requestedTarget); if (activeConversation.value?.id !== requestedConversationId) return []; groupMembers.value = members; selectedAdminIds.value = groupMembers.value.filter(member => member.role === 'admin').map(member => member.uid); return groupMembers.value; } catch (error) { if (!silent && activeConversation.value?.id === requestedConversationId) { conversations.setActionError(error.message || '群员加载失败'); } return []; } finally { if (activeConversation.value?.id === requestedConversationId) groupBusy.value = false; } } async function openGroupAlias() { closeGroupMenu(); groupPanel.value = 'alias'; const detail = await loadGroupDetail(); groupAliasDraft.value = detail?.myAlias || ''; } function msToLocalInput(value) { const timestamp = Number(value || 0); if (!timestamp) { return ''; } const date = new Date(timestamp); const local = new Date(date.getTime() - date.getTimezoneOffset() * 60000); return local.toISOString().slice(0, 16); } function localInputToMs(value) { return value ? new Date(value).getTime() : 0; } function prepareManagementDrafts() { clearMuteSaveFeedback(); profileDraft.value = { name: groupDetail.value?.name || activeConversation.value?.title || '', announcement: groupDetail.value?.announcement || '', welcomeText: groupDetail.value?.welcomeText || '' }; const setting = groupDetail.value?.muteSetting || {}; muteDraft.value = { mode: setting.mode || 'off', scheduleType: setting.scheduleType || 'once', startsAtLocal: msToLocalInput(setting.startsAtMs), endsAtLocal: msToLocalInput(setting.endsAtMs), dailyStart: setting.dailyStart || '09:00', dailyEnd: setting.dailyEnd || '18:00' }; } function clearMuteSaveFeedback() { muteSaveNotice.value = ''; muteSaveError.value = ''; } async function openGroupManage() { if (!canManageGroup.value) { return; } closeGroupMenu(); groupPanel.value = 'manage'; manageSection.value = isGroupOwner.value ? 'admins' : 'profile'; await loadGroupDetail(); prepareManagementDrafts(); await loadGroupMembers(); } async function openTransferGroup() { groupPanel.value = 'transfer'; transferTargetId.value = ''; await loadGroupMembers(); } async function saveGroupAlias() { if (!activeConversation.value?.target || groupBusy.value) { return; } groupBusy.value = true; try { const alias = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.updateGroupAlias(session.userId, activeConversation.value.target, groupAliasDraft.value); groupDetail.value = { ...(groupDetail.value || {}), myAlias: alias }; conversations.setActionNotice('本群昵称已保存'); closeGroupPanel(); } catch (error) { conversations.setActionError(error.message || '本群昵称保存失败'); } finally { groupBusy.value = false; } } function toggleAdmin(userId) { const selected = new Set(selectedAdminIds.value); if (selected.has(userId)) { selected.delete(userId); } else { selected.add(userId); } selectedAdminIds.value = Array.from(selected); } function toggleKick(userId) { const selected = new Set(selectedKickIds.value); if (selected.has(userId)) { selected.delete(userId); } else { selected.add(userId); } selectedKickIds.value = Array.from(selected); } async function saveGroupAdmins() { if (!activeConversation.value?.target || groupBusy.value) { return; } groupBusy.value = true; try { await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.setGroupAdmins(session.userId, activeConversation.value.target, selectedAdminIds.value); groupMembers.value = groupMembers.value.map(member => { if (member.role === 'owner') { return member; } return { ...member, role: selectedAdminIds.value.includes(member.uid) ? 'admin' : 'member' }; }); conversations.setActionNotice('管理员已更新'); } catch (error) { conversations.setActionError(error.message || '管理员设置失败'); } finally { groupBusy.value = false; } } async function saveGroupProfile() { if (!activeConversation.value?.target || groupBusy.value) { return; } groupBusy.value = true; try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.updateGroupProfile(session.userId, activeConversation.value.target, profileDraft.value); groupDetail.value = { ...(groupDetail.value || {}), name: result.name, announcement: result.announcement, welcomeText: result.welcomeText }; conversations.upsertConversation({ ...activeConversation.value, title: result.name, avatarText: String(result.name || '?').slice(0, 1).toUpperCase(), updatedAt: Number(result.updatedAt || Date.now()) }); conversations.setActionNotice('群资料已保存'); } catch (error) { conversations.setActionError(error.message || '群资料保存失败'); } finally { groupBusy.value = false; } } async function kickSelectedMembers() { if (!selectedKickIds.value.length || groupBusy.value) { return; } if (!window.confirm('确认将所选成员移出群组?')) { return; } groupBusy.value = true; try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.kickGroupMembers(session.userId, activeConversation.value.target, selectedKickIds.value); const removed = new Set(result.removedIds || selectedKickIds.value); groupMembers.value = groupMembers.value.filter(member => !removed.has(member.uid)); selectedKickIds.value = []; conversations.setActionNotice('已移出群组'); } catch (error) { conversations.setActionError(error.message || '踢人失败'); } finally { groupBusy.value = false; } } async function saveMuteSetting() { if (!activeConversation.value?.target || groupBusy.value) { return; } clearMuteSaveFeedback(); groupBusy.value = true; try { const setting = await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.updateGroupMuteSetting(session.userId, activeConversation.value.target, { mode: muteDraft.value.mode, scheduleType: muteDraft.value.scheduleType, startsAtMs: localInputToMs(muteDraft.value.startsAtLocal), endsAtMs: localInputToMs(muteDraft.value.endsAtLocal), dailyStart: muteDraft.value.dailyStart, dailyEnd: muteDraft.value.dailyEnd }); groupDetail.value = { ...(groupDetail.value || {}), muteSetting: setting }; muteSaveNotice.value = '禁言设置已保存'; } catch (error) { muteSaveError.value = error.message || '禁言设置保存失败'; } finally { groupBusy.value = false; } } async function leaveCurrentGroup() { if (!activeConversation.value || groupBusy.value) { return; } if (!window.confirm('确认退出该群组?')) { return; } groupBusy.value = true; const ok = await conversations.leaveGroup(activeConversation.value); groupBusy.value = false; if (ok) { closeGroupPanel(); } } async function dismissCurrentGroup() { if (!activeConversation.value || groupBusy.value) { return; } if (!window.confirm('确认解散该群组?所有成员都将不可继续使用该群。')) { return; } groupBusy.value = true; const ok = await conversations.dismissGroup(activeConversation.value); groupBusy.value = false; if (ok) { closeGroupPanel(); } } async function transferCurrentGroup() { if (!activeConversation.value?.target || !transferTargetId.value || groupBusy.value) { return; } if (!window.confirm('确认将群主转让给该成员?')) { return; } groupBusy.value = true; try { await _services_imClient__WEBPACK_IMPORTED_MODULE_21__/* .imClient */ .wD.transferGroup(session.userId, activeConversation.value.target, transferTargetId.value); groupDetail.value = { ...(groupDetail.value || {}), myRole: 'member' }; activeConversation.value.role = 'member'; if (activeConversation.value.raw) { activeConversation.value.raw.role = 'member'; } conversations.setActionNotice('群组已转让'); closeGroupPanel(); conversations.refreshRemoteConversations(); } catch (error) { conversations.setActionError(error.message || '转让群组失败'); } finally { groupBusy.value = false; } } function memberAvatar(member) { return String(member.displayName || member.uid || '?').slice(0, 1).toUpperCase(); } document.addEventListener('click', closeGroupMenu); (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .onBeforeUnmount */ .xo)(() => { document.removeEventListener('click', closeGroupMenu); }); (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .watch */ .wB)(() => activeConversation.value?.id, async () => { conversations.actionError = ''; conversations.actionNotice = ''; closeGroupMenu(); closeSingleProfile(); closeGroupPanel(); groupDetail.value = null; groupMembers.value = []; groupAliasDraft.value = ''; selectedAdminIds.value = []; selectedKickIds.value = []; transferTargetId.value = ''; manageSection.value = ''; if (isGroupConversation.value) { await loadGroupMembers({ silent: true }); } }, { immediate: true }); return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", { class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)(["chat-panel", { 'has-pinned-message': Boolean((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activePinnedMessage) }]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [isGroupConversation.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 0, type: "button", class: "chat-title-button", onClick: openGroupOverview }, [activeConversation.value?.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "chat-title-avatar image-avatar", src: activeConversation.value.portrait, alt: "", onError: _cache[0] || (_cache[0] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, activeConversation.value.portrait)) }, null, 40, _hoisted_2)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(activeConversation.value?.avatarText || '?'), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h2", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(activeConversation.value?.title || '未选择会话'), 1)])])) : activeConversation.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 1, type: "button", class: "chat-title-button", onClick: openSingleProfile }, [singleProfile.value.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "chat-title-avatar image-avatar", src: singleProfile.value.portrait, alt: "", onError: _cache[1] || (_cache[1] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, singleProfile.value.portrait)) }, null, 40, _hoisted_5)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_6, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h2", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(activeConversation.value?.title || '未选择会话'), 1)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("h2", _hoisted_8, "未选择会话")), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(statusText.value), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_9, [_cache[34] || (_cache[34] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { class: "icon-button", title: "搜索" }, "⌕", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { class: "icon-button", title: "更多", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)(toggleGroupMenu, ["stop"]) }, "⋯"), groupMenuOpen.value && isGroupConversation.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 0, class: "quick-action-menu chat-more-menu", onClick: _cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: openGroupMembers }, "查看群员"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: openGroupAlias }, "我在本群的昵称"), canManageGroup.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 0, type: "button", onClick: openGroupManage }, "群组管理")) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)])]), !activeConversation.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_10, _cache[35] || (_cache[35] = [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, "选择一个会话", -1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "真实会话同步完成后,可以在左侧打开聊天", -1)]))) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), activeConversation.value && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activePinnedMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 1, type: "button", class: "pinned-message-banner", title: "点击定位该消息", onClick: _cache[4] || (_cache[4] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).focusMessage((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activePinnedMessage)) }, [_cache[36] || (_cache[36] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "📌", -1)), _cache[37] || (_cache[37] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, "置顶消息", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_11, [pinnedMessageIsImage.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, src: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activePinnedMessage.attachment.url, alt: "置顶图片" }, null, 8, _hoisted_12)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(pinnedMessageText.value), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", { class: "pinned-message-close", title: "取消置顶", onClick: _cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)((...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).clearPinnedMessage && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).clearPinnedMessage(...args), ["stop"])) }, "×")])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), activeConversation.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createBlock */ .Wv)(_MessageList_vue__WEBPACK_IMPORTED_MODULE_19__/* ["default"] */ .A, { key: 2, messages: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activeMessages, "selection-mode": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).selectionMode, "selected-message-ids": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).selectedMessageIds, "favorite-message-ids": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).favoriteMessageIds, "pinned-message-id": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).activePinnedMessage?.key || '', "attention-message-id": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).attentionMessageId, "can-recall-others": canManageGroup.value && isGroupConversation.value, onMessageAction: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).handleMessageAction, onToggleSelect: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).toggleSelectedMessage, onSenderProfileUpdated: handleSenderProfileUpdated }, null, 8, ["messages", "selection-mode", "selected-message-ids", "favorite-message-ids", "pinned-message-id", "attention-message-id", "can-recall-others", "onMessageAction", "onToggleSelect"])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).selectionMode ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "已选 " + (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).selectedMessageIds.length) + " 条", 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[5] || (_cache[5] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).copySelectedMessages && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).copySelectedMessages(...args)) }, "复制"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[6] || (_cache[6] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).deleteSelectedMessages && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).deleteSelectedMessages(...args)) }, "删除"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[7] || (_cache[7] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).startForwardSelectedMessages && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).startForwardSelectedMessages(...args)) }, "转发"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[8] || (_cache[8] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).clearSelection && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).clearSelection(...args)) }, "取消")])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createVNode */ .bF)(_MessageComposer_vue__WEBPACK_IMPORTED_MODULE_20__/* ["default"] */ .A, { disabled: !activeConversation.value || !(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(session).isAuthenticated || !(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).canSendActiveConversation, "quote-message": (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).quotedMessage, "mention-users": isGroupConversation.value ? mentionCandidates.value : [], onCancelQuote: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelQuote, onSend: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).sendText, onSendAttachment: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).sendAttachment }, null, 8, ["disabled", "quote-message", "mention-users", "onCancelQuote", "onSend", "onSendAttachment"]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).forwardingMessages.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 4, class: "modal-backdrop", onClick: _cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)((...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelForward && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelForward(...args), ["self"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[38] || (_cache[38] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "转发给", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: _cache[9] || (_cache[9] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelForward && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelForward(...args)) }, "×")]), ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).conversations, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: item.id, type: "button", class: "forward-target", onClick: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).completeForward(item.id) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(item.avatarText), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(item.title), 1)], 8, _hoisted_15); }), 128))])])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).editingMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 5, class: "modal-backdrop", onClick: _cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)((...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage(...args), ["self"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("form", { class: "edit-dialog", onSubmit: _cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)((...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).completeEditMessage && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).completeEditMessage(...args), ["prevent"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).editingMode === 'resend' ? '重新编辑' : '编辑消息'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: _cache[11] || (_cache[11] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage(...args)) }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[12] || (_cache[12] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).editingText = $event), maxlength: "5000", rows: "5", autofocus: "" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).editingText]]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[13] || (_cache[13] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).cancelEditMessage(...args)) }, "取消"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", _hoisted_17, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).editingMode === 'resend' ? '发送' : '保存'), 1)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).messageDetailOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 6, class: "modal-backdrop", onClick: _cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)((...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).closeMessageDetail && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).closeMessageDetail(...args), ["self"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_18, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[39] || (_cache[39] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "消息详情", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: _cache[16] || (_cache[16] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).closeMessageDetail && (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).closeMessageDetail(...args)) }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).messageDetailLoading ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_19, "正在加载")) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, { key: 1 }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dl", _hoisted_20, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[40] || (_cache[40] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "发送时间", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(formatDetailTime(messageDetail.value?.sentAt)), 1)]), messageDetail.value?.editedAt ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_21, [_cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "编辑时间", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(formatDetailTime(messageDetail.value.editedAt)), 1)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[42] || (_cache[42] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "发送人", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberName(messageDetail.value?.sender)), 1)]), !isMessageDetailGroup.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, { key: 1 }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[43] || (_cache[43] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "接收人", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberName(messageDetail.value?.receiver)), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[44] || (_cache[44] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "送达时间", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", { class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ 'message-detail-muted': !messageDetail.value?.deliveredAt }) }, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetail.value?.deliveredAt ? formatDetailTime(messageDetail.value.deliveredAt) : '未送达'), 3)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[45] || (_cache[45] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "已读时间", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", { class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ 'message-detail-muted': !messageDetail.value?.readAt }) }, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetail.value?.readAt ? formatDetailTime(messageDetail.value.readAt) : '未读'), 3)])], 64)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).messageDetailError ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_22, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).messageDetailError), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), isMessageDetailGroup.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, { key: 1 }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_23, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [_cache[46] || (_cache[46] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createTextVNode */ .eW)("已读 ")), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.read || 0), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [_cache[47] || (_cache[47] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createTextVNode */ .eW)("未读 ")), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.unread || 0), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [_cache[48] || (_cache[48] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createTextVNode */ .eW)("未送达 ")), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.undelivered || 0), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [_cache[49] || (_cache[49] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createTextVNode */ .eW)("成员 ")), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.total || 0), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_24, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_25, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[50] || (_cache[50] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, "已读", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.read || 0) + " 人", 1)]), messageDetailGroup.value?.read?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_26, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(messageDetailGroup.value.read, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: `read-${member.uid}`, class: "message-detail-member-row" }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_27)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_28, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_29, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberName(member)), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.uid), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_30, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(formatDetailTime(member.time)), 1), detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_31, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailRoleLabel(member.role)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]); }), 128))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_32, "暂无已读成员"))]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_33, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[51] || (_cache[51] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, "未读", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.unread || 0) + " 人", 1)]), messageDetailGroup.value?.unread?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_34, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(messageDetailGroup.value.unread, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: `unread-${member.uid}`, class: "message-detail-member-row" }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_35)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_36, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_37, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberName(member)), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.uid), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_38, "送达 " + (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(formatDetailTime(member.time)), 1), detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_39, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailRoleLabel(member.role)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]); }), 128))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_40, "暂无未读成员"))]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_41, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[52] || (_cache[52] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, "未送达", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(messageDetailCounts.value.undelivered || 0) + " 人", 1)]), messageDetailGroup.value?.undelivered?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_42, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(messageDetailGroup.value.undelivered, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: `undelivered-${member.uid}`, class: "message-detail-member-row" }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_43)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_44, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", _hoisted_45, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailMemberName(member)), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.uid), 1)]), _cache[53] || (_cache[53] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", { class: "message-detail-member-time message-detail-muted" }, "未送达", -1)), detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_46, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(detailRoleLabel(member.role)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]); }), 128))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_47, "暂无未送达成员"))])])], 64)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)], 64))])])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), singleProfileOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 7, class: "modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)(closeSingleProfile, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("section", _hoisted_48, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[54] || (_cache[54] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "联系人资料", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeSingleProfile }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_49, [singleProfile.value.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "profile-avatar image-avatar", src: singleProfile.value.portrait, alt: "", onError: _cache[18] || (_cache[18] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, singleProfile.value.portrait)) }, null, 40, _hoisted_50)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_51, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.displayName), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dl", _hoisted_52, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[55] || (_cache[55] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "用户ID", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.userId || '-'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[56] || (_cache[56] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.rawName || '-'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[57] || (_cache[57] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "手机号", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.mobile || '未知'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[58] || (_cache[58] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "地区", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfile.value.address || '未知'), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[59] || (_cache[59] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "备注名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[19] || (_cache[19] = $event => singleAliasDraft.value = $event), maxlength: "32", autocomplete: "off", placeholder: "留空使用对方昵称" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, singleAliasDraft.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", _hoisted_53, [singleProfileNotice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_54, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfileNotice.value), 1)) : singleProfileError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_55, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfileError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", disabled: singleProfileSaving.value, onClick: closeSingleProfile }, "取消", 8, _hoisted_56), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: singleProfileSaving.value || !singleProfile.value.uid, onClick: saveSingleAlias }, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(singleProfileSaving.value ? '保存中...' : '保存备注'), 9, _hoisted_57)])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), groupPanel.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 8, class: "modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)(closeGroupPanel, ["self"]) }, [groupPanel.value === 'overview' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_58, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[60] || (_cache[60] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "群概况", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeGroupPanel }, "×")]), groupBusy.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_59, "正在加载")) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("dl", _hoisted_60, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[61] || (_cache[61] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "群名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(groupDetail.value?.name || activeConversation.value?.title || '-'), 1)]), groupDisplayId.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_61, [_cache[62] || (_cache[62] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "群ID", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(groupDisplayId.value), 1)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[63] || (_cache[63] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "群说明", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(groupDetail.value?.announcement || '未设置'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", null, [_cache[64] || (_cache[64] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dt", null, "群主昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(groupDetail.value?.ownerName || '-'), 1)])])), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [isGroupOwner.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, { key: 0 }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "danger-inline-action", disabled: groupBusy.value, onClick: dismissCurrentGroup }, "解散群组", 8, _hoisted_62), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: groupBusy.value, onClick: openTransferGroup }, "转让群组", 8, _hoisted_63)], 64)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 1, type: "button", class: "danger-inline-action", disabled: groupBusy.value, onClick: leaveCurrentGroup }, "退出群组", 8, _hoisted_64))])])) : groupPanel.value === 'members' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_65, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[65] || (_cache[65] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "群员", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeGroupPanel }, "×")]), groupBusy.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_66, "正在加载")) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_67, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(groupMembers.value, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: member.uid, class: "group-member-row" }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_68)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_69, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(memberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.displayName), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.role === 'owner' ? '群主' : member.rawDisplayName), 1)])]); }), 128)), !groupMembers.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_70, "暂无群员")) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]))])) : groupPanel.value === 'alias' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("form", { key: 2, class: "group-dialog", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_15__/* .withModifiers */ .D$)(saveGroupAlias, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[66] || (_cache[66] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "我在本群的昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeGroupPanel }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[67] || (_cache[67] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[20] || (_cache[20] = $event => groupAliasDraft.value = $event), maxlength: "64", autocomplete: "off", placeholder: "留空使用个人昵称" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, groupAliasDraft.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: closeGroupPanel }, "取消"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { class: "primary-inline-action", disabled: groupBusy.value }, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(groupBusy.value ? '保存中...' : '保存'), 9, _hoisted_71)])], 32)) : groupPanel.value === 'transfer' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_72, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[68] || (_cache[68] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "转让群组", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeGroupPanel }, "×")]), groupBusy.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_73, "正在加载")) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_74, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(transferableMembers.value, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: member.uid, type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)(["group-member-row selectable", { selected: transferTargetId.value === member.uid }]), onClick: $event => transferTargetId.value = member.uid }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_76)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_77, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(memberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.displayName), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.rawDisplayName), 1)])], 10, _hoisted_75); }), 128)), !transferableMembers.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_78, "暂无可转让成员")) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)])), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: closeGroupPanel }, "取消"), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: groupBusy.value || !transferTargetId.value, onClick: transferCurrentGroup }, "确认转让", 8, _hoisted_79)])])) : groupPanel.value === 'manage' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_80, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("header", null, [_cache[69] || (_cache[69] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("h3", null, "群组管理", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeGroupPanel }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("nav", _hoisted_81, [isGroupOwner.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("button", { key: 0, type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ active: manageSection.value === 'admins' }), onClick: _cache[21] || (_cache[21] = $event => manageSection.value = 'admins') }, "管理员设置", 2)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ active: manageSection.value === 'profile' }), onClick: _cache[22] || (_cache[22] = $event => manageSection.value = 'profile') }, "修改群资料", 2), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ active: manageSection.value === 'kick' }), onClick: _cache[23] || (_cache[23] = $event => manageSection.value = 'kick') }, "踢人", 2), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)({ active: manageSection.value === 'mute' }), onClick: _cache[24] || (_cache[24] = $event => manageSection.value = 'mute') }, "禁言设置", 2)]), groupBusy.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_82, "正在加载")) : manageSection.value === 'admins' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_83, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_84, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(adminCandidateMembers.value, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("label", { key: member.uid, class: "group-member-row selectable with-check" }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { type: "checkbox", checked: selectedAdminIds.value.includes(member.uid), onChange: $event => toggleAdmin(member.uid) }, null, 40, _hoisted_85), member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_86)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_87, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(memberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.displayName), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.rawDisplayName), 1)])]); }), 128)), !adminCandidateMembers.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_88, "暂无可设置成员")) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", onClick: saveGroupAdmins }, "保存管理员")])])) : manageSection.value === 'profile' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_89, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[70] || (_cache[70] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "群名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[25] || (_cache[25] = $event => profileDraft.value.name = $event), maxlength: "128", autocomplete: "off" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, profileDraft.value.name, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[71] || (_cache[71] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "群说明", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[26] || (_cache[26] = $event => profileDraft.value.announcement = $event), maxlength: "1000", rows: "3" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, profileDraft.value.announcement, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[72] || (_cache[72] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "欢迎词", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[27] || (_cache[27] = $event => profileDraft.value.welcomeText = $event), maxlength: "1000", rows: "3" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, profileDraft.value.welcomeText, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", onClick: saveGroupProfile }, "保存资料")])])) : manageSection.value === 'kick' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_90, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("div", _hoisted_91, [((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_16__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .renderList */ .pI)(kickCandidateMembers.value, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("label", { key: member.uid, class: "group-member-row selectable with-check" }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { type: "checkbox", checked: selectedKickIds.value.includes(member.uid), onChange: $event => toggleKick(member.uid) }, null, 40, _hoisted_92), member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: member.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_26__/* .useImageProxyFallback */ .TJ)($event, member.portrait) }, null, 40, _hoisted_93)) : ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_94, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(memberAvatar(member)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.displayName), 1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(member.role === 'admin' ? '管理员' : member.rawDisplayName), 1)])]); }), 128)), !kickCandidateMembers.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_95, "暂无可移除成员")) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", null, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "danger-inline-action", disabled: !selectedKickIds.value.length, onClick: kickSelectedMembers }, "移出群组", 8, _hoisted_96)])])) : manageSection.value === 'mute' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("section", _hoisted_97, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[74] || (_cache[74] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "禁言模式", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("select", { "onUpdate:modelValue": _cache[28] || (_cache[28] = $event => muteDraft.value.mode = $event), onChange: clearMuteSaveFeedback }, _cache[73] || (_cache[73] = [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "off" }, "关闭禁言", -1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "all_include_admins" }, "全体禁言包含管理员", -1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "all_except_admins" }, "除管理员外全体禁言", -1)]), 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelSelect */ .u1, muteDraft.value.mode]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[76] || (_cache[76] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "时段类型", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("select", { "onUpdate:modelValue": _cache[29] || (_cache[29] = $event => muteDraft.value.scheduleType = $event), onChange: clearMuteSaveFeedback }, _cache[75] || (_cache[75] = [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "manual" }, "立即禁言直到管理解除", -1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "once" }, "单次", -1), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("option", { value: "daily" }, "每天固定时段", -1)]), 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelSelect */ .u1, muteDraft.value.scheduleType]])]), muteDraft.value.mode !== 'off' && muteDraft.value.scheduleType === 'once' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_98, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[77] || (_cache[77] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "开始", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[30] || (_cache[30] = $event => muteDraft.value.startsAtLocal = $event), type: "datetime-local", onInput: clearMuteSaveFeedback }, null, 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, muteDraft.value.startsAtLocal]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[78] || (_cache[78] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "结束", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[31] || (_cache[31] = $event => muteDraft.value.endsAtLocal = $event), type: "datetime-local", onInput: clearMuteSaveFeedback }, null, 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, muteDraft.value.endsAtLocal]])])])) : muteDraft.value.mode !== 'off' && muteDraft.value.scheduleType === 'daily' ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", _hoisted_99, [(0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[79] || (_cache[79] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "开始", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[32] || (_cache[32] = $event => muteDraft.value.dailyStart = $event), type: "time", onInput: clearMuteSaveFeedback }, null, 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, muteDraft.value.dailyStart]])]), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("label", null, [_cache[80] || (_cache[80] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("span", null, "结束", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[33] || (_cache[33] = $event => muteDraft.value.dailyEnd = $event), type: "time", onInput: clearMuteSaveFeedback }, null, 544), [[vue__WEBPACK_IMPORTED_MODULE_15__/* .vModelText */ .Jo, muteDraft.value.dailyEnd]])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("footer", _hoisted_100, [muteSaveNotice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_101, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(muteSaveNotice.value), 1)) : muteSaveError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("span", _hoisted_102, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)(muteSaveError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: groupBusy.value, onClick: saveMuteSetting }, "保存禁言", 8, _hoisted_103)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).actionNotice || (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).actionError ? ((0,vue__WEBPACK_IMPORTED_MODULE_16__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createElementBlock */ .CE)("div", { key: 9, class: (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .normalizeClass */ .C4)(["chat-toast", { error: (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).actionError }]) }, (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).actionError || (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .unref */ .R1)(conversations).actionNotice), 3)) : (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .createCommentVNode */ .Q3)("", true)], 2); }; } }); /***/ }), /***/ 6935: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4114); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(5187); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(144); const _hoisted_1 = { key: 0, class: "quote-preview" }; const _hoisted_2 = { class: "composer-tools" }; const _hoisted_3 = ["disabled"]; const _hoisted_4 = ["disabled"]; const _hoisted_5 = ["disabled"]; const _hoisted_6 = ["disabled"]; const _hoisted_7 = ["onClick"]; const _hoisted_8 = ["disabled", "onKeydown"]; const _hoisted_9 = { key: 1, class: "mention-picker" }; const _hoisted_10 = ["onClick"]; const _hoisted_11 = ["src"]; const _hoisted_12 = { key: 1 }; const _hoisted_13 = { class: "composer-footer" }; const _hoisted_14 = ["disabled"]; /* harmony default export */ __webpack_exports__.A = ({ __name: 'MessageComposer', props: { disabled: { type: Boolean, default: false }, quoteMessage: { type: Object, default: null }, mentionUsers: { type: Array, default: () => [] } }, emits: ['send', 'send-attachment', 'cancel-quote'], setup(__props, { emit: __emit }) { const props = __props; const emit = __emit; const text = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(''); const emojiOpen = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(false); const dropActive = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(false); const textareaEl = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(null); const imageInput = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(null); const fileInput = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(null); const mentionOpen = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(false); const mentionQuery = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(''); const mentionStart = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)(-1); const mentionedUserIds = (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .ref */ .KR)([]); let dragDepth = 0; const emojiList = ['😀', '😄', '😂', '😊', '😍', '😘', '😎', '😢', '😡', '👍', '🙏', '👏', '💪', '🎉', '❤️', '🔥', '🌹', '☕', '✅', '⭐', '💰', '🎁', '🤝', '👌']; const filteredMentionUsers = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .computed */ .EW)(() => { const query = mentionQuery.value.toLowerCase(); return props.mentionUsers.filter(member => member?.uid).filter(member => !query || mentionName(member).toLowerCase().includes(query)).slice(0, 12); }); function submit() { const value = text.value.trim(); if (!value) { return; } emit('send', { text: value, mentionedUserIds: [...mentionedUserIds.value] }); text.value = ''; mentionedUserIds.value = []; mentionOpen.value = false; emojiOpen.value = false; } function mentionName(member) { return String(member?.displayName || member?.name || member?.rawName || member?.uid || '群成员'); } function handleMentionInput(event) { const cursor = event?.target?.selectionStart ?? text.value.length; const beforeCursor = text.value.slice(0, cursor); const match = beforeCursor.match(/@([^\s@]*)$/); mentionOpen.value = Boolean(match && props.mentionUsers.length); mentionQuery.value = match?.[1] || ''; mentionStart.value = match ? cursor - match[1].length - 1 : -1; } function openMentionPicker() { if (!props.mentionUsers.length) return; const element = textareaEl.value; const start = element?.selectionStart ?? text.value.length; const end = element?.selectionEnd ?? start; text.value = `${text.value.slice(0, start)}@${text.value.slice(end)}`; mentionStart.value = start; mentionQuery.value = ''; mentionOpen.value = true; (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .nextTick */ .dY)(() => { element?.focus(); element?.setSelectionRange(start + 1, start + 1); }); } function selectMention(member) { const element = textareaEl.value; const cursor = element?.selectionStart ?? text.value.length; const start = mentionStart.value >= 0 ? mentionStart.value : cursor; const name = mentionName(member); text.value = `${text.value.slice(0, start)}@${name} ${text.value.slice(cursor)}`; if (!mentionedUserIds.value.includes(String(member.uid))) { mentionedUserIds.value.push(String(member.uid)); } mentionOpen.value = false; mentionQuery.value = ''; mentionStart.value = -1; (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .nextTick */ .dY)(() => { const nextCursor = start + name.length + 2; element?.focus(); element?.setSelectionRange(nextCursor, nextCursor); }); } function toggleEmojiPicker() { emojiOpen.value = !emojiOpen.value; } function insertEmoji(emoji) { const element = textareaEl.value; if (!element) { text.value += emoji; return; } const start = element.selectionStart ?? text.value.length; const end = element.selectionEnd ?? text.value.length; text.value = `${text.value.slice(0, start)}${emoji}${text.value.slice(end)}`; requestAnimationFrame(() => { element.focus(); const cursor = start + emoji.length; element.setSelectionRange(cursor, cursor); }); } function chooseImage() { imageInput.value?.click(); } function chooseFile() { fileInput.value?.click(); } function attachmentTypeForFile(file, fallbackType = 'file') { if (file?.type?.startsWith('image/')) { return 'image'; } return fallbackType === 'image' ? 'image' : 'file'; } function emitFiles(files, fallbackType = 'file') { if (props.disabled) { return; } const validFiles = Array.from(files || []).filter(file => file instanceof File && file.size > 0); if (!validFiles.length) { return; } const caption = text.value.trim(); validFiles.forEach((file, index) => { emit('send-attachment', { type: attachmentTypeForFile(file, fallbackType), file, text: index === 0 ? caption : '' }); }); text.value = ''; emojiOpen.value = false; } function selectAttachment(event, type) { const input = event.target; const files = input.files ? Array.from(input.files) : []; input.value = ''; if (!files.length || props.disabled) { return; } emitFiles(files, type); } function hasDraggedFiles(event) { const types = Array.from(event.dataTransfer?.types || []); return types.includes('Files'); } function handleDragEnter(event) { if (props.disabled || !hasDraggedFiles(event)) { return; } dragDepth += 1; dropActive.value = true; event.dataTransfer.dropEffect = 'copy'; } function handleDragOver(event) { if (props.disabled || !hasDraggedFiles(event)) { return; } dropActive.value = true; event.dataTransfer.dropEffect = 'copy'; } function handleDragLeave() { dragDepth = Math.max(0, dragDepth - 1); if (dragDepth === 0) { dropActive.value = false; } } function filesFromDataTransfer(dataTransfer) { const items = Array.from(dataTransfer?.items || []); const files = items.filter(item => item.kind === 'file' && !item.webkitGetAsEntry?.()?.isDirectory).map(item => item.getAsFile()).filter(Boolean); if (files.length) { return files; } return Array.from(dataTransfer?.files || []); } function handleDrop(event) { dragDepth = 0; dropActive.value = false; if (props.disabled) { return; } emitFiles(filesFromDataTransfer(event.dataTransfer)); } function imageFilesFromClipboard(clipboardData) { return Array.from(clipboardData?.items || []).filter(item => item.kind === 'file' && item.type.startsWith('image/')).map(item => item.getAsFile()).filter(Boolean); } function handlePaste(event) { if (props.disabled) { return; } const imageFiles = imageFilesFromClipboard(event.clipboardData); if (!imageFiles.length) { return; } event.preventDefault(); emitFiles(imageFiles, 'image'); } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("form", { class: (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .normalizeClass */ .C4)(["message-composer", { 'drop-active': dropActive.value }]), onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(submit, ["prevent"]), onDragenter: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(handleDragEnter, ["prevent"]), onDragover: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(handleDragOver, ["prevent"]), onDragleave: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(handleDragLeave, ["prevent"]), onDrop: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(handleDrop, ["prevent"]), onPaste: handlePaste }, [__props.quoteMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, "引用", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createTextVNode */ .eW)(" " + (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .toDisplayString */ .v_)(__props.quoteMessage.quoteText || __props.quoteMessage.text), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "取消引用", onClick: _cache[0] || (_cache[0] = $event => _ctx.$emit('cancel-quote')) }, "×")])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "表情", disabled: __props.disabled, onClick: toggleEmojiPicker }, "☺", 8, _hoisted_3), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "艾特群成员", disabled: __props.disabled || !__props.mentionUsers.length, onClick: openMentionPicker }, "@", 8, _hoisted_4), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "图片", disabled: __props.disabled, onClick: chooseImage }, "▧", 8, _hoisted_5), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "文件", disabled: __props.disabled, onClick: chooseFile }, "▤", 8, _hoisted_6), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("input", { ref_key: "imageInput", ref: imageInput, type: "file", accept: "image/*", multiple: "", onChange: _cache[1] || (_cache[1] = $event => selectAttachment($event, 'image')) }, null, 544), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("input", { ref_key: "fileInput", ref: fileInput, type: "file", multiple: "", onChange: _cache[2] || (_cache[2] = $event => selectAttachment($event, 'file')) }, null, 544), emojiOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", { key: 0, class: "emoji-picker", onClick: _cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .renderList */ .pI)(emojiList, emoji => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { key: emoji, type: "button", onClick: $event => insertEmoji(emoji) }, (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .toDisplayString */ .v_)(emoji), 9, _hoisted_7); }), 64))])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("textarea", { ref_key: "textareaEl", ref: textareaEl, "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => text.value = $event), disabled: __props.disabled, placeholder: "输入消息", rows: "3", onInput: handleMentionInput, onKeydown: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withKeys */ .jR)((0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(submit, ["exact", "prevent"]), ["enter"]) }, null, 40, _hoisted_8), [[vue__WEBPACK_IMPORTED_MODULE_6__/* .vModelText */ .Jo, text.value]]), mentionOpen.value && filteredMentionUsers.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_9, [((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .renderList */ .pI)(filteredMentionUsers.value, member => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: member.uid, type: "button", onClick: $event => selectMention(member) }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("img", { key: 0, src: member.portrait, alt: "" }, null, 8, _hoisted_11)) : ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .toDisplayString */ .v_)(mentionName(member).slice(0, 1)), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .toDisplayString */ .v_)(mentionName(member)), 1)], 8, _hoisted_10); }), 128))])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", _hoisted_13, [_cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, "Enter 发送,Shift + Enter 换行", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { class: "send-button", disabled: __props.disabled || !text.value.trim() }, "发送", 8, _hoisted_14)])], 34); }; } }); /***/ }), /***/ 4021: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4114); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5187); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(9045); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(446); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(6384); const _hoisted_1 = ["data-message-key", "onClick"]; const _hoisted_2 = { key: 0, class: "system-message-pill" }; const _hoisted_3 = { key: 1, class: "message-select" }; const _hoisted_4 = ["checked", "onChange"]; const _hoisted_5 = ["title", "onClick"]; const _hoisted_6 = ["src", "onError"]; const _hoisted_7 = { key: 1 }; const _hoisted_8 = { key: 3, class: "message-stack" }; const _hoisted_9 = ["onClick"]; const _hoisted_10 = { key: 0, class: "message-sender-role" }; const _hoisted_11 = ["onContextmenu"]; const _hoisted_12 = { key: 0, class: "red-packet-card" }; const _hoisted_13 = { class: "red-packet-card-main" }; const _hoisted_14 = { key: 1, class: "red-packet-receipt" }; const _hoisted_15 = ["onClick"]; const _hoisted_16 = ["src", "alt"]; const _hoisted_17 = ["src", "onError"]; const _hoisted_18 = ["href"]; const _hoisted_19 = { class: "message-file-main" }; const _hoisted_20 = { key: 5 }; const _hoisted_21 = { key: 0, class: "recall-mark" }; const _hoisted_22 = { key: 1, class: "edit-mark" }; const _hoisted_23 = { key: 2, class: "favorite-mark", title: "已收藏", "aria-label": "已收藏" }; const _hoisted_24 = ["title", "aria-label"]; const _hoisted_25 = { key: 0, class: "delivery-check delivery-check-second" }; const _hoisted_26 = { key: 4, class: "delivery-error" }; const _hoisted_27 = ["onClick"]; const _hoisted_28 = ["src", "alt"]; const _hoisted_29 = { class: "sender-profile-main" }; const _hoisted_30 = ["src"]; const _hoisted_31 = { key: 1, class: "profile-avatar" }; const _hoisted_32 = { key: 2 }; const _hoisted_33 = { class: "sender-profile-fields" }; const _hoisted_34 = { key: 0 }; const _hoisted_35 = { class: "sender-profile-alias" }; const _hoisted_36 = ["disabled"]; const _hoisted_37 = { class: "sender-profile-actions" }; const _hoisted_38 = { key: 0, class: "inline-save-status" }; const _hoisted_39 = { key: 1, class: "inline-save-status error" }; const _hoisted_40 = ["disabled"]; const _hoisted_41 = ["disabled"]; const IMAGE_MIN_SCALE = 0.5; const IMAGE_MAX_SCALE = 6; /* harmony default export */ __webpack_exports__.A = ({ __name: 'MessageList', props: { messages: { type: Array, default: () => [] }, selectionMode: { type: Boolean, default: false }, selectedMessageIds: { type: Array, default: () => [] }, favoriteMessageIds: { type: Array, default: () => [] }, pinnedMessageId: { type: String, default: '' }, attentionMessageId: { type: String, default: '' }, canRecallOthers: { type: Boolean, default: false } }, emits: ['message-action', 'toggle-select', 'sender-profile-updated'], setup(__props, { emit: __emit }) { const props = __props; const emit = __emit; const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_10__/* .useContactStore */ .p)(); const listEl = (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .ref */ .KR)(null); const viewerStage = (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .ref */ .KR)(null); const contextMenu = (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .reactive */ .Kh)({ visible: false, x: 0, y: 0, message: null }); const imageViewer = (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .reactive */ .Kh)({ visible: false, url: '', name: '', sourceUrl: '', index: 0, scale: 1, rotation: 0, offsetX: 0, offsetY: 0, dragging: false, dragStartX: 0, dragStartY: 0, dragOffsetX: 0, dragOffsetY: 0 }); const senderProfile = (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .reactive */ .Kh)({ visible: false, uid: '', userId: '', displayName: '', rawName: '', mobile: '', address: '', portrait: '', avatarText: '', role: '', roleLabel: '', contactAlias: '', groupAlias: '', isContact: false, aliasDraft: '', saving: false, adding: false, notice: '', error: '' }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_12__/* .useAutoDismiss */ .R)(() => senderProfile.error || senderProfile.notice, value => { if ((senderProfile.error || senderProfile.notice) === value) { senderProfile.error = ''; senderProfile.notice = ''; } }); const imageViewerStyle = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .computed */ .EW)(() => ({ transform: `translate3d(${imageViewer.offsetX}px, ${imageViewer.offsetY}px, 0) scale(${imageViewer.scale}) rotate(${imageViewer.rotation}deg)` })); const viewerImages = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .computed */ .EW)(() => props.messages.filter(message => isImageMessage(message))); const menuItems = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .computed */ .EW)(() => { if (!contextMenu.message) { return []; } const isOwnMessage = contextMenu.message.direction === 'out'; if (isRecalledMessage(contextMenu.message)) { return [...(isOwnMessage ? [{ action: 'edit', label: '编辑' }] : []), { action: 'copy', label: '复制' }, { action: 'delete', label: '删除' }, { action: 'detail', label: '详情' }]; } const favoriteLabel = isFavorite(contextMenu.message) ? '取消收藏' : '收藏'; const pinnedLabel = props.pinnedMessageId === messageIdentity(contextMenu.message) ? '取消置顶' : '置顶'; const items = [{ action: 'copy', label: '复制' }, { action: 'delete', label: '删除' }, { action: 'forward', label: '转发' }, { action: 'favorite', label: favoriteLabel }, { action: 'pin', label: pinnedLabel }, { action: 'quote', label: '引用' }, { action: 'select', label: '多选' }, { action: 'detail', label: '详情' }]; if (isOwnMessage) { items.unshift({ action: 'edit', label: '编辑' }); items.push({ action: 'recall', label: '撤回' }); } else if (props.canRecallOthers) { items.push({ action: 'recall', label: '撤回' }); } return items; }); function scrollToBottom() { (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .nextTick */ .dY)(() => { if (listEl.value) { listEl.value.scrollTop = listEl.value.scrollHeight; } }); } function scrollToMessage(messageId) { (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .nextTick */ .dY)(() => { if (!listEl.value || !messageId) { return; } const row = Array.from(listEl.value.querySelectorAll('.message-row')).find(element => element.dataset.messageKey === messageId); if (row) { row.scrollIntoView({ block: 'center', behavior: 'smooth' }); } }); } (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .watch */ .wB)(() => props.messages.map(message => `${message.id}:${message.status}:${message.deliveryStatus || ''}:${message.messageUid || ''}:${message.recalled ? '1' : ''}`).join('|'), scrollToBottom, { immediate: true }); (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .watch */ .wB)(() => props.attentionMessageId, scrollToMessage); (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .onMounted */ .sV)(() => { document.addEventListener('click', closeMenu); document.addEventListener('keydown', closeMenuOnEscape); document.addEventListener('pointermove', moveImageDrag); document.addEventListener('pointerup', stopImageDrag); }); (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .onBeforeUnmount */ .xo)(() => { document.removeEventListener('click', closeMenu); document.removeEventListener('keydown', closeMenuOnEscape); document.removeEventListener('pointermove', moveImageDrag); document.removeEventListener('pointerup', stopImageDrag); }); function messageIdentity(message) { return String(message.messageUid || message.id || ''); } function canOpenMessageMenu(message) { return message && message.status !== 'failed' && message.status !== 'sending'; } function isSelected(message) { return props.selectedMessageIds.includes(messageIdentity(message)); } function isFavorite(message) { return props.favoriteMessageIds.includes(messageIdentity(message)); } function isAttention(message) { return props.attentionMessageId === messageIdentity(message); } function isRecallNotice(message) { return message.direction === 'out' && (message.recalled || message.status === 'recalled'); } function isRecalledMessage(message) { return message.recalled || message.status === 'recalled'; } function isImageMessage(message) { return message?.type === 'image' && message?.attachment?.url; } function isFileMessage(message) { return message?.type === 'file' && message?.attachment?.url; } function displayFileName(message) { const text = String(message?.text || '').trim(); const attachmentName = String(message?.attachment?.name || '').trim(); return text || attachmentName || '文件'; } function isVideoMessage(message) { return (message?.type === 'video' || Number(message?.contentType || 0) === 6) && message?.attachment?.url; } function isRedPacketMessage(message) { return Number(message?.contentType || 0) === 90 || Boolean(redPacketPayload(message)); } function isRedPacketReceipt(message) { return Number(message?.contentType || 0) === 105; } function isSystemMessage(message) { return [92, 93].includes(Number(message?.contentType || 0)); } function systemMessageText(message) { const contentType = Number(message?.contentType || 0); if (contentType === 92) { return '以上是打招呼的内容'; } if (contentType === 93) { return '你们已经是好友了,可以开始聊天了。'; } return String(message?.text || ''); } function redPacketReceiptText(message) { const text = String(message?.text || '').trim(); if (text && text !== '[领取了红包]') { return text; } const receiverName = message?.direction === 'out' ? '你' : message?.senderName || '对方'; const packetSenderName = message?.redPacketSenderName || nearestRedPacketSenderName(message); return packetSenderName ? `${receiverName}领取了${packetSenderName}的红包` : `${receiverName}领取了红包`; } function nearestRedPacketSenderName(receiptMessage) { const receiptIndex = props.messages.findIndex(item => messageIdentity(item) === messageIdentity(receiptMessage)); for (let index = receiptIndex - 1; index >= 0; index -= 1) { const candidate = props.messages[index]; if (isRedPacketMessage(candidate)) { return candidate?.direction === 'out' ? '你' : candidate?.senderName || '对方'; } } return ''; } function redPacketPayload(message) { if (message?.redPacket && typeof message.redPacket === 'object') { return message.redPacket; } const text = String(message?.text || '').trim(); if (!text.startsWith('{')) { return null; } try { const payload = JSON.parse(text); return payload?.redPackets || payload?.redPacket || null; } catch (error) { return null; } } function redPacketBlessing(message) { return String(redPacketPayload(message)?.blessing || '恭喜发财,大吉大利'); } function isGroupMessage(message) { return ['group', 'channel'].includes(message?.conversationType || ''); } function showGroupSender(message) { return isGroupMessage(message) && message?.direction === 'in'; } function senderRoleLabel(message) { const role = message?.senderProfile?.role || message?.senderRole || ''; if (role === 'owner') { return '群主'; } if (role === 'admin') { return '管理员'; } return ''; } function groupSenderName(message) { return message?.senderName || message?.senderProfile?.displayName || message?.from || '未知用户'; } function groupSenderAvatarText(message) { return String(groupSenderName(message) || '?').slice(0, 1).toUpperCase(); } function openSenderProfile(message) { const profile = message?.senderProfile || {}; const uid = profile.uid || message?.from || ''; const cachedContact = contacts.contacts.find(contact => String(contact.uid || contact.id || '') === uid) || null; const cachedAlias = String(cachedContact?.alias || '').trim(); const contactAlias = String(profile.contactAlias || cachedAlias || profile.remarkAlias || '').trim(); const groupAlias = String(profile.groupAlias || '').trim(); const rawName = profile.rawName || cachedContact?.rawUser?.displayName || cachedContact?.rawUser?.name || cachedContact?.title || groupSenderName(message); const displayName = contactAlias || groupAlias || rawName || uid; senderProfile.visible = true; senderProfile.uid = uid; senderProfile.userId = profile.userId || profile.name || cachedContact?.rawUser?.name || ''; senderProfile.displayName = displayName; senderProfile.rawName = rawName || ''; senderProfile.mobile = profile.mobile || cachedContact?.rawUser?.mobile || ''; senderProfile.address = profile.address || cachedContact?.address || cachedContact?.rawUser?.address || ''; senderProfile.portrait = profile.portrait || cachedContact?.portrait || message?.senderPortrait || ''; senderProfile.avatarText = String(displayName || senderProfile.uid || '?').slice(0, 1).toUpperCase(); senderProfile.role = profile.role || message?.senderRole || ''; senderProfile.roleLabel = senderRoleLabel(message); senderProfile.contactAlias = contactAlias; senderProfile.groupAlias = groupAlias; senderProfile.isContact = Boolean(profile.isContact || cachedContact); senderProfile.aliasDraft = contactAlias; senderProfile.saving = false; senderProfile.adding = false; senderProfile.notice = ''; senderProfile.error = ''; closeMenu(); } function closeSenderProfile() { if (senderProfile.saving || senderProfile.adding) { return; } senderProfile.visible = false; } async function addSenderAsContact() { if (!senderProfile.uid || senderProfile.adding || senderProfile.saving) { return; } senderProfile.adding = true; senderProfile.notice = ''; senderProfile.error = ''; const ok = await contacts.addContact(senderProfile.uid); if (ok || String(contacts.actionError || '').includes('已经是联系人')) { senderProfile.isContact = true; const alias = senderProfile.aliasDraft.trim(); let aliasSaved = false; if (alias) { aliasSaved = await contacts.updateContactAlias(senderProfile.uid, alias); if (aliasSaved) { senderProfile.contactAlias = alias; senderProfile.displayName = alias; senderProfile.avatarText = String(alias || senderProfile.uid || '?').slice(0, 1).toUpperCase(); } } await contacts.refreshContacts({ force: true }).catch(() => {}); if (alias && !aliasSaved) { senderProfile.notice = ''; senderProfile.error = contacts.actionError ? `已添加为好友,但${contacts.actionError}` : '已添加为好友,但备注名同步失败'; } else { senderProfile.notice = alias ? '已添加为好友,备注名已保存' : ok ? '已添加为好友' : '已是好友'; } emit('sender-profile-updated', { userId: senderProfile.uid }); } else { senderProfile.error = contacts.actionError || '添加好友失败'; } senderProfile.adding = false; } async function saveSenderAlias() { if (!senderProfile.uid || senderProfile.saving || senderProfile.adding) { return; } senderProfile.saving = true; senderProfile.notice = ''; senderProfile.error = ''; const ok = await contacts.updateContactAlias(senderProfile.uid, senderProfile.aliasDraft); if (ok) { await contacts.refreshContacts({ force: true }).catch(() => {}); const alias = senderProfile.aliasDraft.trim(); senderProfile.contactAlias = alias; senderProfile.displayName = alias || senderProfile.groupAlias || senderProfile.rawName || senderProfile.uid; senderProfile.avatarText = String(senderProfile.displayName || senderProfile.uid || '?').slice(0, 1).toUpperCase(); senderProfile.notice = '备注名已保存'; emit('sender-profile-updated', { userId: senderProfile.uid }); } else { senderProfile.error = contacts.actionError || '备注名修改失败'; } senderProfile.saving = false; } function roleBubbleClass(message) { const role = message?.senderRole || ''; if (role === 'owner') { return 'role-bubble-owner'; } if (role === 'admin') { return 'role-bubble-admin'; } return ''; } function formatFileSize(size) { const bytes = Number(size || 0); if (bytes >= 1024 * 1024) { return `${(bytes / 1024 / 1024).toFixed(bytes >= 10 * 1024 * 1024 ? 0 : 1)} MB`; } if (bytes >= 1024) { return `${(bytes / 1024).toFixed(bytes >= 10 * 1024 ? 0 : 1)} KB`; } return bytes > 0 ? `${bytes} B` : ''; } function handleMessageClick(message) { if (props.selectionMode) { emit('toggle-select', message); } } function handleImageClick(message) { if (props.selectionMode) { emit('toggle-select', message); return; } openImageViewer(message); } function openImageViewer(message) { const attachment = message?.attachment || {}; if (!attachment.url) { return; } closeMenu(); imageViewer.visible = true; const index = viewerImages.value.findIndex(item => messageIdentity(item) === messageIdentity(message)); showViewerImage(index >= 0 ? index : 0); } function showViewerImage(index) { const images = viewerImages.value; if (!images.length) { closeImageViewer(); return; } const normalizedIndex = (index + images.length) % images.length; const attachment = images[normalizedIndex]?.attachment || {}; imageViewer.index = normalizedIndex; imageViewer.sourceUrl = attachment.url || ''; imageViewer.url = attachment.url || ''; imageViewer.name = attachment.name || `图片 ${normalizedIndex + 1}`; resetImageViewer(); } function showPreviousImage() { showViewerImage(imageViewer.index - 1); } function showNextImage() { showViewerImage(imageViewer.index + 1); } function closeImageViewer() { imageViewer.visible = false; imageViewer.dragging = false; imageViewer.sourceUrl = ''; } function resetImageViewer() { imageViewer.scale = 1; imageViewer.rotation = 0; imageViewer.offsetX = 0; imageViewer.offsetY = 0; } function clampImageScale(value) { return Math.min(IMAGE_MAX_SCALE, Math.max(IMAGE_MIN_SCALE, Number(value.toFixed(2)))); } function setImageScale(value, originX = null, originY = null) { const previousScale = imageViewer.scale; const nextScale = clampImageScale(value); if (nextScale === previousScale) { return; } if (originX !== null && originY !== null && viewerStage.value) { const rect = viewerStage.value.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const ratio = nextScale / previousScale - 1; imageViewer.offsetX -= (originX - centerX - imageViewer.offsetX) * ratio; imageViewer.offsetY -= (originY - centerY - imageViewer.offsetY) * ratio; } imageViewer.scale = nextScale; if (nextScale <= 1) { imageViewer.offsetX = 0; imageViewer.offsetY = 0; } } function zoomImage(delta) { setImageScale(imageViewer.scale + delta); } function rotateImage() { imageViewer.rotation = (imageViewer.rotation + 90) % 360; } function handleImageWheel(event) { const factor = event.deltaY < 0 ? 1.12 : 1 / 1.12; setImageScale(imageViewer.scale * factor, event.clientX, event.clientY); } function startImageDrag(event) { if (!imageViewer.visible || imageViewer.scale <= 1) { return; } imageViewer.dragging = true; imageViewer.dragStartX = event.clientX; imageViewer.dragStartY = event.clientY; imageViewer.dragOffsetX = imageViewer.offsetX; imageViewer.dragOffsetY = imageViewer.offsetY; } function moveImageDrag(event) { if (!imageViewer.dragging) { return; } imageViewer.offsetX = imageViewer.dragOffsetX + event.clientX - imageViewer.dragStartX; imageViewer.offsetY = imageViewer.dragOffsetY + event.clientY - imageViewer.dragStartY; } function stopImageDrag() { imageViewer.dragging = false; } function saveViewerImage() { if (!imageViewer.sourceUrl) { return; } const downloadUrl = new URL('/api/media_download.php', window.location.origin); downloadUrl.searchParams.set('url', imageViewer.sourceUrl); downloadUrl.searchParams.set('name', imageViewer.name || 'image'); const link = document.createElement('a'); link.href = downloadUrl.toString(); link.download = imageViewer.name || 'image'; document.body.appendChild(link); link.click(); link.remove(); } function openMenu(event, message) { if (!canOpenMessageMenu(message)) { closeMenu(); return; } contextMenu.visible = true; contextMenu.message = message; contextMenu.x = Math.min(event.clientX, window.innerWidth - 148); contextMenu.y = Math.min(event.clientY, window.innerHeight - 352); } function closeMenu() { contextMenu.visible = false; contextMenu.message = null; } function closeMenuOnEscape(event) { if (imageViewer.visible && event.key === 'ArrowLeft') { event.preventDefault(); showPreviousImage(); return; } if (imageViewer.visible && event.key === 'ArrowRight') { event.preventDefault(); showNextImage(); return; } if (event.key === 'Escape') { if (senderProfile.visible) { closeSenderProfile(); } if (imageViewer.visible) { closeImageViewer(); } closeMenu(); } } function chooseMenuAction(action) { if (contextMenu.message) { emit('message-action', { action, message: contextMenu.message }); } closeMenu(); } function formatTime(timestamp) { return new Intl.DateTimeFormat('zh-CN', { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone }).format(timestamp); } function deliveryState(message) { if (message.direction !== 'out' || message.status === 'failed' || message.status === 'recalled' || message.recalled) { return ''; } const state = message.deliveryStatus || message.status; if (state === 'read') { return 'read'; } if (state === 'delivered') { return 'delivered'; } if (state === 'sent') { return 'sent'; } return ''; } function deliveryTitle(message) { const state = deliveryState(message); if (state === 'read') { return '对方已读'; } if (state === 'delivered') { return '已送达对方'; } if (state === 'sent') { return '已送出'; } return ''; } function failureText(message) { if (message.status === 'failed') { if (message.errorCode) { return message.error ? `失败:${message.error}(${message.errorCode})` : `失败:${message.errorCode}`; } return message.error ? `失败:${message.error}` : '失败'; } return ''; } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", { ref_key: "listEl", ref: listEl, class: "message-list" }, [((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .renderList */ .pI)(__props.messages, message => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("article", { key: message.id, class: (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .normalizeClass */ .C4)(["message-row", [message.direction, { system: isSystemMessage(message), selected: isSelected(message), attention: isAttention(message), recalled: message.recalled || message.status === 'recalled' }]]), "data-message-key": messageIdentity(message), onClick: $event => handleMessageClick(message) }, [isSystemMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(systemMessageText(message)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), __props.selectionMode && !isSystemMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("label", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("input", { type: "checkbox", checked: isSelected(message), onClick: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])), onChange: $event => emit('toggle-select', message) }, null, 40, _hoisted_4)])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), !isSystemMessage(message) && showGroupSender(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 2, type: "button", class: "message-sender-avatar", title: groupSenderName(message), onClick: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)($event => openSenderProfile(message), ["stop"]) }, [message.senderPortrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("img", { key: 0, src: message.senderPortrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_11__/* .useImageProxyFallback */ .TJ)($event, message.senderPortrait) }, null, 40, _hoisted_6)) : ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_7, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(groupSenderAvatarText(message)), 1))], 8, _hoisted_5)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), !isSystemMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_8, [showGroupSender(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 0, type: "button", class: "message-sender-name", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)($event => openSenderProfile(message), ["stop"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createTextVNode */ .eW)((0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(groupSenderName(message)) + " ", 1), senderRoleLabel(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderRoleLabel(message)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)], 8, _hoisted_9)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", { class: (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .normalizeClass */ .C4)(["message-bubble", roleBubbleClass(message)]), onContextmenu: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)($event => openMenu($event, message), ["prevent"]) }, [isRedPacketMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", _hoisted_13, [_cache[9] || (_cache[9] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", { class: "red-packet-icon" }, "福", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(redPacketBlessing(message)), 1), _cache[8] || (_cache[8] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("small", null, "请在 App 上领取", -1))])]), _cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", { class: "red-packet-card-footer" }, "中聊红包", -1))])) : isRedPacketReceipt(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_14, [_cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", { class: "red-packet-mini-icon" }, "福", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(redPacketReceiptText(message)), 1)])) : isImageMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 2, type: "button", class: "message-image", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)($event => handleImageClick(message), ["stop"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("img", { src: message.attachment.url, alt: message.attachment.name || '图片' }, null, 8, _hoisted_16)], 8, _hoisted_15)) : isVideoMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("video", { key: 3, class: "message-video", src: (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_11__/* .videoDisplayUrl */ .nM)(message.attachment.url), controls: "", playsinline: "", preload: "metadata", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_11__/* .useVideoOriginalFallback */ .eR)($event, message.attachment.url) }, " 当前浏览器无法播放该视频 ", 40, _hoisted_17)) : isFileMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("a", { key: 4, class: "message-file", href: message.attachment.url, target: "_blank", rel: "noreferrer", download: "" }, [_cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", { class: "message-file-icon" }, "▤", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", _hoisted_19, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(displayFileName(message)), 1), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(formatFileSize(message.attachment.size)), 1)])], 8, _hoisted_18)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), message.text && !isFileMessage(message) && !isRedPacketMessage(message) && !isRedPacketReceipt(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("p", _hoisted_20, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(message.text), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("time", null, [isRecallNotice(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_21, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(message.recallStatus || '已撤回'), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(formatTime(message.displayTimestamp || message.timestamp)), 1), message.editedAt ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_22, "【edit " + (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(formatTime(message.editedAt)) + "】", 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), isFavorite(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_23, "★")) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), deliveryState(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", { key: 3, class: (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .normalizeClass */ .C4)(["delivery-mark", `delivery-mark-${deliveryState(message)}`]), title: deliveryTitle(message), "aria-label": deliveryTitle(message) }, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", { class: "delivery-check" }, "✓", -1)), deliveryState(message) !== 'sent' ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_25, "✓")) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)], 10, _hoisted_24)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), message.status === 'failed' ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_26, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(failureText(message)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)])], 42, _hoisted_11)])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)], 10, _hoisted_1); }), 128)), contextMenu.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", { key: 0, class: "message-context-menu", style: (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .normalizeStyle */ .Tr)({ left: `${contextMenu.x}px`, top: `${contextMenu.y}px` }), onClick: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .renderList */ .pI)(menuItems.value, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: item.action, type: "button", onClick: $event => chooseMenuAction(item.action) }, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(item.label), 9, _hoisted_27); }), 128))], 4)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createBlock */ .Wv)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Teleport */ .Im, { to: "body" }, [imageViewer.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", { key: 0, class: "image-viewer-backdrop", onClick: closeImageViewer }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", { class: "image-viewer-dialog", onClick: _cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", { class: "image-viewer-toolbar" }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "旋转", "aria-label": "旋转", onClick: rotateImage }, "⟳"), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "保存", "aria-label": "保存", onClick: saveViewerImage }, "⇩"), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", title: "关闭", "aria-label": "关闭", onClick: closeImageViewer }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", { ref_key: "viewerStage", ref: viewerStage, class: "image-viewer-stage" }, [viewerImages.value.length > 1 ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 0, type: "button", class: "image-viewer-nav image-viewer-prev", title: "上一张", "aria-label": "上一张", onPointerdown: _cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])), onClick: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(showPreviousImage, ["stop"]) }, "‹", 32)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("img", { class: "image-viewer-img", src: imageViewer.url, alt: imageViewer.name || '图片', style: (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .normalizeStyle */ .Tr)(imageViewerStyle.value), draggable: "false" }, null, 12, _hoisted_28), viewerImages.value.length > 1 ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 1, type: "button", class: "image-viewer-nav image-viewer-next", title: "下一张", "aria-label": "下一张", onPointerdown: _cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])), onClick: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(showNextImage, ["stop"]) }, "›", 32)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)], 512)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)])), ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createBlock */ .Wv)(vue__WEBPACK_IMPORTED_MODULE_7__/* .Teleport */ .Im, { to: "body" }, [senderProfile.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", { key: 0, class: "sender-profile-backdrop", onClick: closeSenderProfile }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("section", { class: "sender-profile-dialog", onClick: _cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("header", null, [_cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, "用户资料", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeSenderProfile }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", _hoisted_29, [senderProfile.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("img", { key: 0, class: "profile-avatar image-avatar", src: senderProfile.portrait, alt: "", onError: _cache[5] || (_cache[5] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_8__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_11__/* .useImageProxyFallback */ .TJ)($event, senderProfile.portrait)) }, null, 40, _hoisted_30)) : ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_31, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.displayName || senderProfile.uid), 1), senderProfile.roleLabel ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_32, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.roleLabel), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dl", _hoisted_33, [senderProfile.isContact ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("div", _hoisted_34, [_cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dt", null, "用户ID", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.userId || '-'), 1)])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", null, [_cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dt", null, "昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.rawName || senderProfile.displayName || '-'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", null, [_cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dt", null, "手机号", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.mobile || '未知'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("div", null, [_cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dt", null, "地区", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.address || '未知'), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("label", _hoisted_35, [_cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("span", null, "备注名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => senderProfile.aliasDraft = $event), maxlength: "32", autocomplete: "off", placeholder: "可给群员设置备注", disabled: senderProfile.saving || senderProfile.adding }, null, 8, _hoisted_36), [[vue__WEBPACK_IMPORTED_MODULE_6__/* .vModelText */ .Jo, senderProfile.aliasDraft, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("footer", _hoisted_37, [senderProfile.notice ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_38, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.notice), 1)) : senderProfile.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("span", _hoisted_39, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.error), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), !senderProfile.isContact ? ((0,vue__WEBPACK_IMPORTED_MODULE_7__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementBlock */ .CE)("button", { key: 2, type: "button", class: "ghost-inline-action", disabled: senderProfile.adding || senderProfile.saving || !senderProfile.uid, onClick: addSenderAsContact }, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.adding ? '添加中...' : '添加为好友'), 9, _hoisted_40)) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: senderProfile.saving || senderProfile.adding || !senderProfile.uid, onClick: saveSenderAlias }, (0,vue__WEBPACK_IMPORTED_MODULE_9__/* .toDisplayString */ .v_)(senderProfile.saving ? '保存中...' : '保存备注'), 9, _hoisted_41)])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_7__/* .createCommentVNode */ .Q3)("", true)]))], 512); }; } }); /***/ }), /***/ 3915: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5187); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9045); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(6384); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(446); const _hoisted_1 = { class: "contact-panel" }; const _hoisted_2 = { class: "chat-header" }; const _hoisted_3 = { class: "contact-profile" }; const _hoisted_4 = ["src"]; const _hoisted_5 = { key: 1, class: "profile-avatar" }; const _hoisted_6 = { class: "profile-main" }; const _hoisted_7 = { class: "remark-row" }; const _hoisted_8 = { class: "profile-fields" }; const _hoisted_9 = { key: 0, class: "form-error" }; const _hoisted_10 = { class: "modal-actions" }; const _hoisted_11 = ["disabled"]; const _hoisted_12 = ["disabled"]; const _hoisted_13 = { key: 1, class: "empty-chat" }; /* harmony default export */ __webpack_exports__.A = ({ __name: 'ContactPanel', setup(__props) { const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_4__/* .useContactStore */ .p)(); const contact = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => contacts.activeContact); const remarkName = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => contact.value?.alias || '未设置'); const username = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => contact.value?.rawUser?.displayName || contact.value?.rawUser?.name || contact.value?.uid || ''); const mobile = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => contact.value?.rawUser?.mobile || '未知'); const address = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => contact.value?.rawUser?.address || '未知'); const editingAlias = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(false); const aliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(''); const aliasSaving = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(false); const aliasError = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(''); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_5__/* .useAutoDismiss */ .R)(aliasError, value => { if (aliasError.value === value) aliasError.value = ''; }); (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .watch */ .wB)(contact, () => { editingAlias.value = false; aliasError.value = ''; }); function openAliasEditor() { aliasDraft.value = contact.value?.alias || ''; aliasError.value = ''; editingAlias.value = true; } function closeAliasEditor() { if (aliasSaving.value) { return; } editingAlias.value = false; aliasError.value = ''; } async function submitAlias() { if (!contact.value) { return; } aliasSaving.value = true; aliasError.value = ''; const ok = await contacts.updateContactAlias(contact.value.uid, aliasDraft.value); aliasSaving.value = false; if (ok) { editingAlias.value = false; return; } aliasError.value = contacts.actionError || '备注名修改失败'; } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("section", _hoisted_1, [contact.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_1__/* .Fragment */ .FK, { key: 0 }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("header", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("h2", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(remarkName.value), 1), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(username.value), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_3, [contact.value.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("img", { key: 0, class: "profile-avatar image-avatar", src: contact.value.portrait, alt: "", onError: _cache[0] || (_cache[0] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_6__/* .useImageProxyFallback */ .TJ)($event, contact.value.portrait)) }, null, 40, _hoisted_4)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("div", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(contact.value.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("h3", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(remarkName.value), 1), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button remark-edit-button", title: "编辑备注名", onClick: openAliasEditor }, "✏️")])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dl", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "用户名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(username.value), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "手机号", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(mobile.value), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "地区", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(address.value), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", { class: "primary-action profile-action", onClick: _cache[1] || (_cache[1] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(contacts).openChat(contact.value)) }, "发消息")]), editingAlias.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("div", { key: 0, class: "modal-backdrop contact-modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .withModifiers */ .D$)(closeAliasEditor, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("form", { class: "modal-panel", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .withModifiers */ .D$)(submitAlias, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("header", null, [_cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("strong", null, "编辑备注名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeAliasEditor }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("label", null, [_cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("span", null, "备注名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => aliasDraft.value = $event), maxlength: "32", autocomplete: "off", autofocus: "" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_0__/* .vModelText */ .Jo, aliasDraft.value, void 0, { trim: true }]])]), aliasError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("p", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(aliasError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", disabled: aliasSaving.value, onClick: closeAliasEditor }, "取消", 8, _hoisted_11), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", { type: "submit", class: "primary-inline-action", disabled: aliasSaving.value }, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(aliasSaving.value ? '保存中' : '保存'), 9, _hoisted_12)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createCommentVNode */ .Q3)("", true)], 64)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("div", _hoisted_13, _cache[8] || (_cache[8] = [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("strong", null, "选择一个联系人", -1), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("span", null, "好友列表同步完成后,可以在左侧查看资料", -1)])))]); }; } }); /***/ }), /***/ 9829: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5187); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7566); const _hoisted_1 = { class: "conversation-list favorite-list" }; const _hoisted_2 = { class: "list-header" }; const _hoisted_3 = { class: "sidebar-scroll" }; const _hoisted_4 = ["onClick"]; const _hoisted_5 = { class: "favorite-item-main" }; const _hoisted_6 = { key: 0, class: "empty-list" }; /* harmony default export */ __webpack_exports__.A = ({ __name: 'FavoriteList', setup(__props) { const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_5__/* .useConversationStore */ .w)(); const activeKey = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => conversations.activeFavorite?.key || ''); function favoriteTitle(item) { if (item.conversationTitle) { return item.conversationTitle; } const conversation = conversations.conversations.find(entry => entry.id === item.conversationId); return conversation?.title || item.conversationId || '未知会话'; } function favoritePreview(item) { if (item.recalled) { return `[${item.recallStatus || '已撤回'}]`; } if (item.preview) { return item.preview; } if (item.text) { return item.text; } if (item.type === 'image') { return '[图片]'; } if (item.type === 'file') { return `[文件] ${item.attachment?.name || '文件'}`; } return '(无文字内容)'; } function formatFavoriteTime(timestamp) { const value = Number(timestamp || 0); if (!value) { return ''; } return new Intl.DateTimeFormat('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false }).format(value); } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("aside", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("header", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", null, [_cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("h2", null, "收藏", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(conversations).favoriteMessages.length) + " 条消息", 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_3, [((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_2__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .renderList */ .pI)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(conversations).favoriteMessages, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("button", { key: item.key, type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .normalizeClass */ .C4)(["favorite-item", { active: activeKey.value === item.key }]), onClick: $event => (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(conversations).setActiveFavorite(item.key) }, [_cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", { class: "favorite-item-icon" }, "★", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(favoriteTitle(item)), 1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(favoritePreview(item)), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("time", null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .toDisplayString */ .v_)(formatFavoriteTime(item.timestamp)), 1)], 10, _hoisted_4); }), 128)), !(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .unref */ .R1)(conversations).favoriteMessages.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("div", _hoisted_6, " 暂无收藏消息 ")) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true)])]); }; } }); /***/ }), /***/ 6415: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5187); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(144); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7566); /* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1414); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(6384); const _hoisted_1 = { class: "favorite-panel" }; const _hoisted_2 = { class: "chat-header" }; const _hoisted_3 = { class: "favorite-detail" }; const _hoisted_4 = { class: "favorite-detail-body" }; const _hoisted_5 = { key: 0, class: "recall-mark" }; const _hoisted_6 = ["href"]; const _hoisted_7 = ["src", "alt"]; const _hoisted_8 = ["href"]; const _hoisted_9 = { class: "message-file-main" }; const _hoisted_10 = { key: 3 }; const _hoisted_11 = { class: "favorite-detail-actions" }; const _hoisted_12 = { key: 0, class: "inline-save-status" }; const _hoisted_13 = { key: 1, class: "inline-save-status error" }; const _hoisted_14 = { key: 1, class: "empty-chat" }; /* harmony default export */ __webpack_exports__.A = ({ __name: 'FavoritePanel', setup(__props) { const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_5__/* .useConversationStore */ .w)(); const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_6__/* .useNavigationStore */ .l)(); const favorite = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .computed */ .EW)(() => conversations.activeFavorite); const notice = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const error = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_7__/* .useAutoDismiss */ .R)(() => error.value || notice.value, value => { if ((error.value || notice.value) === value) clearFeedback(); }); function clearFeedback() { notice.value = ''; error.value = ''; } function favoriteTitle(item) { if (item.conversationTitle) { return item.conversationTitle; } const conversation = conversations.conversations.find(entry => entry.id === item.conversationId); return conversation?.title || item.conversationId || '未知会话'; } function favoriteText(item) { return item.text || ''; } function isImageFavorite(item) { return item?.type === 'image' && item?.attachment?.url; } function isFileFavorite(item) { return item?.type === 'file' && item?.attachment?.url; } function favoriteCopyText(item) { if (!item) { return ''; } if (item.text) { return item.text; } if (item.recalled) { return item.recallStatus || '已撤回'; } if (isImageFavorite(item)) { return item.attachment.url; } if (isFileFavorite(item)) { return `${item.attachment.name || '文件'} ${item.attachment.url}`.trim(); } return item.preview || ''; } function formatFileSize(size) { const bytes = Number(size || 0); if (bytes >= 1024 * 1024) { return `${(bytes / 1024 / 1024).toFixed(bytes >= 10 * 1024 * 1024 ? 0 : 1)} MB`; } if (bytes >= 1024) { return `${(bytes / 1024).toFixed(bytes >= 10 * 1024 ? 0 : 1)} KB`; } return bytes > 0 ? `${bytes} B` : ''; } function formatFavoriteTime(timestamp) { const value = Number(timestamp || 0); if (!value) { return ''; } return new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false }).format(value); } async function copyFavorite() { clearFeedback(); const text = favoriteCopyText(favorite.value || {}).trim(); if (!text) { error.value = '没有可复制的文字内容'; return; } try { await writeClipboard(text); notice.value = '已复制'; } catch (copyError) { error.value = '复制失败'; } } async function writeClipboard(text) { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(text); return; } const element = document.createElement('textarea'); element.value = text; element.setAttribute('readonly', 'readonly'); element.style.position = 'fixed'; element.style.left = '-9999px'; document.body.appendChild(element); element.select(); document.execCommand('copy'); document.body.removeChild(element); } function openConversation() { clearFeedback(); const item = favorite.value; if (!item?.conversationId) { error.value = '缺少原会话信息'; return; } const conversation = conversations.conversations.find(entry => entry.id === item.conversationId); if (!conversation) { error.value = '原会话暂未加载,请刷新会话后再试'; conversations.refreshRemoteConversations(); return; } navigation.showMessages(); conversations.setActiveConversation(item.conversationId); window.setTimeout(() => { conversations.focusMessage({ id: item.id || item.key, messageUid: item.messageUid || item.key }); }, 450); } function removeFavorite() { clearFeedback(); const key = favorite.value?.key || ''; if (!key) { return; } conversations.removeFavorite(key); notice.value = '已取消收藏'; } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("section", _hoisted_1, [favorite.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_2__/* .Fragment */ .FK, { key: 0 }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("header", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", null, [_cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("h2", null, "收藏详情", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(favoriteTitle(favorite.value)), 1)])]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", { class: (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .normalizeClass */ .C4)(["favorite-detail-message", { recalled: favorite.value.recalled }]) }, [_cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", { class: "favorite-detail-star" }, "★", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_4, [favorite.value.recalled ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("span", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(favorite.value.recallStatus || '已撤回'), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), isImageFavorite(favorite.value) ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("a", { key: 1, class: "favorite-detail-image", href: favorite.value.attachment.url, target: "_blank", rel: "noreferrer" }, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("img", { src: favorite.value.attachment.url, alt: favorite.value.attachment.name || '图片' }, null, 8, _hoisted_7)], 8, _hoisted_6)) : isFileFavorite(favorite.value) ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("a", { key: 2, class: "message-file favorite-detail-file", href: favorite.value.attachment.url, target: "_blank", rel: "noreferrer", download: "" }, [_cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", { class: "message-file-icon" }, "▤", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(favorite.value.attachment.name || '文件'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(formatFileSize(favorite.value.attachment.size)), 1)])], 8, _hoisted_8)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), favoriteText(favorite.value) ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("p", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(favoriteText(favorite.value)), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("time", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(formatFavoriteTime(favorite.value.timestamp)), 1)], 2), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("div", _hoisted_11, [notice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("span", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(notice.value), 1)) : error.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("span", _hoisted_13, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(error.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: copyFavorite }, "复制"), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: openConversation }, "打开原会话"), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("button", { type: "button", class: "danger-inline-action", onClick: removeFavorite }, "取消收藏")])])], 64)) : ((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementBlock */ .CE)("div", _hoisted_14, _cache[3] || (_cache[3] = [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("strong", null, "暂无收藏消息", -1), (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .createElementVNode */ .Lk)("span", null, "右键消息气泡选择“收藏”后,会显示在这里", -1)])))]); }; } }); /***/ }), /***/ 5684: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(5187); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9045); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(446); const _hoisted_1 = { class: "conversation-list" }; const _hoisted_2 = { class: "list-header" }; const _hoisted_3 = { class: "header-actions" }; const _hoisted_4 = { class: "search-box" }; const _hoisted_5 = { class: "sidebar-scroll" }; const _hoisted_6 = ["onClick"]; const _hoisted_7 = ["src", "onError"]; const _hoisted_8 = { key: 1, class: "conversation-avatar" }; const _hoisted_9 = { class: "conversation-copy" }; const _hoisted_10 = { key: 0, class: "empty-list" }; const _hoisted_11 = { key: 0, class: "form-error" }; const _hoisted_12 = { key: 1, class: "form-info" }; const _hoisted_13 = { class: "modal-actions" }; const _hoisted_14 = ["disabled"]; /* harmony default export */ __webpack_exports__.A = ({ __name: 'ContactList', setup(__props) { const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_7__/* .useContactStore */ .p)(); const keyword = (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .ref */ .KR)(''); const addingContact = (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .ref */ .KR)(false); const addKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .ref */ .KR)(''); const filteredContacts = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .computed */ .EW)(() => { const value = keyword.value.toLowerCase(); if (!value) { return contacts.contacts; } return contacts.contacts.filter(item => { return item.title.toLowerCase().includes(value) || item.subtitle.toLowerCase().includes(value) || item.uid.toLowerCase().includes(value); }); }); function openAddContact() { contacts.actionError = ''; contacts.actionInfo = ''; addKeyword.value = ''; addingContact.value = true; } function closeAddContact() { addingContact.value = false; } async function submitAddContact() { const added = await contacts.addContact(addKeyword.value); if (added) { window.setTimeout(() => { addingContact.value = false; }, 500); } } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("aside", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("header", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("div", null, [_cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("h2", null, "联系人", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).contacts.length) + " 位好友", 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("button", { class: "icon-button", title: "添加联系人", onClick: openAddContact }, "+"), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("button", { class: "icon-button", title: "刷新", onClick: _cache[0] || (_cache[0] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).refreshContacts({ force: true })) }, "↻")])]), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("div", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => keyword.value = $event), placeholder: "搜索联系人" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_3__/* .vModelText */ .Jo, keyword.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("div", _hoisted_5, [((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_4__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .renderList */ .pI)(filteredContacts.value, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("button", { key: item.id, class: (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .normalizeClass */ .C4)(["conversation-item", { active: item.id === (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).activeId }]), onClick: $event => (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).setActiveContact(item.id) }, [item.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: item.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_8__/* .useImageProxyFallback */ .TJ)($event, item.portrait) }, null, 40, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("span", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)(item.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("span", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)(item.title), 1), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)(item.subtitle), 1)])], 10, _hoisted_6); }), 128)), !filteredContacts.value.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("div", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).loading ? '正在加载' : '暂无联系人'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).loading ? '请稍候' : '好友同步完成后会显示在这里'), 1)])) : (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createCommentVNode */ .Q3)("", true)]), addingContact.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("div", { key: 0, class: "modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withModifiers */ .D$)(closeAddContact, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("form", { class: "modal-panel", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withModifiers */ .D$)(submitAddContact, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("header", null, [_cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("strong", null, "添加联系人", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeAddContact }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("label", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("span", null, "用户ID / 手机号 / 用户名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[2] || (_cache[2] = $event => addKeyword.value = $event), autocomplete: "off", placeholder: "请输入要添加的联系人" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_3__/* .vModelText */ .Jo, addKeyword.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).actionError ? ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("p", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).actionError), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).actionInfo ? ((0,vue__WEBPACK_IMPORTED_MODULE_4__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementBlock */ .CE)("p", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).actionInfo), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("div", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: closeAddContact }, "取消"), (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createElementVNode */ .Lk)("button", { class: "primary-inline-action", disabled: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).loading || !addKeyword.value }, (0,vue__WEBPACK_IMPORTED_MODULE_6__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_5__/* .unref */ .R1)(contacts).loading ? '添加中...' : '添加'), 9, _hoisted_14)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .createCommentVNode */ .Q3)("", true)]); }; } }); /***/ }), /***/ 4621: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(531); /* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3579); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(5367); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(2731); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8__); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(7642); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9__); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(8004); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10__); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(3853); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11__); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(5876); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(2475); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(5024); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14__); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(1698); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(5187); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(7566); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(9045); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(446); const _hoisted_1 = { class: "conversation-list" }; const _hoisted_2 = { class: "list-header" }; const _hoisted_3 = { class: "header-actions action-menu-anchor" }; const _hoisted_4 = { class: "search-box" }; const _hoisted_5 = { class: "sidebar-scroll" }; const _hoisted_6 = ["onClick", "onContextmenu"]; const _hoisted_7 = ["src", "onError"]; const _hoisted_8 = { key: 1, class: "conversation-avatar" }; const _hoisted_9 = { class: "conversation-copy" }; const _hoisted_10 = { key: 0, class: "conversation-pin", "aria-label": "已置顶" }; const _hoisted_11 = ["aria-label"]; const _hoisted_12 = { key: 1, class: "empty-list" }; const _hoisted_13 = { key: 2, class: "empty-list" }; const _hoisted_14 = { key: 0 }; const _hoisted_15 = { key: 2 }; const _hoisted_16 = { key: 5, class: "form-error" }; const _hoisted_17 = { key: 6, class: "form-info" }; const _hoisted_18 = { class: "modal-actions" }; const _hoisted_19 = ["disabled"]; /* harmony default export */ __webpack_exports__.A = ({ __name: 'ConversationList', setup(__props) { const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_20__/* .useConversationStore */ .w)(); const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_21__/* .useContactStore */ .p)(); const actionMenuOpen = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(false); const activeAction = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const actionBusy = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(false); const searchKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const addKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const groupName = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const groupAnnouncement = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const groupWelcomeText = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const joinGroupKey = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const broadcastText = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const channelName = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const channelAnnouncement = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const contactKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)(''); const selectedContactIds = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)([]); const conversationMenu = (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .ref */ .KR)({ item: null, x: 0, y: 0 }); const actionTitles = { addContact: '添加联系人', createGroup: '新建群组', joinGroup: '加入群组', broadcast: '群发助手', createChannel: '创建频道/公告群' }; const submitLabels = { addContact: '添加', createGroup: '创建', joinGroup: '加入', broadcast: '发送', createChannel: '创建' }; const actionTitle = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => actionTitles[activeAction.value] || ''); const submitLabel = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => submitLabels[activeAction.value] || '确定'); const modalError = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => contacts.actionError || conversations.actionError); const modalInfo = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => contacts.actionInfo || conversations.actionNotice); const normalizedSearchKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => searchKeyword.value.trim().toLowerCase()); const contactsByUid = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => { const map = new Map(); contacts.contacts.forEach(contact => { const uid = String(contact.uid || contact.id || ''); if (uid) { map.set(uid, contact); } }); return map; }); const filteredConversationItems = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => { const keyword = normalizedSearchKeyword.value; if (!keyword) { return conversations.conversations.map(item => conversationResult(item)); } const conversationResults = conversations.conversations.filter(item => matchesConversation(item, keyword, contactForConversation(item))).map(item => conversationResult(item)); const conversationTargets = new Set(conversations.conversations.filter(item => item.type === 'single').map(item => conversationTarget(item))); const contactResults = contacts.contacts.filter(item => !conversationTargets.has(String(item.uid || item.id || ''))).filter(item => matchesContact(item, keyword)).map(item => contactResult(item)); return [...conversationResults, ...contactResults]; }); const filteredContacts = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => { const keyword = contactKeyword.value.toLowerCase(); if (!keyword) { return contacts.contacts; } return contacts.contacts.filter(item => { return String(item.title || '').toLowerCase().includes(keyword) || String(item.subtitle || '').toLowerCase().includes(keyword) || String(item.uid || '').toLowerCase().includes(keyword); }); }); const submitDisabled = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .computed */ .EW)(() => { if (activeAction.value === 'addContact') { return !addKeyword.value; } if (activeAction.value === 'createGroup') { return !groupName.value || !selectedContactIds.value.length; } if (activeAction.value === 'joinGroup') { return !joinGroupKey.value; } if (activeAction.value === 'broadcast') { return !broadcastText.value || !selectedContactIds.value.length; } if (activeAction.value === 'createChannel') { return !channelName.value; } return true; }); (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .onMounted */ .sV)(() => { contacts.refreshContacts().catch(() => {}); }); function isPinned(item) { return item?.resultKind === 'conversation' && Number(item.pinnedAt || item.top || 0) > 0; } function openConversationMenu(event, item) { if (item.resultKind !== 'conversation') return; conversationMenu.value = { item, x: Math.min(event.clientX, window.innerWidth - 140), y: Math.min(event.clientY, window.innerHeight - 60) }; } function closeConversationMenu() { conversationMenu.value = { item: null, x: 0, y: 0 }; } function togglePinned() { const item = conversationMenu.value.item; if (item) conversations.togglePinnedConversation(item.id); closeConversationMenu(); } function deleteConversation() { const item = conversationMenu.value.item; if (item && window.confirm(`确定删除与“${item.title}”的会话吗?`)) { conversations.removeConversation(item.id); conversations.setActionNotice('会话已删除'); } closeConversationMenu(); } const ContactPicker = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .defineComponent */ .pM)({ name: 'ContactPicker', props: { contacts: { type: Array, default: () => [] }, selectedIds: { type: Array, default: () => [] }, keyword: { type: String, default: '' }, emptyText: { type: String, default: '暂无联系人' } }, emits: ['toggle', 'update:keyword'], setup(props, { emit }) { return () => (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('div', { class: 'contact-picker' }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('input', { value: props.keyword, placeholder: '搜索联系人', onInput: event => emit('update:keyword', event.target.value) }), (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('div', { class: 'contact-picker-list' }, props.contacts.length ? props.contacts.map(contact => (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('button', { key: contact.uid, type: 'button', class: ['contact-picker-row', { selected: props.selectedIds.includes(contact.uid) }], onClick: () => emit('toggle', contact.uid) }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('span', { class: 'contact-check' }, props.selectedIds.includes(contact.uid) ? '✓' : ''), contact.portrait ? (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('img', { class: 'conversation-avatar image-avatar', src: contact.portrait, alt: '' }) : (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('span', { class: 'conversation-avatar' }, contact.avatarText), (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('span', { class: 'contact-picker-copy' }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('strong', contact.title), (0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('small', contact.subtitle)])])) : [(0,vue__WEBPACK_IMPORTED_MODULE_17__.h)('div', { class: 'contact-picker-empty' }, props.emptyText)])]); } }); function searchableValues(...values) { return values.flatMap(value => { if (Array.isArray(value)) { return value; } if (value && typeof value === 'object') { return Object.values(value); } return [value]; }).map(value => String(value || '').toLowerCase()).filter(Boolean); } function matchesKeyword(values, keyword) { const compactKeyword = keyword.replace(/[^\p{L}\p{N}]+/gu, ''); return searchableValues(values).some(value => { if (value.includes(keyword)) { return true; } if (!compactKeyword) { return false; } return value.replace(/[^\p{L}\p{N}]+/gu, '').includes(compactKeyword); }); } function conversationTarget(item) { if (item.type !== 'single') { return String(item.target || item.raw?.target || item.id || ''); } return String(item.target || item.raw?.target || item.id.replace(/^single-/, '') || ''); } function contactForConversation(item) { const target = conversationTarget(item); return target ? contactsByUid.value.get(target) || null : null; } function matchesConversation(item, keyword, contact = null) { return matchesKeyword([item.title, item.subtitle, item.target, item.id, item.type, item.raw?.target, item.raw?.groupId, item.raw?.group_id, item.raw?.owner_uid, item.raw?.name, item.raw?.displayName, item.raw?.mobile, item.raw?.friendAlias, item.raw?.alias, contact?.title, contact?.subtitle, contact?.uid, contact?.id, contact?.alias, contact?.address, contact?.rawUser, contact?.rawFriend], keyword); } function matchesContact(item, keyword) { return matchesKeyword([item.title, item.subtitle, item.uid, item.id, item.alias, item.address, item.rawUser, item.rawFriend], keyword); } function conversationResult(item) { return { ...item, resultKind: 'conversation', resultKey: `conversation-${item.id}` }; } function contactResult(contact) { return { id: contact.id, resultKind: 'contact', resultKey: `contact-${contact.uid || contact.id}`, contact, title: contact.title, subtitle: contact.subtitle, portrait: contact.portrait, avatarText: contact.avatarText, unread: 0 }; } function isListItemActive(item) { if (item.resultKind === 'conversation') { return item.id === conversations.activeId; } return `single-${item.contact?.uid || item.id}` === conversations.activeId; } function selectListItem(item) { if (item.resultKind === 'contact') { contacts.openChat(item.contact); return; } conversations.setActiveConversation(item.id); } function clearStoreMessages() { contacts.actionError = ''; contacts.actionInfo = ''; conversations.actionError = ''; conversations.actionNotice = ''; } function resetActionFields() { addKeyword.value = ''; groupName.value = ''; groupAnnouncement.value = ''; groupWelcomeText.value = ''; joinGroupKey.value = ''; broadcastText.value = ''; channelName.value = ''; channelAnnouncement.value = ''; contactKeyword.value = ''; selectedContactIds.value = []; clearStoreMessages(); } function toggleActionMenu() { actionMenuOpen.value = !actionMenuOpen.value; } function closeActionMenu() { actionMenuOpen.value = false; } function openAction(action) { resetActionFields(); activeAction.value = action; actionMenuOpen.value = false; if (['createGroup', 'broadcast', 'createChannel'].includes(action)) { contacts.refreshContacts({ force: true }); } } function closeActionModal() { activeAction.value = ''; actionBusy.value = false; resetActionFields(); } function toggleContact(contactId) { const selected = new Set(selectedContactIds.value); if (selected.has(contactId)) { selected.delete(contactId); } else { selected.add(contactId); } selectedContactIds.value = Array.from(selected); } async function submitAction() { if (submitDisabled.value || actionBusy.value) { return; } actionBusy.value = true; clearStoreMessages(); try { let ok = false; if (activeAction.value === 'addContact') { ok = await contacts.addContact(addKeyword.value); if (ok && contacts.activeContact) { contacts.openChat(contacts.activeContact); } } else if (activeAction.value === 'createGroup') { ok = await conversations.createGroup({ name: groupName.value, announcement: groupAnnouncement.value, welcomeText: groupWelcomeText.value, memberIds: selectedContactIds.value }); } else if (activeAction.value === 'joinGroup') { ok = await conversations.joinGroup(joinGroupKey.value); } else if (activeAction.value === 'broadcast') { ok = await conversations.broadcastMessage(selectedContactIds.value, broadcastText.value); } else if (activeAction.value === 'createChannel') { ok = await conversations.createGroup({ name: channelName.value, memberIds: selectedContactIds.value, announcement: channelAnnouncement.value, channel: true }); } if (ok) { window.setTimeout(closeActionModal, 450); } } finally { actionBusy.value = false; } } document.addEventListener('click', closeActionMenu); document.addEventListener('click', closeConversationMenu); (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .onBeforeUnmount */ .xo)(() => { document.removeEventListener('click', closeActionMenu); document.removeEventListener('click', closeConversationMenu); }); function formatUnread(value) { const count = Number(value || 0); return count > 99 ? '99+' : String(count); } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("aside", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("header", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("div", null, [_cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("h2", null, "消息", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("p", null, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(conversations).totalUnread) + " 条未读", 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { class: "icon-button", title: "新建会话", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)(toggleActionMenu, ["stop"]) }, "+"), actionMenuOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("div", { key: 0, class: "quick-action-menu", onClick: _cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[0] || (_cache[0] = $event => openAction('addContact')) }, "添加联系人"), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[1] || (_cache[1] = $event => openAction('createGroup')) }, "新建群组"), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[2] || (_cache[2] = $event => openAction('joinGroup')) }, "加入群组"), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[3] || (_cache[3] = $event => openAction('broadcast')) }, "群发助手"), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: _cache[4] || (_cache[4] = $event => openAction('createChannel')) }, "创建频道/公告群")])) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true)])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("div", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => searchKeyword.value = $event), placeholder: "搜索会话、联系人" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, searchKeyword.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("div", _hoisted_5, [((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_17__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .renderList */ .pI)(filteredConversationItems.value, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("button", { key: item.resultKey, class: (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .normalizeClass */ .C4)(["conversation-item", { active: isListItemActive(item), pinned: isPinned(item) }]), onClick: $event => selectListItem(item), onContextmenu: (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)($event => openConversationMenu($event, item), ["prevent"]) }, [item.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("img", { key: 0, class: "conversation-avatar image-avatar", src: item.portrait, alt: "", onError: $event => (0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_22__/* .useImageProxyFallback */ .TJ)($event, item.portrait) }, null, 40, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("span", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(item.avatarText), 1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("strong", null, [isPinned(item) ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("span", _hoisted_10, "⌖")) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createTextVNode */ .eW)((0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(item.title), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(item.subtitle), 1)]), Number(item.unread || 0) > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("span", { key: 2, class: "unread-badge", "aria-label": `${item.unread} 条未读消息` }, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(formatUnread(item.unread)), 9, _hoisted_11)) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true)], 42, _hoisted_6); }), 128)), conversationMenu.value.item ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("div", { key: 0, class: "conversation-context-menu", style: (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .normalizeStyle */ .Tr)({ left: `${conversationMenu.value.x}px`, top: `${conversationMenu.value.y}px` }), onClick: _cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)(() => {}, ["stop"])) }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: togglePinned }, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(isPinned(conversationMenu.value.item) ? '取消置顶' : '置顶会话'), 1), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", onClick: deleteConversation }, "删除会话")], 4)) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true), !filteredConversationItems.value.length && searchKeyword.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("div", _hoisted_12, _cache[20] || (_cache[20] = [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("strong", null, "没有匹配结果", -1), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "换个关键词再试试", -1)]))) : !(0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(conversations).conversations.length && !(0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(conversations).usingDemoData ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("div", _hoisted_13, _cache[21] || (_cache[21] = [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("strong", null, "暂无会话", -1), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "收到或发起消息后会出现在这里", -1)]))) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true)]), activeAction.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("div", { key: 0, class: "modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)(closeActionModal, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("form", { class: "modal-panel conversation-action-panel", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_16__/* .withModifiers */ .D$)(submitAction, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("header", null, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(actionTitle.value), 1), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeActionModal }, "×")]), activeAction.value === 'addContact' ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("label", _hoisted_14, [_cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "用户ID / 手机号 / 用户名", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[8] || (_cache[8] = $event => addKeyword.value = $event), autocomplete: "off", placeholder: "请输入要添加的联系人" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, addKeyword.value, void 0, { trim: true }]])])) : activeAction.value === 'createGroup' ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_17__/* .Fragment */ .FK, { key: 1 }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "群组名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[9] || (_cache[9] = $event => groupName.value = $event), maxlength: "64", autocomplete: "off", placeholder: "请输入群组名称" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, groupName.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "群说明", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[10] || (_cache[10] = $event => groupAnnouncement.value = $event), maxlength: "1000", rows: "3", placeholder: "可选" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, groupAnnouncement.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "欢迎词", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[11] || (_cache[11] = $event => groupWelcomeText.value = $event), maxlength: "1000", rows: "3", placeholder: "群组创建后自动发送" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, groupWelcomeText.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createVNode */ .bF)((0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(ContactPicker), { contacts: filteredContacts.value, "selected-ids": selectedContactIds.value, keyword: contactKeyword.value, "empty-text": "暂无可选联系人", "onUpdate:keyword": _cache[12] || (_cache[12] = $event => contactKeyword.value = $event), onToggle: toggleContact }, null, 8, ["contacts", "selected-ids", "keyword"])], 64)) : activeAction.value === 'joinGroup' ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("label", _hoisted_15, [_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "群组ID / 群名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[13] || (_cache[13] = $event => joinGroupKey.value = $event), autocomplete: "off", placeholder: "请输入群组ID或群名称" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, joinGroupKey.value, void 0, { trim: true }]])])) : activeAction.value === 'broadcast' ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_17__/* .Fragment */ .FK, { key: 3 }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "群发内容", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[14] || (_cache[14] = $event => broadcastText.value = $event), maxlength: "2000", rows: "4", placeholder: "输入要群发的文字" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, broadcastText.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createVNode */ .bF)((0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(ContactPicker), { contacts: filteredContacts.value, "selected-ids": selectedContactIds.value, keyword: contactKeyword.value, "empty-text": "暂无可选联系人", "onUpdate:keyword": _cache[15] || (_cache[15] = $event => contactKeyword.value = $event), onToggle: toggleContact }, null, 8, ["contacts", "selected-ids", "keyword"])], 64)) : activeAction.value === 'createChannel' ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_17__/* .Fragment */ .FK, { key: 4 }, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "频道/公告群名称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[16] || (_cache[16] = $event => channelName.value = $event), maxlength: "64", autocomplete: "off", placeholder: "请输入名称" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, channelName.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("label", null, [_cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("span", null, "公告说明", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("textarea", { "onUpdate:modelValue": _cache[17] || (_cache[17] = $event => channelAnnouncement.value = $event), maxlength: "1000", rows: "3", placeholder: "可选" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_16__/* .vModelText */ .Jo, channelAnnouncement.value, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createVNode */ .bF)((0,vue__WEBPACK_IMPORTED_MODULE_18__/* .unref */ .R1)(ContactPicker), { contacts: filteredContacts.value, "selected-ids": selectedContactIds.value, keyword: contactKeyword.value, "empty-text": "暂无可选联系人", "onUpdate:keyword": _cache[18] || (_cache[18] = $event => contactKeyword.value = $event), onToggle: toggleContact }, null, 8, ["contacts", "selected-ids", "keyword"])], 64)) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true), modalError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("p", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(modalError.value), 1)) : modalInfo.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_17__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementBlock */ .CE)("p", _hoisted_17, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(modalInfo.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("div", _hoisted_18, [(0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: closeActionModal }, "取消"), (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createElementVNode */ .Lk)("button", { class: "primary-inline-action", disabled: actionBusy.value || submitDisabled.value }, (0,vue__WEBPACK_IMPORTED_MODULE_19__/* .toDisplayString */ .v_)(actionBusy.value ? '处理中...' : submitLabel.value), 9, _hoisted_19)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_17__/* .createCommentVNode */ .Q3)("", true)]); }; } }); /***/ }), /***/ 7420: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5130); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6768); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(144); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5187); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(926); /* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(1414); /* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(9045); /* harmony import */ var _composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(6384); /* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(446); const _hoisted_1 = { class: "navigation-rail" }; const _hoisted_2 = ["src"]; const _hoisted_3 = { key: 1 }; const _hoisted_4 = { class: "settings-panel" }; const _hoisted_5 = { class: "settings-layout" }; const _hoisted_6 = { class: "settings-menu", "aria-label": "设置菜单" }; const _hoisted_7 = ["onClick"]; const _hoisted_8 = { key: 0 }; const _hoisted_9 = { key: 0, class: "inline-save-status" }; const _hoisted_10 = { key: 1, class: "inline-save-status error" }; const _hoisted_11 = ["disabled"]; const _hoisted_12 = { key: 1, class: "settings-placeholder" }; const _hoisted_13 = { class: "profile-avatar-field" }; const _hoisted_14 = ["src"]; const _hoisted_15 = { key: 1 }; const _hoisted_16 = ["value"]; const _hoisted_17 = { class: "modal-actions" }; const _hoisted_18 = { key: 0, class: "inline-save-status" }; const _hoisted_19 = { key: 1, class: "inline-save-status error" }; const _hoisted_20 = ["disabled"]; const _hoisted_21 = { class: "avatar-preview-dialog" }; const _hoisted_22 = { class: "avatar-preview-actions" }; const _hoisted_23 = ["src"]; const _hoisted_24 = { class: "modal-panel avatar-cropper-panel" }; const _hoisted_25 = { class: "avatar-cropper-header-actions" }; const _hoisted_26 = ["disabled"]; const _hoisted_27 = { class: "avatar-cropper-layout" }; const _hoisted_28 = { key: 0, class: "avatar-cropper-placeholder" }; const _hoisted_29 = { class: "avatar-cropper-controls" }; const _hoisted_30 = { class: "avatar-cropper-tools" }; const _hoisted_31 = { class: "avatar-cropper-preview" }; const _hoisted_32 = { key: 0, class: "inline-save-status error" }; const _hoisted_33 = ["disabled"]; const _hoisted_34 = ["disabled"]; const CROP_OUTPUT_SIZE = 512; /* harmony default export */ __webpack_exports__.A = ({ __name: 'NavigationRail', setup(__props) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_6__/* .useSessionStore */ .B)(); const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_7__/* .useNavigationStore */ .l)(); const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_8__/* .useContactStore */ .p)(); const settingsItems = [{ key: 'notifications', label: '通知设置' }, { key: 'password', label: '更改密码' }, { key: 'wallet', label: '钱包管理' }, { key: 'language', label: '切换语言' }, { key: 'feedback', label: '问题反馈' }]; const initials = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .computed */ .EW)(() => (session.displayName || session.userId || 'Q').slice(0, 1).toUpperCase()); const settingsOpen = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(false); const settingsSection = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)('password'); const passwordSaving = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(false); const settingsNotice = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const settingsError = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const profileOpen = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(false); const profileSaving = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(false); const profileNotice = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const profileError = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const profileFile = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(null); const profilePreview = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(''); const portraitInput = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(null); const cropperCanvas = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(null); const cropperPreviewCanvas = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)(null); const profileDraft = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .ref */ .KR)({ displayName: '' }); const passwordDraft = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .reactive */ .Kh)({ oldPassword: '', newPassword: '', confirmPassword: '' }); const currentAvatarUrl = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .computed */ .EW)(() => profilePreview.value || session.portrait || ''); const activeSettingsItem = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .computed */ .EW)(() => settingsItems.find(item => item.key === settingsSection.value) || settingsItems[0]); const avatarPreviewViewer = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .reactive */ .Kh)({ open: false, url: '', scale: 1, offsetX: 0, offsetY: 0, dragging: false, dragStartX: 0, dragStartY: 0, dragOffsetX: 0, dragOffsetY: 0 }); const avatarCropper = (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .reactive */ .Kh)({ open: false, loaded: false, busy: false, error: '', objectUrl: '', fileName: 'avatar.jpg', image: null, baseScale: 1, scale: 1, rotation: 0, offsetX: 0, offsetY: 0, dragging: false, dragStartX: 0, dragStartY: 0, dragOffsetX: 0, dragOffsetY: 0 }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_9__/* .useAutoDismiss */ .R)(() => settingsError.value || settingsNotice.value, value => { if ((settingsError.value || settingsNotice.value) === value) { settingsError.value = ''; settingsNotice.value = ''; } }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_9__/* .useAutoDismiss */ .R)(() => profileError.value || profileNotice.value, value => { if ((profileError.value || profileNotice.value) === value) { profileError.value = ''; profileNotice.value = ''; } }); (0,_composables_useAutoDismiss__WEBPACK_IMPORTED_MODULE_9__/* .useAutoDismiss */ .R)(() => avatarCropper.error, value => { if (avatarCropper.error === value) avatarCropper.error = ''; }); const avatarPreviewStyle = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .computed */ .EW)(() => ({ transform: `translate3d(${avatarPreviewViewer.offsetX}px, ${avatarPreviewViewer.offsetY}px, 0) scale(${avatarPreviewViewer.scale})` })); (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .onMounted */ .sV)(() => { session.refreshProfile(); window.addEventListener('resize', drawAvatarCropper); }); (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .onBeforeUnmount */ .xo)(() => { revokeProfilePreview(); closeAvatarCropper(); window.removeEventListener('resize', drawAvatarCropper); }); function showContacts() { navigation.showContacts(); contacts.refreshContacts(); } function clearProfileFeedback() { profileNotice.value = ''; profileError.value = ''; } function clearSettingsFeedback() { settingsNotice.value = ''; settingsError.value = ''; } function resetPasswordDraft() { passwordDraft.oldPassword = ''; passwordDraft.newPassword = ''; passwordDraft.confirmPassword = ''; } function openSettings() { settingsOpen.value = true; settingsSection.value = 'password'; clearSettingsFeedback(); } function closeSettings() { if (passwordSaving.value) { return; } settingsOpen.value = false; clearSettingsFeedback(); resetPasswordDraft(); } function selectSettingsSection(section) { settingsSection.value = section; clearSettingsFeedback(); } function revokeProfilePreview() { if (profilePreview.value) { URL.revokeObjectURL(profilePreview.value); profilePreview.value = ''; } } function revokeCropperObjectUrl() { if (avatarCropper.objectUrl) { URL.revokeObjectURL(avatarCropper.objectUrl); avatarCropper.objectUrl = ''; } } async function openProfileEditor() { profileOpen.value = true; clearProfileFeedback(); profileDraft.value.displayName = session.displayName || session.userId || ''; const profile = await session.refreshProfile(); if (profileOpen.value && profile) { profileDraft.value.displayName = session.displayName || session.userId || ''; } } function closeProfileEditor() { profileOpen.value = false; profileFile.value = null; clearProfileFeedback(); revokeProfilePreview(); closeAvatarPreview(); closeAvatarCropper(); } function selectPortrait(event) { const file = event.target.files?.[0] || null; event.target.value = ''; clearProfileFeedback(); if (file) { openAvatarCropper(file); } } function choosePortraitFile() { portraitInput.value?.click(); } function openAvatarPreview() { if (!currentAvatarUrl.value) { return; } avatarPreviewViewer.open = true; avatarPreviewViewer.url = currentAvatarUrl.value; resetAvatarPreview(); } function closeAvatarPreview() { avatarPreviewViewer.open = false; avatarPreviewViewer.dragging = false; } function resetAvatarPreview() { avatarPreviewViewer.scale = 1; avatarPreviewViewer.offsetX = 0; avatarPreviewViewer.offsetY = 0; } function zoomAvatarPreview(factor) { avatarPreviewViewer.scale = Math.max(0.5, Math.min(6, Number((avatarPreviewViewer.scale * factor).toFixed(2)))); if (avatarPreviewViewer.scale <= 1) { avatarPreviewViewer.offsetX = 0; avatarPreviewViewer.offsetY = 0; } } function handleAvatarPreviewWheel(event) { zoomAvatarPreview(event.deltaY < 0 ? 1.12 : 1 / 1.12); } function startAvatarPreviewDrag(event) { if (avatarPreviewViewer.scale <= 1) { return; } avatarPreviewViewer.dragging = true; avatarPreviewViewer.dragStartX = event.clientX; avatarPreviewViewer.dragStartY = event.clientY; avatarPreviewViewer.dragOffsetX = avatarPreviewViewer.offsetX; avatarPreviewViewer.dragOffsetY = avatarPreviewViewer.offsetY; event.currentTarget.setPointerCapture?.(event.pointerId); } function moveAvatarPreviewDrag(event) { if (!avatarPreviewViewer.dragging) { return; } avatarPreviewViewer.offsetX = avatarPreviewViewer.dragOffsetX + event.clientX - avatarPreviewViewer.dragStartX; avatarPreviewViewer.offsetY = avatarPreviewViewer.dragOffsetY + event.clientY - avatarPreviewViewer.dragStartY; } function stopAvatarPreviewDrag() { avatarPreviewViewer.dragging = false; } function dropPortrait(event) { const file = Array.from(event.dataTransfer?.files || []).find(item => item.type.startsWith('image/')); if (file) { clearProfileFeedback(); openAvatarCropper(file); } } function cropperStageSize() { const canvas = cropperCanvas.value; const rect = canvas?.getBoundingClientRect(); const width = Math.max(280, Math.round(rect?.width || 360)); const height = Math.max(280, Math.round(rect?.height || 360)); return { width, height }; } function cropperBoxSize() { const { width, height } = cropperStageSize(); return Math.round(Math.min(width, height) * 0.74); } function rotatedImageSize() { const image = avatarCropper.image; if (!image) { return { width: 1, height: 1 }; } const quarterTurn = Math.abs(avatarCropper.rotation % 180) === 90; return { width: quarterTurn ? image.naturalHeight : image.naturalWidth, height: quarterTurn ? image.naturalWidth : image.naturalHeight }; } function clampCropperOffset() { const cropSize = cropperBoxSize(); const rotated = rotatedImageSize(); const scaledWidth = rotated.width * avatarCropper.scale; const scaledHeight = rotated.height * avatarCropper.scale; const maxX = Math.max(0, (scaledWidth - cropSize) / 2); const maxY = Math.max(0, (scaledHeight - cropSize) / 2); avatarCropper.offsetX = Math.max(-maxX, Math.min(maxX, avatarCropper.offsetX)); avatarCropper.offsetY = Math.max(-maxY, Math.min(maxY, avatarCropper.offsetY)); } function updateCropperBaseScale() { const cropSize = cropperBoxSize(); const rotated = rotatedImageSize(); avatarCropper.baseScale = Math.max(cropSize / rotated.width, cropSize / rotated.height); avatarCropper.scale = Math.max(avatarCropper.baseScale, avatarCropper.scale || avatarCropper.baseScale); } function drawCanvasImage(canvas, width, height, outputScale = 1, cropOnly = false) { const image = avatarCropper.image; if (!canvas || !image) { return; } const dpr = cropOnly ? 1 : window.devicePixelRatio || 1; canvas.width = Math.round(width * dpr); canvas.height = Math.round(height * dpr); const context = canvas.getContext('2d'); context.setTransform(dpr, 0, 0, dpr, 0, 0); context.clearRect(0, 0, width, height); context.fillStyle = '#eef4f7'; context.fillRect(0, 0, width, height); context.save(); context.translate(width / 2 + avatarCropper.offsetX * outputScale, height / 2 + avatarCropper.offsetY * outputScale); context.rotate(avatarCropper.rotation * Math.PI / 180); context.scale(avatarCropper.scale * outputScale, avatarCropper.scale * outputScale); context.drawImage(image, -image.naturalWidth / 2, -image.naturalHeight / 2); context.restore(); if (!cropOnly) { const cropSize = cropperBoxSize(); context.save(); context.fillStyle = 'rgba(10, 18, 30, 0.42)'; context.beginPath(); context.rect(0, 0, width, height); context.rect((width - cropSize) / 2, (height - cropSize) / 2, cropSize, cropSize); context.fill('evenodd'); context.restore(); } } function drawAvatarCropper() { if (!avatarCropper.open || !avatarCropper.loaded) { return; } clampCropperOffset(); const { width, height } = cropperStageSize(); drawCanvasImage(cropperCanvas.value, width, height); const previewCanvas = cropperPreviewCanvas.value; if (previewCanvas) { drawCanvasImage(previewCanvas, 108, 108, 108 / cropperBoxSize(), true); } } function resetCropperTransform() { if (!avatarCropper.image) { return; } avatarCropper.rotation = 0; avatarCropper.offsetX = 0; avatarCropper.offsetY = 0; updateCropperBaseScale(); avatarCropper.scale = avatarCropper.baseScale; drawAvatarCropper(); } function openAvatarCropper(file) { if (!file.type.startsWith('image/')) { profileError.value = '请选择图片文件'; return; } if (file.size > 8 * 1024 * 1024) { profileError.value = '头像图片不能超过8MB'; return; } closeAvatarCropper(); avatarCropper.open = true; avatarCropper.loaded = false; avatarCropper.error = ''; avatarCropper.fileName = file.name || 'avatar.jpg'; avatarCropper.objectUrl = URL.createObjectURL(file); const image = new Image(); image.onload = () => { avatarCropper.image = image; avatarCropper.loaded = true; (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .nextTick */ .dY)(resetCropperTransform); }; image.onerror = () => { avatarCropper.error = '图片加载失败'; avatarCropper.loaded = false; }; image.src = avatarCropper.objectUrl; } function closeAvatarCropper() { avatarCropper.open = false; avatarCropper.loaded = false; avatarCropper.busy = false; avatarCropper.error = ''; avatarCropper.image = null; avatarCropper.dragging = false; revokeCropperObjectUrl(); } function zoomCropper(factor) { if (!avatarCropper.loaded) { return; } updateCropperBaseScale(); avatarCropper.scale = Math.max(avatarCropper.baseScale, Math.min(avatarCropper.baseScale * 6, avatarCropper.scale * factor)); drawAvatarCropper(); } function rotateCropper(degrees) { if (!avatarCropper.loaded) { return; } avatarCropper.rotation = (avatarCropper.rotation + degrees + 360) % 360; updateCropperBaseScale(); clampCropperOffset(); drawAvatarCropper(); } function handleCropperWheel(event) { zoomCropper(event.deltaY < 0 ? 1.08 : 1 / 1.08); } function startCropperDrag(event) { if (!avatarCropper.loaded) { return; } avatarCropper.dragging = true; avatarCropper.dragStartX = event.clientX; avatarCropper.dragStartY = event.clientY; avatarCropper.dragOffsetX = avatarCropper.offsetX; avatarCropper.dragOffsetY = avatarCropper.offsetY; event.currentTarget.setPointerCapture?.(event.pointerId); } function moveCropperDrag(event) { if (!avatarCropper.dragging) { return; } avatarCropper.offsetX = avatarCropper.dragOffsetX + event.clientX - avatarCropper.dragStartX; avatarCropper.offsetY = avatarCropper.dragOffsetY + event.clientY - avatarCropper.dragStartY; drawAvatarCropper(); } function stopCropperDrag() { avatarCropper.dragging = false; } function canvasToBlob(canvas, type = 'image/jpeg', quality = 0.9) { return new Promise((resolve, reject) => { canvas.toBlob(blob => { if (blob) { resolve(blob); } else { reject(new Error('头像裁切失败')); } }, type, quality); }); } async function confirmAvatarCrop() { if (!avatarCropper.loaded || avatarCropper.busy) { return; } avatarCropper.busy = true; avatarCropper.error = ''; try { const outputCanvas = document.createElement('canvas'); drawCanvasImage(outputCanvas, CROP_OUTPUT_SIZE, CROP_OUTPUT_SIZE, CROP_OUTPUT_SIZE / cropperBoxSize(), true); const blob = await canvasToBlob(outputCanvas); const fileName = avatarCropper.fileName.replace(/\.[^.]+$/, '') || 'avatar'; const croppedFile = new File([blob], `${fileName}.jpg`, { type: 'image/jpeg' }); profileFile.value = croppedFile; revokeProfilePreview(); profilePreview.value = URL.createObjectURL(croppedFile); closeAvatarCropper(); } catch (error) { avatarCropper.error = error.message || '头像裁切失败'; } finally { avatarCropper.busy = false; } } async function saveProfile() { if (profileSaving.value || !profileDraft.value.displayName) { return; } clearProfileFeedback(); profileSaving.value = true; try { await session.saveProfile({ displayName: profileDraft.value.displayName, portraitFile: profileFile.value }); profileFile.value = null; revokeProfilePreview(); profileNotice.value = '资料已保存'; contacts.refreshContacts({ force: true }); } catch (error) { profileError.value = error.message || '资料保存失败'; } finally { profileSaving.value = false; } } async function savePassword() { if (passwordSaving.value) { return; } clearSettingsFeedback(); const oldPassword = passwordDraft.oldPassword; const newPassword = passwordDraft.newPassword; const confirmPassword = passwordDraft.confirmPassword; if (!oldPassword || !newPassword || !confirmPassword) { settingsError.value = '请填写完整密码'; return; } if (newPassword !== confirmPassword) { settingsError.value = '两次输入的新密码不一致'; return; } if (oldPassword === newPassword) { settingsError.value = '新密码不能和当前密码相同'; return; } passwordSaving.value = true; try { await session.changePassword({ oldPassword, newPassword }); resetPasswordDraft(); settingsNotice.value = '密码已更新'; } catch (error) { settingsError.value = error.message || '密码修改失败'; } finally { passwordSaving.value = false; } } function logout() { closeSettings(); contacts.clearContacts(); session.logout(); } return (_ctx, _cache) => { return (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_3__/* .Fragment */ .FK, null, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("aside", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "rail-avatar rail-avatar-button", title: "编辑个人资料", onClick: openProfileEditor }, [(0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(session).portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("img", { key: 0, src: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(session).portrait, alt: "", onError: _cache[0] || (_cache[0] = $event => (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(_services_mediaProxy__WEBPACK_IMPORTED_MODULE_10__/* .useImageProxyFallback */ .TJ)($event, (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(session).portrait)) }, null, 40, _hoisted_2)) : ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(initials.value), 1))]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["rail-button", { active: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).section === 'messages' }]), title: "消息", onClick: _cache[1] || (_cache[1] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).showMessages && (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).showMessages(...args)) }, "💬", 2), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["rail-button", { active: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).section === 'contacts' }]), title: "联系人", onClick: showContacts }, "👥", 2), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["rail-button", { active: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).section === 'favorites' }]), title: "收藏", onClick: _cache[2] || (_cache[2] = (...args) => (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).showFavorites && (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(navigation).showFavorites(...args)) }, "☆", 2), _cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", { class: "rail-spacer" }, null, -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: "rail-button", title: "设置", "aria-label": "设置", onClick: openSettings }, _cache[14] || (_cache[14] = [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("svg", { viewBox: "0 0 24 24", "aria-hidden": "true" }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("path", { d: "M12 8.2a3.8 3.8 0 1 1 0 7.6 3.8 3.8 0 0 1 0-7.6Z" }), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("path", { d: "M19.4 13.6a7.8 7.8 0 0 0 .1-1.6l1.7-1.3-1.7-3-2 .8a8 8 0 0 0-1.4-.8L15.8 5h-3.5l-.3 2.1a8 8 0 0 0-1.5.8l-1.9-.8-1.8 3 1.7 1.3a7.8 7.8 0 0 0 0 1.6l-1.7 1.3 1.8 3 1.9-.8c.5.4 1 .7 1.5.8l.3 2.1h3.5l.3-2.1c.5-.2 1-.5 1.4-.8l2 .8 1.7-3-1.8-1.3Z" })], -1)])), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: "rail-button rail-logout-button", title: "退出登录", "aria-label": "退出登录", onClick: logout }, _cache[15] || (_cache[15] = [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createStaticVNode */ .Fv)("", 1)]))]), settingsOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("div", { key: 0, class: "modal-backdrop settings-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(closeSettings, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("section", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("header", null, [_cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("strong", null, "设置", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeSettings }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("nav", _hoisted_6, [((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)(vue__WEBPACK_IMPORTED_MODULE_3__/* .Fragment */ .FK, null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .renderList */ .pI)(settingsItems, item => { return (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { key: item.key, type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)({ active: settingsSection.value === item.key }), onClick: $event => selectSettingsSection(item.key) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(item.label), 1), item.key !== 'password' ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("small", _hoisted_8, "稍后开放")) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true)], 10, _hoisted_7); }), 64))]), settingsSection.value === 'password' ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("form", { key: 0, class: "settings-password-form", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(savePassword, ["prevent"]) }, [_cache[21] || (_cache[21] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("h3", null, "更改密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("label", null, [_cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, "当前密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => passwordDraft.oldPassword = $event), type: "password", autocomplete: "current-password" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_2__/* .vModelText */ .Jo, passwordDraft.oldPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("label", null, [_cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, "新密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => passwordDraft.newPassword = $event), type: "password", autocomplete: "new-password" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_2__/* .vModelText */ .Jo, passwordDraft.newPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("label", null, [_cache[20] || (_cache[20] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, "确认新密码", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => passwordDraft.confirmPassword = $event), type: "password", autocomplete: "new-password" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_2__/* .vModelText */ .Jo, passwordDraft.confirmPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("footer", null, [settingsNotice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(settingsNotice.value), 1)) : settingsError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(settingsError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "submit", class: "primary-inline-action", disabled: passwordSaving.value }, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(passwordSaving.value ? '保存中...' : '保存密码'), 9, _hoisted_11)])], 32)) : ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("section", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("h3", null, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(activeSettingsItem.value?.label || '设置'), 1), _cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("p", null, "该功能稍后开放。", -1))]))])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), profileOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("div", { key: 1, class: "modal-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(closeProfileEditor, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("form", { class: "modal-panel profile-edit-panel", onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(saveProfile, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("header", null, [_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("strong", null, "个人资料", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeProfileEditor }, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["profile-avatar-preview", { clickable: currentAvatarUrl.value }]), title: "预览头像", onClick: openAvatarPreview }, [currentAvatarUrl.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("img", { key: 0, src: currentAvatarUrl.value, alt: "" }, null, 8, _hoisted_14)) : ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_15, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(initials.value), 1))], 2), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action profile-avatar-change-button", onClick: choosePortraitFile }, "更换头像"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { ref_key: "portraitInput", ref: portraitInput, type: "file", accept: "image/*", onChange: selectPortrait }, null, 544)]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("label", null, [_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, "昵称", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .withDirectives */ .bo)((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => profileDraft.value.displayName = $event), maxlength: "64", autocomplete: "off" }, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_2__/* .vModelText */ .Jo, profileDraft.value.displayName, void 0, { trim: true }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("label", null, [_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("span", null, "用户ID", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("input", { value: (0,vue__WEBPACK_IMPORTED_MODULE_4__/* .unref */ .R1)(session).userId, readonly: "" }, null, 8, _hoisted_16)]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", onClick: closeProfileEditor }, "取消"), profileNotice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_18, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(profileNotice.value), 1)) : profileError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_19, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(profileError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { class: "primary-inline-action", disabled: profileSaving.value || !profileDraft.value.displayName }, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(profileSaving.value ? '保存中...' : '保存'), 9, _hoisted_20)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), avatarPreviewViewer.open ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("div", { key: 2, class: "modal-backdrop avatar-preview-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(closeAvatarPreview, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("section", _hoisted_21, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("header", null, [_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("strong", null, "头像预览", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_22, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "缩小", onClick: _cache[7] || (_cache[7] = $event => zoomAvatarPreview(1 / 1.16)) }, "−"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "放大", onClick: _cache[8] || (_cache[8] = $event => zoomAvatarPreview(1.16)) }, "+"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "还原", onClick: resetAvatarPreview }, "1:1"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeAvatarPreview }, "×")])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", { class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["avatar-preview-stage", { dragging: avatarPreviewViewer.dragging }]), onWheel: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(handleAvatarPreviewWheel, ["prevent"]), onPointerdown: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(startAvatarPreviewDrag, ["prevent"]), onPointermove: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(moveAvatarPreviewDrag, ["prevent"]), onPointerup: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(stopAvatarPreviewDrag, ["prevent"]), onPointerleave: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(stopAvatarPreviewDrag, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("img", { src: avatarPreviewViewer.url, alt: "头像预览", style: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeStyle */ .Tr)(avatarPreviewStyle.value), draggable: "false" }, null, 12, _hoisted_23)], 34)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), avatarCropper.open ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("div", { key: 3, class: "modal-backdrop avatar-cropper-backdrop", onClick: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(closeAvatarCropper, ["self"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("section", _hoisted_24, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("header", null, [_cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("strong", null, "头像预裁切", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_25, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: avatarCropper.busy, onClick: choosePortraitFile }, "上传", 8, _hoisted_26), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "icon-button", title: "关闭", onClick: closeAvatarCropper }, "×")])]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_27, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", { class: (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .normalizeClass */ .C4)(["avatar-cropper-stage", { dragging: avatarCropper.dragging }]), onWheel: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(handleCropperWheel, ["prevent"]), onPointerdown: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(startCropperDrag, ["prevent"]), onPointermove: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(moveCropperDrag, ["prevent"]), onPointerup: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(stopCropperDrag, ["prevent"]), onPointerleave: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(stopCropperDrag, ["prevent"]), onDragover: _cache[9] || (_cache[9] = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(() => {}, ["prevent"])), onDrop: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .withModifiers */ .D$)(dropPortrait, ["prevent"]) }, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("canvas", { ref_key: "cropperCanvas", ref: cropperCanvas }, null, 512), _cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", { class: "avatar-cropper-mask", "aria-hidden": "true" }, null, -1)), _cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", { class: "avatar-cropper-box", "aria-hidden": "true" }, null, -1)), !avatarCropper.loaded ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("div", _hoisted_28, "图片加载中")) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true)], 34), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("aside", _hoisted_29, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_30, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "左旋90度", onClick: _cache[10] || (_cache[10] = $event => rotateCropper(-90)) }, "↶90°"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "右旋90度", onClick: _cache[11] || (_cache[11] = $event => rotateCropper(90)) }, "↷90°"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "放大", onClick: _cache[12] || (_cache[12] = $event => zoomCropper(1.12)) }, "+"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "缩小", onClick: _cache[13] || (_cache[13] = $event => zoomCropper(1 / 1.12)) }, "−"), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", title: "重置", onClick: resetCropperTransform }, "重置")]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("div", _hoisted_31, [(0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("canvas", { ref_key: "cropperPreviewCanvas", ref: cropperPreviewCanvas }, null, 512)]), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("footer", null, [avatarCropper.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_3__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementBlock */ .CE)("span", _hoisted_32, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(avatarCropper.error), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "ghost-inline-action", disabled: avatarCropper.busy, onClick: closeAvatarCropper }, "取消", 8, _hoisted_33), (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createElementVNode */ .Lk)("button", { type: "button", class: "primary-inline-action", disabled: avatarCropper.busy || !avatarCropper.loaded, onClick: confirmAvatarCrop }, (0,vue__WEBPACK_IMPORTED_MODULE_5__/* .toDisplayString */ .v_)(avatarCropper.busy ? '处理中...' : '确认裁切'), 9, _hoisted_34)])])])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .createCommentVNode */ .Q3)("", true)], 64); }; } }); /***/ }), /***/ 6384: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ R: function() { return /* binding */ useAutoDismiss; } /* harmony export */ }); /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6768); function useAutoDismiss(source, clear, delay = 3000) { let timer = null; (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .watch */ .wB)(source, value => { window.clearTimeout(timer); timer = null; if (!value) return; const currentValue = value; timer = window.setTimeout(() => { clear(currentValue); timer = null; }, delay); }, { flush: 'post' }); (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .onBeforeUnmount */ .xo)(() => window.clearTimeout(timer)); } /***/ }), /***/ 2169: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { const currentHost = window.location.hostname || '127.0.0.1'; const runtimeConfig = window.JC_WEB_IM_CONFIG || {}; const appServerOrigin = `${window.location.protocol}//${currentHost}:8888`; const qrAppServerOrigin = `${window.location.protocol}//${currentHost}:18888`; const adminServerOrigin = `${window.location.protocol}//${currentHost}:8024`; const appConfig = { appName: 'Web IM', adminServer: runtimeConfig.adminServer || undefined || adminServerOrigin, appServer: runtimeConfig.appServer || undefined || appServerOrigin, qrAppServer: runtimeConfig.qrAppServer || undefined || qrAppServerOrigin, platformConfigApi: runtimeConfig.platformConfigApi || undefined || ( false ? 0 : '/api/platform_config.php'), registerConfigApi: runtimeConfig.registerConfigApi || undefined || `${adminServerOrigin}/api/register-config`, registerPhoneExistsApi: runtimeConfig.registerPhoneExistsApi || undefined || `${adminServerOrigin}/api/register-phone-exists`, contactsApi: runtimeConfig.contactsApi || undefined || ( false ? 0 : '/api/contacts.php'), updateAliasApi: runtimeConfig.updateAliasApi || undefined || ( false ? 0 : '/api/update_alias.php'), addContactApi: runtimeConfig.addContactApi || undefined || ( false ? 0 : '/api/add_contact.php'), conversationActionsApi: runtimeConfig.conversationActionsApi || undefined || ( false ? 0 : '/api/conversation_actions.php'), sendMessageApi: runtimeConfig.sendMessageApi || undefined || ( false ? 0 : '/api/send_message.php'), messageActionApi: runtimeConfig.messageActionApi || undefined || ( false ? 0 : '/api/message_action.php'), messageDetailApi: runtimeConfig.messageDetailApi || undefined || ( false ? 0 : '/api/message_detail.php'), messagesApi: runtimeConfig.messagesApi || undefined || ( false ? 0 : '/api/messages.php'), profileApi: runtimeConfig.profileApi || undefined || ( false ? 0 : '/api/profile.php'), changePasswordApi: runtimeConfig.changePasswordApi || undefined || `${appServerOrigin}/auth/changePassword`, logoutApi: runtimeConfig.logoutApi || undefined || `${appServerOrigin}/auth/logout`, imServerHost: runtimeConfig.imServerHost || undefined || currentHost, imRoutePort: Number(runtimeConfig.imRoutePort || undefined || 18000), useWss: runtimeConfig.useWss ?? undefined === 'true', wsPath: runtimeConfig.wsPath || undefined || '/ws', wsUrl: runtimeConfig.wsUrl || undefined || '', sdkMode: runtimeConfig.sdkMode || undefined || 'http', syncIntervalMs: Number(runtimeConfig.syncIntervalMs || undefined || 300), sseEnabled: runtimeConfig.sseEnabled ?? undefined === 'true', sseTicketApi: runtimeConfig.sseTicketApi || undefined || '/api/sse_ticket.php', sseUrl: runtimeConfig.sseUrl || undefined || '/ws-events', platform: 5, clientIdStorageKey: 'qmt-web-im-client-id', authTokenStoragePrefix: 'qmt-web-im-auth-token-' }; /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "U", 0, /* binding */ appConfig /* harmony export */ ]); /***/ }), /***/ 1406: /***/ (function(__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) { /* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5130); /* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2261); /* harmony import */ var _App_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7067); (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .createApp */ .Ef)(_App_vue__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A).use((0,pinia__WEBPACK_IMPORTED_MODULE_1__/* .createPinia */ .Ey)()).mount('#app'); /***/ }), /***/ 9311: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Ln: function() { return /* binding */ appServerPost; }, /* harmony export */ Pd: function() { return /* binding */ getStoredAppAuth; }, /* harmony export */ eG: function() { return /* binding */ persistAppAuth; }, /* harmony export */ u$: function() { return /* binding */ clearStoredAppAuth; } /* harmony export */ }); /* unused harmony exports appServerRequest, appServerGet */ /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9577); /* harmony import */ var core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6632); /* harmony import */ var core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4226); /* harmony import */ var core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9486); /* harmony import */ var core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(456); /* harmony import */ var core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(4979); /* harmony import */ var core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(2387); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2169); const AES_KEY = 'xczx2026!@#secKe'; const ENCRYPTION_EXCLUDE_PATHS = ['/avatar/', '/f/', '/amr2mp3', '/appVersion/check']; const AUTH_STORAGE_KEY = 'qmt-web-im-app-auth-v1'; const AUTH_ERROR_CODE = 13; const REFRESH_ERROR_CODE = 20045; let importedCryptoKeyPromise = null; let refreshPromise = null; function storageScope() { return _config__WEBPACK_IMPORTED_MODULE_9__/* .appConfig */ .U.appServer || ''; } function readAuthStore() { try { return JSON.parse(localStorage.getItem(AUTH_STORAGE_KEY) || '{}'); } catch (error) { return {}; } } function writeAuthStore(store) { localStorage.setItem(AUTH_STORAGE_KEY, JSON.stringify(store)); } function normalizeAuthBundle(bundle = {}) { const accessToken = String(bundle.accessToken || '').trim(); const refreshToken = String(bundle.refreshToken || '').trim(); if (!accessToken || !refreshToken) { return null; } return { accessToken, refreshToken, tokenType: String(bundle.tokenType || 'Bearer').trim() || 'Bearer', accessTokenExpireIn: Number(bundle.accessTokenExpireIn || 0) || 0, accessTokenExpireAt: Number(bundle.accessTokenExpireAt || 0) || 0, refreshTokenExpireIn: Number(bundle.refreshTokenExpireIn || 0) || 0, refreshTokenExpireAt: Number(bundle.refreshTokenExpireAt || 0) || 0 }; } function getStoredAppAuth() { const store = readAuthStore(); return normalizeAuthBundle(store[storageScope()]); } function persistAppAuth(bundle) { const normalized = normalizeAuthBundle(bundle); const store = readAuthStore(); if (!normalized) { delete store[storageScope()]; writeAuthStore(store); return null; } store[storageScope()] = normalized; writeAuthStore(store); return normalized; } function clearStoredAppAuth() { persistAppAuth(null); } function hasFormData(value) { return typeof FormData !== 'undefined' && value instanceof FormData; } function absoluteUrl(url) { return new URL(url, window.location.origin); } function shouldEncrypt(url) { const pathname = absoluteUrl(url).pathname; return !ENCRYPTION_EXCLUDE_PATHS.some(path => pathname === path || pathname.startsWith(path)); } function shouldAttachAuth(config) { return !config.skipAuth; } function textEncoder() { return new TextEncoder(); } function textDecoder() { return new TextDecoder(); } function bytesToBase64(bytes) { let binary = ''; bytes.forEach(byte => { binary += String.fromCharCode(byte); }); return btoa(binary); } function base64ToBytes(base64) { const binary = atob(base64); const bytes = new Uint8Array(binary.length); for (let index = 0; index < binary.length; index += 1) { bytes[index] = binary.charCodeAt(index); } return bytes; } async function getCryptoKey() { if (!importedCryptoKeyPromise) { importedCryptoKeyPromise = window.crypto.subtle.importKey('raw', textEncoder().encode(AES_KEY), { name: 'AES-CBC' }, false, ['encrypt', 'decrypt']); } return importedCryptoKeyPromise; } async function encryptPayload(plainText) { const iv = window.crypto.getRandomValues(new Uint8Array(16)); const key = await getCryptoKey(); const encrypted = await window.crypto.subtle.encrypt({ name: 'AES-CBC', iv }, key, textEncoder().encode(plainText)); return `${bytesToBase64(iv)}:${bytesToBase64(new Uint8Array(encrypted))}`; } async function decryptPayload(cipherText) { const [ivBase64, encryptedBase64] = String(cipherText || '').split(':', 2); if (!ivBase64 || !encryptedBase64) { throw new Error('Encrypted payload format is invalid'); } const key = await getCryptoKey(); const decrypted = await window.crypto.subtle.decrypt({ name: 'AES-CBC', iv: base64ToBytes(ivBase64) }, key, base64ToBytes(encryptedBase64)); return textDecoder().decode(decrypted); } function normalizeBusinessResponse(payload) { if (payload && typeof payload === 'object' && !Array.isArray(payload)) { return payload; } return { code: 0, message: 'success', data: payload }; } async function decodeResponsePayload(response) { const encrypted = String(response.headers?.['x-encrypted'] || '').toLowerCase() === 'true'; if (encrypted && typeof response.data === 'string') { const plainText = await decryptPayload(response.data); response.data = normalizeBusinessResponse(JSON.parse(plainText)); return response; } response.data = normalizeBusinessResponse(response.data); return response; } const client = axios__WEBPACK_IMPORTED_MODULE_8__/* ["default"] */ .A.create({ withCredentials: false }); client.interceptors.request.use(async config => { const nextConfig = { ...config }; const url = absoluteUrl(nextConfig.url || '').toString(); if (shouldAttachAuth(nextConfig)) { const auth = getStoredAppAuth(); if (auth?.accessToken) { nextConfig.headers = { ...(nextConfig.headers || {}), Authorization: `${auth.tokenType || 'Bearer'} ${auth.accessToken}` }; } } if (!hasFormData(nextConfig.data) && nextConfig.method?.toLowerCase() !== 'get' && shouldEncrypt(url)) { const plainBody = JSON.stringify(nextConfig.data ?? {}); nextConfig.data = await encryptPayload(plainBody); nextConfig.headers = { ...(nextConfig.headers || {}), 'Content-Type': 'text/plain;charset=UTF-8', 'X-Timestamp': `${Math.floor(Date.now() / 1000)}` }; } return nextConfig; }); client.interceptors.response.use(async response => decodeResponsePayload(response)); async function refreshAccessToken() { if (refreshPromise) { return refreshPromise; } const auth = getStoredAppAuth(); if (!auth?.refreshToken) { clearStoredAppAuth(); throw new Error('登录状态已失效,请重新登录'); } refreshPromise = client.post(`${_config__WEBPACK_IMPORTED_MODULE_9__/* .appConfig */ .U.appServer}/auth/refreshToken`, { refreshToken: auth.refreshToken }, { skipAuth: true }).then(response => { const payload = response.data || {}; if (Number(payload.code) !== 0 || !payload.data) { if (Number(payload.code) === REFRESH_ERROR_CODE) { clearStoredAppAuth(); } throw new Error(payload.message || '刷新登录状态失败'); } persistAppAuth(payload.data); return payload.data; }).finally(() => { refreshPromise = null; }); return refreshPromise; } async function request(config) { const response = await client.request(config); const payload = response.data || {}; if (Number(payload.code) === AUTH_ERROR_CODE && shouldAttachAuth(config) && !config._retriedAfterRefresh) { await refreshAccessToken(); return request({ ...config, _retriedAfterRefresh: true }); } return response; } async function appServerRequest(config) { return request(config); } async function appServerGet(url, config = {}) { return request({ ...config, method: 'get', url }); } async function appServerPost(url, data = {}, config = {}) { return request({ ...config, method: 'post', url, data }); } /***/ }), /***/ 4355: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ u: function() { return /* binding */ DocumentedHttpImClient; } /* harmony export */ }); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2169); /* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5099); /* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2387); /* harmony import */ var _appServerClient__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9311); function inferAccountType(account) { return String(account || '').includes('@') ? 2 : 1; } function unwrapData(response) { return response.data?.data ?? response.data?.result ?? null; } function unwrapMessage(response, fallback) { return response.data?.message || response.data?.msg || fallback; } class DocumentedHttpImClient extends _httpImClient__WEBPACK_IMPORTED_MODULE_2__/* .HttpImClient */ .Y { unsupported(feature) { throw new Error(`当前对接文档未提供“${feature}”接口,已禁用旧本地代理链路`); } async loginWithPassword(account, password, type = inferAccountType(account)) { const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .appServerPost */ .Ln)(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.appServer}/auth/login_pwd`, { type, number: account, password, platform: _config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.platform, clientId: this.getClientId() }, { skipAuth: true }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '登录失败')); } (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .persistAppAuth */ .eG)(unwrapData(response)); return unwrapData(response); } async requestAuthCode(email) { const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .appServerPost */ .Ln)(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.appServer}/auth/sendEmailCode`, { email }, { skipAuth: true }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '验证码发送失败')); } return unwrapData(response); } async loginWithCode(account, code) { void account; void code; throw new Error('接口文档未提供验证码登录接口,请使用密码登录'); } async register({ type, number, code = '', password, invitationCode = '' }) { const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .appServerPost */ .Ln)(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.appServer}/auth/register`, { type, number, code, password, clientId: this.getClientId(), platform: _config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.platform, invitationCode }, { skipAuth: true }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '注册失败')); } (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .persistAppAuth */ .eG)(unwrapData(response)); return unwrapData(response); } async createPcSession(userId = '') { const response = await axios__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A.post(`${_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.qrAppServer}/pc_session`, { flag: 1, device_name: 'Web IM', userId, clientId: this.getClientId(), platform: _config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.platform }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '二维码登录会话创建失败')); } return unwrapData(response) || {}; } async loginWithPcSession(token) { const url = `${_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.qrAppServer}/session_login/${encodeURIComponent(token)}`; let response; try { response = await axios__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A.post(url, null, { withCredentials: false }); } catch (postError) { response = await axios__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A.get(url, { withCredentials: false }); } this.persistAppToken(url, response); const payload = response.data || {}; const result = payload.result ?? payload.data ?? null; if (Number(payload.code) === 0 && result) { (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .persistAppAuth */ .eG)(result); } if ([0, 8, 9, 10, 13, 18, 20042].includes(Number(payload.code))) { return { ...payload, data: result }; } throw new Error(payload.message || '扫码登录失败'); } async changePassword({ oldPassword, newPassword }) { const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .appServerPost */ .Ln)(_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.changePasswordApi, { oldPassword, newPassword }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '密码修改失败')); } return true; } async resetPasswordWithCode({ mobile, resetCode, newPassword }) { void mobile; void resetCode; void newPassword; throw new Error('接口文档未提供重置密码接口,请联系服务端确认流程'); } async logout() { const auth = (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .getStoredAppAuth */ .Pd)(); if (!auth?.refreshToken) { (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .clearStoredAppAuth */ .u$)(); return true; } try { const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .appServerPost */ .Ln)(_config__WEBPACK_IMPORTED_MODULE_1__/* .appConfig */ .U.logoutApi, { refreshToken: auth.refreshToken }); if (response.data?.code !== 0) { throw new Error(unwrapMessage(response, '退出登录失败')); } } finally { (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__/* .clearStoredAppAuth */ .u$)(); } return true; } async fetchRemoteConversations() { return []; } async fetchRemoteMessages() { return []; } async getServerContactList() { return []; } async getProfile() { return null; } async sendTextMessage() { this.unsupported('发送消息'); } async sendAttachmentMessage() { this.unsupported('发送附件消息'); } async addContact() { this.unsupported('添加联系人'); } async updateContactAlias() { this.unsupported('联系人备注'); } async createGroup() { this.unsupported('创建群组'); } async joinGroup() { this.unsupported('加入群组'); } async broadcastMessage() { this.unsupported('群发消息'); } async getGroupDetail() { this.unsupported('群详情'); } async getGroupMembers() { this.unsupported('群成员'); } async updateGroupAlias() { this.unsupported('群备注'); } async leaveGroup() { this.unsupported('退出群组'); } async dismissGroup() { this.unsupported('解散群组'); } async transferGroup() { this.unsupported('转让群组'); } async setGroupAdmins() { this.unsupported('设置群管理员'); } async updateGroupProfile() { this.unsupported('更新群资料'); } async kickGroupMembers() { this.unsupported('移除群成员'); } async updateGroupMuteSetting() { this.unsupported('群禁言设置'); } async updateProfile() { this.unsupported('更新个人资料'); } async recallMessage() { this.unsupported('撤回消息'); } async editMessage() { this.unsupported('编辑消息'); } async getMessageDetail() { this.unsupported('消息详情'); } } /***/ }), /***/ 5099: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Y: function() { return /* binding */ HttpImClient; } /* harmony export */ }); /* unused harmony export imClient */ /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4114); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(3579); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(5367); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8__); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2731); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9__); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(7642); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(8004); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11__); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(3853); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12__); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(5876); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(2475); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14__); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(5024); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15__); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(1698); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16__); /* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(2387); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(2169); /* harmony import */ var _services_appServerClient__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(9311); const LOCAL_MESSAGE_STORAGE_KEY = 'qmt-web-im-local-messages-v2'; const LOCAL_HIDDEN_MESSAGE_STORAGE_KEY = 'qmt-web-im-hidden-messages-v1'; const LOCAL_RECALLED_MESSAGE_STORAGE_KEY = 'qmt-web-im-recalled-messages-v1'; function scopedStorageKey(baseKey, userId = '') { const scope = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer || ''}:${userId || 'anonymous'}`; return `${baseKey}:${encodeURIComponent(scope)}`; } function randomId() { if (window.crypto && window.crypto.randomUUID) { return window.crypto.randomUUID().replaceAll('-', ''); } return `${Date.now()}${Math.random().toString(16).slice(2)}`; } function readLocalMessages(userId) { try { return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_MESSAGE_STORAGE_KEY, userId)) || '{}'); } catch (error) { return {}; } } function readMessageSet(storageKey, userId) { try { return JSON.parse(localStorage.getItem(scopedStorageKey(storageKey, userId)) || '{}'); } catch (error) { return {}; } } function writeMessageSet(storageKey, messagesByConversation, userId) { localStorage.setItem(scopedStorageKey(storageKey, userId), JSON.stringify(messagesByConversation)); } function messageKeys(message) { return [message?.id, message?.messageUid].filter(Boolean).map(value => String(value)); } function hasStoredMessage(storageKey, conversationId, message, userId) { const stored = readMessageSet(storageKey, userId); const ids = new Set(stored[conversationId] || []); return messageKeys(message).some(id => ids.has(id)); } function storeMessageKeys(storageKey, conversationId, messages, userId) { const stored = readMessageSet(storageKey, userId); const ids = new Set(stored[conversationId] || []); messages.forEach(message => { messageKeys(message).forEach(id => ids.add(id)); }); stored[conversationId] = Array.from(ids); writeMessageSet(storageKey, stored, userId); } function withRecalledState(message) { return { ...message, status: 'recalled', deliveryStatus: '', recalled: true, recallStatus: '已撤回' }; } function applyLocalMessageState(conversationId, messages, userId) { return messages.filter(message => !hasStoredMessage(LOCAL_HIDDEN_MESSAGE_STORAGE_KEY, conversationId, message, userId)).map(message => { const isRecalled = Boolean(message.recalled) || message.status === 'recalled' || hasStoredMessage(LOCAL_RECALLED_MESSAGE_STORAGE_KEY, conversationId, message, userId); if (!isRecalled) { return message; } return withRecalledState(message); }); } function writeLocalMessages(messagesByConversation, userId) { localStorage.setItem(scopedStorageKey(LOCAL_MESSAGE_STORAGE_KEY, userId), JSON.stringify(messagesByConversation)); } function saveLocalMessage(message, userId) { const messagesByConversation = readLocalMessages(userId); messagesByConversation[message.conversationId] = messagesByConversation[message.conversationId] || []; const index = messagesByConversation[message.conversationId].findIndex(item => item.id === message.id); if (index >= 0) { messagesByConversation[message.conversationId].splice(index, 1, message); } else { messagesByConversation[message.conversationId].push(message); } writeLocalMessages(messagesByConversation, userId); } function mergeSyncedMessages(localMessages, remoteMessages, conversationId, userId) { const visibleLocalMessages = applyLocalMessageState(conversationId, localMessages, userId); const localByKey = new Map(); visibleLocalMessages.forEach(message => { messageKeys(message).forEach(key => { if (!localByKey.has(key)) { localByKey.set(key, message); } }); }); const visibleRemoteMessages = applyLocalMessageState(conversationId, remoteMessages, userId).map(remoteMessage => { if (!remoteMessage.recalled || String(remoteMessage.text || '').trim()) { return remoteMessage; } const localMessage = messageKeys(remoteMessage).map(key => localByKey.get(key)).find(message => message?.text && message.text !== '你撤回了一条消息'); return localMessage ? { ...remoteMessage, text: localMessage.text } : remoteMessage; }); const remoteKeys = new Set(); visibleRemoteMessages.forEach(message => { messageKeys(message).forEach(key => remoteKeys.add(key)); }); const now = Date.now(); function hasRemoteMatch(localMessage) { if (localMessage.messageUid && remoteKeys.has(localMessage.messageUid)) { return true; } return visibleRemoteMessages.some(remoteMessage => { return remoteMessage.direction === localMessage.direction && remoteMessage.text === localMessage.text && Math.abs(Number(remoteMessage.timestamp || 0) - Number(localMessage.timestamp || 0)) < 15000; }); } const pendingLocalMessages = visibleLocalMessages.filter(message => { if (message.status === 'recalled' || message.recalled) { return message.direction === 'out' && !hasRemoteMatch(message); } if (message.direction !== 'out') { return false; } if (message.status === 'sent' && message.messageUid) { return !hasRemoteMatch(message); } if (message.status === 'sent') { return !hasRemoteMatch(message) && now - Number(message.timestamp || 0) < 30000; } if (message.status === 'failed') { // Failed optimistic messages are only transient feedback. Keeping them in // localStorage forever makes an old server error reappear every time the // conversation is opened, even after later messages send successfully. return now - Number(message.timestamp || 0) < 3000; } return message.status === 'sending'; }); return [...visibleRemoteMessages, ...pendingLocalMessages].sort((a, b) => { return Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0); }); } function getTitle(value, fallback) { return value || fallback || ''; } function getUniqueEquipment(mobile, fallback) { const allowedDevices = { '18301902119': '67072d37062c4f31b1165073552933ba', '18301902116': '1777479418113eeea8e236edce', '18301902118': 'de89fb2f2a61480a8c381f6c16e28bd8', '18301902117': 'd117f480faa64145b6162107b1b49617' }; return allowedDevices[mobile] || localStorage.getItem('uniqueEquipment') || fallback; } function canUseLocalLoginFallback(response) { const message = response.data?.message || ''; return false && 0; } class HttpImClient { constructor() { this.listeners = new Map(); this.connected = false; this.currentUser = null; } getClientId() { let clientId = localStorage.getItem(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.clientIdStorageKey); if (!clientId) { clientId = randomId(); localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.clientIdStorageKey, clientId); } return clientId; } restoreClientId(clientId) { if (clientId) { localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.clientIdStorageKey, clientId); } } getSdkVersion() { return 'HTTP'; } async ensureSdk() { return true; } async loginWithPassword(mobile, password) { const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/login_pwd`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, { mobile, password, platform: _config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.platform, clientId: this.getClientId() }, { withCredentials: false }); this.persistAppToken(url, response); if (response.data?.code !== 0) { if (canUseLocalLoginFallback(response)) { return { userId: mobile, token: `local-device-pending-${Date.now()}`, displayName: mobile, localOnly: true }; } throw new Error(response.data?.message || '登录失败'); } return response.data.result; } async requestAuthCode(mobile) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(`${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/send_code`, { mobile }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '验证码发送失败'); } return response.data.result; } async loginWithCode(mobile, code) { const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/login`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, { mobile, code, platform: _config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.platform, clientId: this.getClientId() }, { withCredentials: false }); this.persistAppToken(url, response); if (response.data?.code !== 0) { throw new Error(response.data?.message || '登录失败'); } return response.data.result; } async createPcSession(userId = '') { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(`${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/pc_session`, { flag: 1, device_name: 'Web IM', userId, clientId: this.getClientId(), platform: _config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.platform }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '二维码登录会话创建失败'); } return response.data.result || {}; } async loginWithPcSession(token) { const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/session_login/${encodeURIComponent(token)}`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, null, { withCredentials: false }); this.persistAppToken(url, response); const data = response.data || {}; if ([0, 8, 9, 10, 18].includes(Number(data.code))) { return data; } throw new Error(data.message || '扫码登录失败'); } async registerWithPhone(mobile, code) { const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/register`; const deviceId = getUniqueEquipment(mobile, this.getClientId()); try { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, { mobile, code, platform: _config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.platform, clientId: deviceId, uniqueEquipment: deviceId }, { withCredentials: false }); this.persistAppToken(url, response); if (response.data?.code !== 0) { throw new Error(response.data?.message || '注册失败'); } return response.data.result; } catch (error) { const status = error.response?.status; if (status === 404 || status === 405) { return this.loginWithCode(mobile, code); } throw error; } } connect(userId, token) { this.currentUser = { userId, token }; this.connected = true; this.emit('connectionStatusChanged', { connected: true, statusText: '已连接' }); this.refreshConversationList(); } disconnect() { this.connected = false; this.currentUser = null; this.emit('connectionStatusChanged', { connected: false, statusText: '未连接' }); } getConversationList() { return []; } refreshConversationList() { const conversations = this.getConversationList(); if (conversations.length) { this.emit('conversationsChanged', conversations); } if (this.currentUser?.userId) { this.fetchRemoteConversations().then(remoteConversations => { this.emit('conversationsChanged', remoteConversations); }).catch(() => {}); } return conversations; } async fetchRemoteConversations(limit = 50) { if (!this.currentUser?.userId) { return []; } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messagesApi, { userId: this.currentUser.userId, limit }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '会话同步失败'); } return (response.data?.result?.conversations || []).map(conversation => ({ ...conversation, updatedAt: Number(conversation.updatedAt || Date.now()), avatarText: conversation.avatarText || String(conversation.title || conversation.target || '?').slice(0, 1).toUpperCase(), raw: conversation.raw || { type: 'single', target: conversation.target, line: 0 } })); } getMessages(conversation) { if (!conversation?.id) { return []; } const userId = this.currentUser?.userId || ''; return applyLocalMessageState(conversation.id, readLocalMessages(userId)[conversation.id] || [], userId); } async fetchRemoteMessages(conversation, limit = 50, options = {}) { if (!conversation?.id || !this.currentUser?.userId) { return []; } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messagesApi, { userId: this.currentUser.userId, target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''), limit, conversationType: conversation.type || conversation.raw?.type || 0, markRead: Boolean(options.markRead), includeConversations: Boolean(options.includeConversations) }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '消息同步失败'); } const messages = (response.data?.result?.messages || []).map(message => ({ ...message, displayTimestamp: message.displayTimestamp || message.timestamp, conversationId: conversation.id })); messages.hasPinnedMessageState = Object.prototype.hasOwnProperty.call(response.data?.result || {}, 'pinnedMessageUid'); messages.pinnedMessageUid = String(response.data?.result?.pinnedMessageUid || ''); messages.pinnedMessage = response.data?.result?.pinnedMessage || null; if (options.includeConversations && Array.isArray(response.data?.result?.conversations)) { const remoteConversations = response.data.result.conversations.map(remoteConversation => ({ ...remoteConversation, updatedAt: Number(remoteConversation.updatedAt || Date.now()), avatarText: remoteConversation.avatarText || String(remoteConversation.title || remoteConversation.target || '?').slice(0, 1).toUpperCase(), raw: remoteConversation.raw || { type: 'single', target: remoteConversation.target, line: 0 } })); this.emit('conversationsChanged', remoteConversations); } const userId = this.currentUser?.userId || ''; const messagesByConversation = readLocalMessages(userId); messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId); messagesByConversation[conversation.id].pinnedMessageUid = messages.pinnedMessageUid; messagesByConversation[conversation.id].pinnedMessage = messages.pinnedMessage; messagesByConversation[conversation.id].hasPinnedMessageState = messages.hasPinnedMessageState; writeLocalMessages(messagesByConversation, userId); return messagesByConversation[conversation.id]; } async setPinnedMessage(conversation, messageUid = '', message = null) { const isGroup = ['group', 'channel'].includes(conversation?.type) || ['group', 'channel', 1, '1'].includes(conversation?.raw?.type); if (isGroup) { if (messageUid && message) { return this.addGroupPinnedMessage(conversation, message); } const serverPinId = String(message?.serverPinId || message?.pinId || '').trim(); if (!serverPinId) { throw new Error('缺少置顶记录ID,请刷新会话后重试'); } return this.removeGroupPinnedMessage(serverPinId); } const action = messageUid ? 'pin' : 'unpin'; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messageActionApi, { action, userId: this.currentUser?.userId || '', messageUid: messageUid || '1', target: conversation.target || conversation.raw?.target || '', conversationType: ['group', 'channel'].includes(conversation.type) ? 'group' : 'single', message: message ? { id: String(message.messageUid || message.id || messageUid), messageUid: String(message.messageUid || message.id || messageUid), text: String(message.text || ''), type: message.type || 'text', attachment: message.attachment || null, senderName: message.senderName || message.from || '', timestamp: Number(message.displayTimestamp || message.timestamp || Date.now()) } : null }, { withCredentials: false }); if (response.data?.code !== 0) throw new Error(response.data?.message || '置顶失败'); } async fetchGroupPinnedMessages(conversation) { const groupId = String(conversation?.target || conversation?.raw?.target || '').trim(); if (!groupId) return []; const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/groupTopMessage/gets`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.get(url, { params: { groupId }, headers: this.getAppAuthHeaders(url), withCredentials: false }); const payload = response.data || {}; if (payload.code !== undefined && Number(payload.code) !== 0) { throw new Error(payload.message || '置顶消息加载失败'); } const result = payload.result ?? payload.data ?? payload; return Array.isArray(result) ? result : []; } async addGroupPinnedMessage(conversation, message) { const groupId = String(conversation?.target || conversation?.raw?.target || '').trim(); const messageId = String(message?.messageId || message?.messageUid || message?.id || '').trim(); if (!groupId || !messageId) throw new Error('缺少群ID或消息ID'); const searchableContent = String(message?.text || '').trim() || (message?.type === 'image' ? '[图片]' : message?.type === 'video' ? '[视频]' : '[消息]'); const rawConversationType = Number(conversation?.raw?.type); const conversationType = Number.isFinite(rawConversationType) && rawConversationType > 0 ? rawConversationType : 1; const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/groupTopMessage/add`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, { groupId, userId: message?.from || this.currentUser?.userId || '', messageId, messageType: conversationType, messageText: JSON.stringify({ ...message, messageId, from: message?.from || this.currentUser?.userId || '', conversation: { type: conversationType, target: groupId, line: Number(conversation?.raw?.line || 0) }, content: { searchableContent } }) }, { headers: this.getAppAuthHeaders(url), withCredentials: false }); const payload = response.data || {}; if (payload.code !== undefined && Number(payload.code) !== 0) { const detail = payload.message || payload.msg || payload.result?.message || '置顶失败'; throw new Error(payload.code !== undefined ? `${detail}(错误码 ${payload.code})` : detail); } return payload.result ?? payload.data ?? payload; } async removeGroupPinnedMessage(pinId) { const url = `${_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer}/groupTopMessage/remove/?id=${encodeURIComponent(pinId)}`; const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, {}, { headers: this.getAppAuthHeaders(url), withCredentials: false }); const payload = response.data || {}; if (payload.code !== undefined && Number(payload.code) !== 0) { throw new Error(payload.message || '取消置顶失败'); } return payload.result ?? payload.data ?? payload; } hideMessages(conversation, messages) { const items = Array.isArray(messages) ? messages : [messages]; if (!conversation?.id || !items.length) { return; } const userId = this.currentUser?.userId || ''; storeMessageKeys(LOCAL_HIDDEN_MESSAGE_STORAGE_KEY, conversation.id, items, userId); const messagesByConversation = readLocalMessages(userId); messagesByConversation[conversation.id] = applyLocalMessageState(conversation.id, messagesByConversation[conversation.id] || [], userId); writeLocalMessages(messagesByConversation, userId); } markMessagesRecalled(conversation, messages) { const items = Array.isArray(messages) ? messages : [messages]; if (!conversation?.id || !items.length) { return; } const userId = this.currentUser?.userId || ''; storeMessageKeys(LOCAL_RECALLED_MESSAGE_STORAGE_KEY, conversation.id, items, userId); const messagesByConversation = readLocalMessages(userId); messagesByConversation[conversation.id] = applyLocalMessageState(conversation.id, messagesByConversation[conversation.id] || [], userId); writeLocalMessages(messagesByConversation, userId); } async recallMessage(conversation, message) { const messageUid = String(message?.messageUid || message?.id || '').trim(); if (!/^\d+$/.test(messageUid)) { throw new Error('缺少可撤回的消息ID'); } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messageActionApi, { action: 'recall', userId: this.currentUser?.userId || message.from || '', messageUid }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '撤回失败'); } this.markMessagesRecalled(conversation, [message]); return response.data.result; } async editMessage(conversation, message, text) { const messageUid = String(message?.messageUid || message?.id || '').trim(); if (!/^\d+$/.test(messageUid)) { throw new Error('缺少可编辑的消息ID'); } const nextText = String(text || '').trim(); if (!nextText) { throw new Error('编辑内容不能为空'); } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messageActionApi, { action: 'edit', userId: this.currentUser?.userId || message.from || '', messageUid, text: nextText }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '编辑失败'); } const result = response.data?.result?.message || {}; const editedMessage = { ...message, text: result.text || nextText, status: 'delivered', deliveryStatus: 'delivered', editedAt: Number(result.editedAt || Date.now()), activityTimestamp: Number(result.editedAt || Date.now()) }; saveLocalMessage(editedMessage, this.currentUser?.userId || ''); this.emit('messageStatusChanged', editedMessage); return editedMessage; } async getMessageDetail(conversation, message) { const messageUid = String(message?.messageUid || message?.id || '').trim(); if (!messageUid) { throw new Error('缺少消息ID'); } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.messageDetailApi, { userId: this.currentUser?.userId || '', target: conversation?.target || conversation?.raw?.target || conversation?.id?.replace(/^single-/, '') || '', conversationType: conversation?.type || conversation?.raw?.type || 'single', messageUid }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '消息详情加载失败'); } return response.data?.result?.detail || null; } async sendTextMessage(conversation, text, initialMessage = null, options = {}) { const senderRole = conversation?.role || conversation?.raw?.role || ''; const message = initialMessage || { id: randomId(), conversationId: conversation.id, from: this.currentUser?.userId || 'me', senderRole, direction: 'out', type: 'text', text, status: 'sending', deliveryStatus: 'sending', timestamp: Date.now() }; saveLocalMessage(message, this.currentUser?.userId || ''); if (!initialMessage) { this.emit('messageSent', message); } try { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.sendMessageApi, { sender: this.currentUser?.userId || '', target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''), conversationType: conversation.type || conversation.raw?.type || 0, text, mentionedUserIds: Array.isArray(options.mentionedUserIds) ? options.mentionedUserIds : [] }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '发送失败'); } const sentMessage = { ...message, status: 'sent', deliveryStatus: 'sent', messageUid: response.data?.result?.messageUid ? String(response.data.result.messageUid) : '', senderRole: response.data?.result?.senderRole || message.senderRole || '', serverTimestamp: Number(response.data?.result?.timestamp || 0) || null, timestamp: message.timestamp, displayTimestamp: message.displayTimestamp || message.timestamp }; saveLocalMessage(sentMessage, this.currentUser?.userId || ''); this.emit('messageStatusChanged', sentMessage); return sentMessage; } catch (error) { const failedMessage = { ...message, status: 'failed', deliveryStatus: '', error: error.response?.data?.message || error.message || '发送失败' }; saveLocalMessage(failedMessage, this.currentUser?.userId || ''); this.emit('messageStatusChanged', failedMessage); return failedMessage; } } async sendAttachmentMessage(conversation, { type, file, text = '' }, initialMessage = null) { const senderRole = conversation?.role || conversation?.raw?.role || ''; const message = initialMessage || { id: randomId(), conversationId: conversation.id, from: this.currentUser?.userId || 'me', senderRole, direction: 'out', type, text, attachment: { type, name: file?.name || (type === 'image' ? '图片' : '文件'), mime: file?.type || '', size: file?.size || 0, url: type === 'image' && file ? URL.createObjectURL(file) : '' }, status: 'sending', deliveryStatus: 'sending', timestamp: Date.now() }; saveLocalMessage(message, this.currentUser?.userId || ''); if (!initialMessage) { this.emit('messageSent', message); } try { const formData = new FormData(); formData.append('sender', this.currentUser?.userId || ''); formData.append('target', conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, '')); formData.append('conversationType', conversation.type || conversation.raw?.type || 0); formData.append('messageType', type); formData.append('text', text || ''); formData.append('attachment', file); const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.sendMessageApi, formData, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '发送失败'); } const sentMessage = { ...message, status: 'sent', deliveryStatus: 'sent', messageUid: response.data?.result?.messageUid ? String(response.data.result.messageUid) : '', senderRole: response.data?.result?.senderRole || message.senderRole || '', attachment: response.data?.result?.attachment || message.attachment, serverTimestamp: Number(response.data?.result?.timestamp || 0) || null, timestamp: message.timestamp, displayTimestamp: message.displayTimestamp || message.timestamp }; saveLocalMessage(sentMessage, this.currentUser?.userId || ''); this.emit('messageStatusChanged', sentMessage); return sentMessage; } catch (error) { const failedMessage = { ...message, status: 'failed', deliveryStatus: '', error: error.response?.data?.message || error.message || '发送失败' }; saveLocalMessage(failedMessage, this.currentUser?.userId || ''); this.emit('messageStatusChanged', failedMessage); return failedMessage; } } async forwardAttachmentMessage(conversation, sourceMessage) { const attachment = sourceMessage?.attachment || {}; const type = attachment.type || sourceMessage?.type || 'file'; const formData = new FormData(); formData.append('sender', this.currentUser?.userId || ''); formData.append('target', conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, '')); formData.append('conversationType', conversation.type || conversation.raw?.type || 0); formData.append('messageType', type); formData.append('text', sourceMessage?.text || ''); formData.append('attachmentUrl', attachment.url || ''); formData.append('attachmentName', attachment.name || (type === 'image' ? '转发图片' : type === 'video' ? '转发视频.mp4' : '转发文件')); formData.append('attachmentMime', attachment.mime || (type === 'video' ? 'video/mp4' : 'application/octet-stream')); formData.append('attachmentSize', String(attachment.size || 0)); const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.sendMessageApi, formData, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '转发失败'); } return response.data?.result || {}; } getContactList() { return []; } async getServerContactList(userId) { if (!userId) { return []; } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.contactsApi, { userId }, { withCredentials: false, headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.contactsApi) }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '联系人加载失败'); } return (response.data?.result?.contacts || []).map(item => { return this.mapContact(item.uid, { alias: item.alias }, { uid: item.uid, displayName: item.displayName, name: item.name, mobile: item.mobile, portrait: item.portrait, address: item.address, friendAlias: item.alias }); }).sort((a, b) => a.title.localeCompare(b.title, 'zh-CN')); } async addContact(userId, keyword, reason = '') { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.addContactApi, { userId, keyword, reason }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '添加联系人失败'); } const item = response.data?.result?.contact; if (!item?.uid) { return null; } return this.mapContact(item.uid, { alias: item.alias }, { uid: item.uid, displayName: item.displayName, name: item.name, mobile: item.mobile, portrait: item.portrait, address: item.address, friendAlias: item.alias }); } normalizeConversation(conversation) { const title = getTitle(conversation?.title, conversation?.target || ''); return { ...conversation, id: conversation?.id || `${conversation?.type === 'single' ? 'single' : 'group'}-${conversation?.target}`, target: conversation?.target || conversation?.raw?.target || '', title, subtitle: conversation?.subtitle || '', unread: Number(conversation?.unread || 0), portrait: conversation?.portrait || '', avatarText: conversation?.avatarText || title.slice(0, 1).toUpperCase(), updatedAt: Number(conversation?.updatedAt || Date.now()), raw: conversation?.raw || { type: conversation?.type === 'single' ? 'single' : 'group', target: conversation?.target || '', line: 0 } }; } async createGroup(userId, { name, memberIds = [], announcement = '', welcomeText = '', channel = false }) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: channel ? 'create_channel' : 'create_group', userId, name, memberIds, announcement, welcomeText }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || (channel ? '创建公告群失败' : '创建群组失败')); } return this.normalizeConversation(response.data?.result?.conversation || {}); } async joinGroup(userId, groupKey) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'join_group', userId, groupKey }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '加入群组失败'); } return this.normalizeConversation(response.data?.result?.conversation || {}); } async broadcastMessage(userId, targetIds, text) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'broadcast', userId, targetIds, text }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '群发失败'); } return response.data?.result || {}; } async getGroupDetail(userId, groupId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'group_detail', userId, groupId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '群资料加载失败'); } return response.data?.result?.group || null; } async getGroupMembers(userId, groupId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'group_members', userId, groupId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '群员加载失败'); } return response.data?.result?.members || []; } async updateGroupAlias(userId, groupId, alias) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'update_group_alias', userId, groupId, alias }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '本群昵称保存失败'); } return response.data?.result?.alias || ''; } async leaveGroup(userId, groupId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'leave_group', userId, groupId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '退出群组失败'); } return response.data?.result || {}; } async dismissGroup(userId, groupId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'dismiss_group', userId, groupId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '解散群组失败'); } return response.data?.result || {}; } async transferGroup(userId, groupId, targetUserId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'transfer_group', userId, groupId, targetUserId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '转让群组失败'); } return response.data?.result || {}; } async setGroupAdmins(userId, groupId, adminIds) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'set_group_admins', userId, groupId, adminIds }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '管理员设置失败'); } return response.data?.result || {}; } async updateGroupProfile(userId, groupId, { name, announcement, welcomeText }) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'update_group_profile', userId, groupId, name, announcement, welcomeText }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '群资料保存失败'); } return response.data?.result || {}; } async kickGroupMembers(userId, groupId, targetIds) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'kick_group_members', userId, groupId, targetIds }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '踢人失败'); } return response.data?.result || {}; } async updateGroupMuteSetting(userId, groupId, setting) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.conversationActionsApi, { action: 'update_mute_setting', userId, groupId, ...setting }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '禁言设置保存失败'); } return response.data?.result?.muteSetting || null; } async updateContactAlias(userId, targetId, alias) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.updateAliasApi, { userId, targetId, alias }, { withCredentials: false, headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.updateAliasApi) }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '备注名修改失败'); } return response.data?.result?.contact?.alias || ''; } async getProfile(userId) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.profileApi, { action: 'get', userId }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '用户资料加载失败'); } return response.data?.result?.profile || null; } async updateProfile(userId, { displayName, portraitFile }) { const formData = new FormData(); formData.append('action', 'update'); formData.append('userId', userId); formData.append('displayName', displayName); if (portraitFile) { formData.append('portraitFile', portraitFile); } const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.profileApi, formData, { withCredentials: false, headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.appServer) }); if (response.data?.code !== 0) { throw new Error(response.data?.message || '用户资料保存失败'); } return response.data?.result?.profile || null; } async changePassword({ oldPassword, newPassword }) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.changePasswordApi, { oldPassword, newPassword }, { withCredentials: false, headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.changePasswordApi) }); if (response.data?.code !== 0) { throw new Error(response.data?.message || response.data?.msg || '密码修改失败'); } return true; } async resetPasswordWithCode({ mobile, resetCode, newPassword }) { const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.resetPasswordApi, { mobile, resetCode, newPassword }, { withCredentials: false }); if (response.data?.code !== 0) { throw new Error(response.data?.message || response.data?.msg || '密码设置失败'); } return true; } refreshContactList() { const contacts = this.getContactList(); this.emit('contactsChanged', contacts); return contacts; } createSingleConversation(userId, userInfo = null) { const title = getTitle(userInfo?.title || userInfo?.displayName || userInfo?.name, userId); return { id: `single-${userId}`, type: 'single', target: userId, title, subtitle: '', unread: 0, portrait: userInfo?.portrait || '', avatarText: title.slice(0, 1).toUpperCase(), updatedAt: Date.now(), raw: { type: 'single', target: userId, line: 0 } }; } mapContact(userId, friend, userInfo) { const title = getTitle(userInfo?.friendAlias || friend?.alias || userInfo?.displayName || userInfo?.name, userId); return { id: userId, uid: userId, title, subtitle: userInfo?.mobile || userInfo?.name || userId, portrait: userInfo?.portrait || '', address: userInfo?.address || '', avatarText: title.slice(0, 1).toUpperCase(), alias: friend?.alias || userInfo?.friendAlias || '', rawFriend: friend, rawUser: userInfo }; } on(eventName, handler) { if (!this.listeners.has(eventName)) { this.listeners.set(eventName, new Set()); } this.listeners.get(eventName).add(handler); return () => this.off(eventName, handler); } off(eventName, handler) { this.listeners.get(eventName)?.delete(handler); } emit(eventName, payload) { this.listeners.get(eventName)?.forEach(handler => handler(payload)); } persistAppToken(url, response) { const appToken = response.headers?.authtoken || response.headers?.authToken; if (appToken) { localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.authTokenStoragePrefix + this.getUrlHost(url), appToken); } } getAppAuthHeaders(url) { const host = this.getUrlHost(url); if (!host) { return {}; } const token = localStorage.getItem(_config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.authTokenStoragePrefix + host); return token ? { authToken: token } : {}; } getUrlHost(url) { try { return new URL(url, window.location.origin).host; } catch (error) { return ''; } } } const imClient = new HttpImClient(); /***/ }), /***/ 5051: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* unused harmony export WildfireImClient */ /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2169); /* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5099); /* harmony import */ var _longConnectionImClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3909); /* harmony import */ var _documentedHttpImClient__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4355); class UnsupportedWildfireImClient { constructor() { throw new Error('当前本地社区版 Web 客户端未启用 WildFire Web SDK'); } } const imClient = _config__WEBPACK_IMPORTED_MODULE_0__/* .appConfig */ .U.sdkMode === 'wildfire' ? new UnsupportedWildfireImClient() : _config__WEBPACK_IMPORTED_MODULE_0__/* .appConfig */ .U.sdkMode === 'custom-ws' || _config__WEBPACK_IMPORTED_MODULE_0__/* .appConfig */ .U.sdkMode === 'long' ? new _longConnectionImClient__WEBPACK_IMPORTED_MODULE_2__/* .LongConnectionImClient */ .E() : _config__WEBPACK_IMPORTED_MODULE_0__/* .appConfig */ .U.sdkMode === 'legacy-http' ? new _httpImClient__WEBPACK_IMPORTED_MODULE_1__/* .HttpImClient */ .Y() : new _documentedHttpImClient__WEBPACK_IMPORTED_MODULE_3__/* .DocumentedHttpImClient */ .u(); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "wD", 0, /* binding */ imClient /* harmony export */ ]); /***/ }), /***/ 3909: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ E: function() { return /* binding */ LongConnectionImClient; } /* harmony export */ }); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2169); /* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5099); const HEARTBEAT_INTERVAL_MS = 25000; const RECONNECT_MIN_MS = 1000; const RECONNECT_MAX_MS = 15000; function buildWsUrl() { if (_config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.wsUrl) { return _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.wsUrl; } const protocol = _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.useWss ? 'wss' : 'ws'; const host = _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.imServerHost || window.location.hostname; const port = _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.imRoutePort ? `:${_config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.imRoutePort}` : ''; const path = _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.wsPath?.startsWith('/') ? _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.wsPath : `/${_config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.wsPath || 'ws'}`; return `${protocol}://${host}${port}${path}`; } function normalizeConversationId(payload) { const target = payload.target || payload.to || payload.receiver || payload.conversationTarget || payload.from || payload.sender; return payload.conversationId || (target ? `single-${target}` : ''); } function normalizeIncomingMessage(payload, currentUserId) { const item = payload.message || payload; const from = item.from || item.sender || item.fromUser || ''; const target = item.target || item.to || item.receiver || ''; const direction = from && String(from) === String(currentUserId) ? 'out' : 'in'; const conversationId = item.conversationId || normalizeConversationId({ ...item, target: direction === 'out' ? target : from }); if (!conversationId) { return null; } const status = item.status || item.deliveryStatus || 'sent'; return { id: item.id || item.messageId || item.messageUid || `${Date.now()}${Math.random().toString(16).slice(2)}`, messageUid: item.messageUid || item.uid || item.messageId || '', conversationId, from, target, direction, type: item.type || 'text', text: item.text || item.content || item.searchableContent || '', status, deliveryStatus: item.deliveryStatus || (direction === 'out' ? status : ''), timestamp: Number(item.timestamp || item.serverTimestamp || Date.now()), displayTimestamp: Number(item.displayTimestamp || item.timestamp || item.serverTimestamp || Date.now()), raw: item }; } class LongConnectionImClient extends _httpImClient__WEBPACK_IMPORTED_MODULE_5__/* .HttpImClient */ .Y { constructor() { super(); this.socket = null; this.wsUrl = buildWsUrl(); this.heartbeatTimer = null; this.reconnectTimer = null; this.reconnectAttempts = 0; this.manualClose = false; } getSdkVersion() { return 'JC-LC/0.1'; } shouldUseMessagePolling() { return !this.connected; } async ensureSdk() { if (typeof WebSocket === 'undefined') { throw new Error('当前浏览器不支持 WebSocket 长连接'); } return true; } connect(userId, token) { this.currentUser = { userId, token }; this.manualClose = false; this.openSocket(); } disconnect() { this.manualClose = true; this.clearReconnectTimer(); this.clearHeartbeatTimer(); if (this.socket) { this.socket.close(); this.socket = null; } super.disconnect(); } openSocket() { if (this.socket?.readyState === WebSocket.OPEN) { this.sendAuthFrame(); return; } if (this.socket?.readyState === WebSocket.CONNECTING) { return; } this.emit('connectionStatusChanged', { connected: false, statusText: '长连接连接中' }); try { this.socket = new WebSocket(this.wsUrl); this.socket.binaryType = 'arraybuffer'; } catch (error) { this.emit('connectionStatusChanged', { connected: false, statusText: '长连接创建失败,使用HTTP补偿' }); this.scheduleReconnect(); return; } this.socket.onopen = () => { this.connected = true; this.reconnectAttempts = 0; this.emit('connectionStatusChanged', { connected: true, statusText: '长连接已连接' }); this.sendAuthFrame(); this.startHeartbeat(); this.refreshConversationList(); }; this.socket.onmessage = event => { this.handleFrame(event.data); }; this.socket.onerror = () => { this.emit('connectionStatusChanged', { connected: false, statusText: '长连接异常,使用HTTP补偿' }); }; this.socket.onclose = () => { this.connected = false; this.clearHeartbeatTimer(); this.socket = null; if (this.manualClose) { return; } this.emit('connectionStatusChanged', { connected: false, statusText: '长连接重连中' }); this.scheduleReconnect(); }; } sendAuthFrame() { this.sendFrame({ type: 'auth', userId: this.currentUser?.userId || '', token: this.currentUser?.token || '', clientId: this.getClientId(), platform: _config__WEBPACK_IMPORTED_MODULE_4__/* .appConfig */ .U.platform, timestamp: Date.now() }); } sendFrame(frame) { if (this.socket?.readyState !== WebSocket.OPEN) { return false; } this.socket.send(JSON.stringify(frame)); return true; } handleFrame(rawData) { if (rawData instanceof ArrayBuffer) { this.emit('rawFrameReceived', rawData); return; } let payload; try { payload = typeof rawData === 'string' ? JSON.parse(rawData) : rawData; } catch (error) { return; } const type = payload.type || payload.event || payload.cmd || ''; if (type === 'pong' || type === 'auth_ok' || type === 'connected') { return; } if (type === 'contactsChanged') { this.emit('contactsChanged', payload.contacts || []); return; } if (type === 'conversationsChanged') { this.emit('conversationsChanged', payload.conversations || []); return; } if (type === 'messages' && Array.isArray(payload.messages)) { payload.messages.map(message => normalizeIncomingMessage(message, this.currentUser?.userId)).filter(Boolean).forEach(message => this.emit('messageReceived', message)); return; } const message = normalizeIncomingMessage(payload, this.currentUser?.userId); if (message) { this.emit(message.direction === 'out' ? 'messageStatusChanged' : 'messageReceived', message); } } startHeartbeat() { this.clearHeartbeatTimer(); this.heartbeatTimer = window.setInterval(() => { this.sendFrame({ type: 'ping', timestamp: Date.now() }); }, HEARTBEAT_INTERVAL_MS); } clearHeartbeatTimer() { if (this.heartbeatTimer) { window.clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } } scheduleReconnect() { this.clearReconnectTimer(); const delay = Math.min(RECONNECT_MAX_MS, RECONNECT_MIN_MS * 2 ** this.reconnectAttempts); this.reconnectAttempts += 1; this.reconnectTimer = window.setTimeout(() => { this.openSocket(); }, delay); } clearReconnectTimer() { if (this.reconnectTimer) { window.clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } } } /***/ }), /***/ 446: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ TJ: function() { return /* binding */ useImageProxyFallback; }, /* harmony export */ eR: function() { return /* binding */ useVideoOriginalFallback; }, /* harmony export */ nM: function() { return /* binding */ videoDisplayUrl; } /* harmony export */ }); /* unused harmony export imageDisplayUrl */ /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7642); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8004); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3853); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5876); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2475); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(5024); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(1698); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_8__); function configuredProxyHosts() { const configured = window.JC_WEB_IM_CONFIG?.mediaProxyHosts; const values = Array.isArray(configured) ? configured : String(configured || '').split(/[\s,]+/); return new Set(['zhiyanim.dfpnm.cn', ...values].map(value => String(value || '').trim().toLowerCase().replace(/\.$/, '')).filter(Boolean)); } function imageDisplayUrl(value) { const source = String(value || '').trim(); if (!source || source.startsWith('blob:') || source.startsWith('data:')) { return source; } try { const url = new URL(source, window.location.origin); if (url.protocol !== 'https:' || !configuredProxyHosts().has(url.hostname.toLowerCase())) { return source; } const proxyUrl = new URL('/api/media_proxy.php', window.location.origin); proxyUrl.searchParams.set('url', url.toString()); return proxyUrl.toString(); } catch (error) { return source; } } function videoDisplayUrl(value) { const source = String(value || '').trim(); if (!source || source.startsWith('blob:') || source.startsWith('data:')) return source; const streamUrl = new URL('/api/media_stream.php', window.location.origin); streamUrl.searchParams.set('url', source); return streamUrl.toString(); } function useVideoOriginalFallback(event, value) { const video = event?.currentTarget; const source = String(value || '').trim(); if (!video || !source || video.dataset.originalFallback === '1') return; video.dataset.originalFallback = '1'; video.src = source; video.load(); } function useImageProxyFallback(event, value) { const image = event?.currentTarget; if (!image) return; const fallback = imageDisplayUrl(value); if (!fallback || fallback === value || image.dataset.proxyFallback === '1') return; image.dataset.proxyFallback = '1'; image.src = fallback; } /***/ }), /***/ 9687: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2387); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2169); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5051); class RealtimeNotificationClient { constructor() { this.source = null; this.userId = ''; this.handler = null; this.reconnectTimer = null; this.reconnectAttempt = 0; this.generation = 0; } isConnected() { return this.source?.readyState === WebSocket.OPEN; } start(userId, handler) { this.stop(); if (!_config__WEBPACK_IMPORTED_MODULE_2__/* .appConfig */ .U.sseEnabled || !userId || typeof window.WebSocket !== 'function') return; this.userId = userId; this.handler = handler; this.generation += 1; this.open(this.generation); } stop() { this.generation += 1; window.clearTimeout(this.reconnectTimer); this.reconnectTimer = null; if (this.source) this.source.close(); this.source = null; this.userId = ''; this.handler = null; this.reconnectAttempt = 0; } async open(generation) { try { const response = await axios__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .A.post(_config__WEBPACK_IMPORTED_MODULE_2__/* .appConfig */ .U.sseTicketApi, { userId: this.userId }, { withCredentials: false, headers: _services_imClient__WEBPACK_IMPORTED_MODULE_3__/* .imClient */ .wD.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_2__/* .appConfig */ .U.appServer) }); if (generation !== this.generation) return; if (response.data?.code !== 0) throw new Error(response.data?.message || '实时通知凭证申请失败'); const ticket = response.data?.result?.ticket || ''; if (!ticket) throw new Error('实时通知凭证为空'); const separator = _config__WEBPACK_IMPORTED_MODULE_2__/* .appConfig */ .U.sseUrl.includes('?') ? '&' : '?'; const endpoint = `${_config__WEBPACK_IMPORTED_MODULE_2__/* .appConfig */ .U.sseUrl}${separator}ticket=${encodeURIComponent(ticket)}`; const socketUrl = endpoint.startsWith('ws://') || endpoint.startsWith('wss://') ? endpoint : `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`; const source = new WebSocket(socketUrl); this.source = source; source.onopen = () => { this.reconnectAttempt = 0; }; source.onmessage = event => { if (generation !== this.generation) return; let payload = {}; try { payload = JSON.parse(event.data || '{}'); } catch (error) { payload = {}; } if (payload.type !== 'message-notification') return; this.handler?.(payload); }; source.onerror = () => { if (generation !== this.generation) return; source.close(); if (this.source === source) this.source = null; this.scheduleReconnect(generation); }; source.onclose = () => { if (generation !== this.generation || this.source !== source) return; this.source = null; this.scheduleReconnect(generation); }; } catch (error) { if (generation === this.generation) this.scheduleReconnect(generation); } } scheduleReconnect(generation) { window.clearTimeout(this.reconnectTimer); const delay = Math.min(30000, 1000 * 2 ** Math.min(this.reconnectAttempt, 5)); this.reconnectAttempt += 1; this.reconnectTimer = window.setTimeout(() => this.open(generation), delay); } } const realtimeNotifications = new RealtimeNotificationClient(); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "w", 0, /* binding */ realtimeNotifications /* harmony export */ ]); /***/ }), /***/ 9045: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5367); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(2731); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2261); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(5051); /* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(7566); /* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(1414); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(926); const CONTACT_CACHE_MS = 15000; function normalizeContacts(contacts) { const unique = new Map(); contacts.forEach(contact => { const uid = String(contact.uid || contact.id || '').trim(); if (!uid) { return; } const normalized = { ...contact, id: String(contact.id || uid), uid }; unique.set(uid, { ...(unique.get(uid) || {}), ...normalized }); }); return Array.from(unique.values()).sort((a, b) => a.title.localeCompare(b.title, 'zh-CN')); } const useContactStore = (0,pinia__WEBPACK_IMPORTED_MODULE_6__/* .defineStore */ .nY)('contacts', { state: () => ({ contacts: [], activeId: '', loading: false, eventsBound: false, refreshSerial: 0, refreshPromise: null, loadedForUserId: '', loadedAt: 0, actionError: '', actionInfo: '' }), getters: { activeContact(state) { return state.contacts.find(item => item.id === state.activeId) || state.contacts[0] || null; } }, actions: { bindImEvents() { if (this.eventsBound) { return; } this.eventsBound = true; _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.on('contactsChanged', contacts => { if (!contacts.length && this.contacts.length) { return; } this.contacts = normalizeContacts(contacts); if (!this.contacts.find(item => item.id === this.activeId)) { this.activeId = this.contacts[0]?.id || ''; } }); }, async refreshContacts(options = {}) { this.bindImEvents(); const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__/* .useSessionStore */ .B)(); const requestUserId = session.userId; const force = Boolean(options.force); if (!requestUserId) { this.clearContacts(); return []; } if (!force && this.contacts.length && this.loadedForUserId === requestUserId && Date.now() - this.loadedAt < CONTACT_CACHE_MS) { return this.contacts; } if (this.refreshPromise && !force) { return this.refreshPromise; } const serial = this.refreshSerial + 1; this.refreshSerial = serial; this.loading = true; this.refreshPromise = (async () => { this.contacts = normalizeContacts(_services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.refreshContactList()); if (!this.contacts.find(item => item.id === this.activeId)) { this.activeId = this.contacts[0]?.id || ''; } if (!this.contacts.length || force) { const serverContacts = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.getServerContactList(requestUserId); if (serial !== this.refreshSerial || (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__/* .useSessionStore */ .B)().userId !== requestUserId) { return this.contacts; } this.contacts = normalizeContacts(serverContacts); this.loadedForUserId = requestUserId; this.loadedAt = Date.now(); if (!this.contacts.find(item => item.id === this.activeId)) { this.activeId = this.contacts[0]?.id || ''; } } window.setTimeout(() => { if (serial !== this.refreshSerial || (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__/* .useSessionStore */ .B)().userId !== requestUserId) { return; } const latest = _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.getContactList(false); if (latest.length || !this.contacts.length) { this.contacts = normalizeContacts(latest); this.loadedForUserId = requestUserId; this.loadedAt = Date.now(); if (!this.contacts.find(item => item.id === this.activeId)) { this.activeId = this.contacts[0]?.id || ''; } } }, 1200); return this.contacts; })(); try { return await this.refreshPromise; } finally { if (serial === this.refreshSerial) { this.loading = false; this.refreshPromise = null; } } }, async addContact(keyword) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__/* .useSessionStore */ .B)(); const value = String(keyword || '').trim(); this.actionError = ''; this.actionInfo = ''; if (!session.userId) { this.actionError = '请先登录'; return false; } if (!value) { this.actionError = '请输入用户ID、手机号或用户名'; return false; } this.loading = true; try { const contact = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.addContact(session.userId, value, '添加联系人'); if (contact) { this.contacts = normalizeContacts([...this.contacts, contact]); this.activeId = contact.id; } this.actionInfo = '联系人已添加'; await this.refreshContacts({ force: true }); return true; } catch (error) { this.actionError = error.message || '添加联系人失败'; return false; } finally { this.loading = false; } }, async updateContactAlias(contactId, alias) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__/* .useSessionStore */ .B)(); const targetId = String(contactId || '').trim(); const nextAlias = String(alias || '').trim(); this.actionError = ''; this.actionInfo = ''; if (!session.userId) { this.actionError = '请先登录'; return false; } if (!targetId) { this.actionError = '缺少联系人ID'; return false; } try { const savedAlias = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.updateContactAlias(session.userId, targetId, nextAlias); this.contacts = normalizeContacts(this.contacts.map(item => { if (item.uid !== targetId && item.id !== targetId) { return item; } const rawUser = { ...(item.rawUser || {}), friendAlias: savedAlias }; const rawFriend = { ...(item.rawFriend || {}), alias: savedAlias }; const title = savedAlias || rawUser.displayName || rawUser.name || item.uid; return { ...item, title, avatarText: title.slice(0, 1).toUpperCase(), alias: savedAlias, rawFriend, rawUser }; })); this.loadedAt = Date.now(); this.actionInfo = '备注名已修改'; return true; } catch (error) { this.actionError = error.message || '备注名修改失败'; return false; } }, clearContacts() { this.refreshSerial += 1; this.contacts = []; this.activeId = ''; this.loading = false; this.refreshPromise = null; this.loadedForUserId = ''; this.loadedAt = 0; this.actionError = ''; this.actionInfo = ''; }, setActiveContact(id) { this.activeId = id; }, openChat(contact) { if (!contact) { return; } const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_8__/* .useConversationStore */ .w)(); const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_9__/* .useNavigationStore */ .l)(); const conversation = _services_imClient__WEBPACK_IMPORTED_MODULE_7__/* .imClient */ .wD.createSingleConversation(contact.uid, contact); conversations.upsertConversation(conversation); conversations.setActiveConversation(conversation.id); navigation.showMessages(); } } }); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "p", 0, /* binding */ useContactStore /* harmony export */ ]); /***/ }), /***/ 7566: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* unused harmony import specifier */ var imClient; /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4114); /* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8111); /* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2489); /* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(116); /* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(531); /* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7588); /* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(1701); /* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(8237); /* harmony import */ var core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8__); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(3579); /* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9__); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(5367); /* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10__); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(2731); /* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11__); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(7642); /* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12__); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(8004); /* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13__); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(3853); /* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14__); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(5876); /* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15__); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(2475); /* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16__); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(5024); /* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17__); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(1698); /* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18__); /* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(2261); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(5051); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(2169); /* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(926); /* harmony import */ var _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(9687); const LOCAL_CONVERSATION_STORAGE_KEY = 'qmt-web-im-local-conversations-v2'; const LOCAL_FAVORITE_MESSAGES_KEY = 'qmt-web-im-favorite-messages-v1'; const LOCAL_PINNED_MESSAGES_KEY = 'qmt-web-im-pinned-messages-v1'; const LOCAL_HIDDEN_CONVERSATIONS_KEY = 'qmt-web-im-hidden-conversations-v1'; function scopedStorageKey(baseKey) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); const scope = `${_config__WEBPACK_IMPORTED_MODULE_21__/* .appConfig */ .U.appServer || ''}:${session.userId || 'anonymous'}`; return `${baseKey}:${encodeURIComponent(scope)}`; } function readFavoriteMessages() { try { return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_FAVORITE_MESSAGES_KEY)) || '[]'); } catch (error) { return []; } } function writeFavoriteMessages(messages) { localStorage.setItem(scopedStorageKey(LOCAL_FAVORITE_MESSAGES_KEY), JSON.stringify(messages)); } function readLocalConversations() { try { return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_CONVERSATION_STORAGE_KEY)) || '[]'); } catch (error) { return []; } } function writeLocalConversations(conversations) { localStorage.setItem(scopedStorageKey(LOCAL_CONVERSATION_STORAGE_KEY), JSON.stringify(conversations)); } function readHiddenConversationIds() { try { return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_HIDDEN_CONVERSATIONS_KEY)) || '[]'); } catch (error) { return []; } } function writeHiddenConversationIds(ids) { localStorage.setItem(scopedStorageKey(LOCAL_HIDDEN_CONVERSATIONS_KEY), JSON.stringify(ids)); } function readPinnedMessages() { try { return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_PINNED_MESSAGES_KEY)) || '{}'); } catch (error) { return {}; } } function writePinnedMessages(messages) { localStorage.setItem(scopedStorageKey(LOCAL_PINNED_MESSAGES_KEY), JSON.stringify(messages)); } function parseNativePinnedMessage(item, messages = []) { if (!item) return null; const messageId = String(item.messageId || item.messageUid || '').trim(); const matched = messages.find(message => [message.messageId, message.messageUid, message.id].filter(Boolean).some(value => String(value) === messageId)); let encoded = {}; try { encoded = typeof item.messageText === 'string' ? JSON.parse(item.messageText) : item.messageText || {}; } catch (error) { encoded = {}; } const text = String(encoded?.content?.searchableContent || encoded?.messageContent?.searchableContent || encoded?.text || matched?.text || '[消息]'); return { ...(matched || {}), key: messageId || `group-pin-${item.id}`, id: messageId || `group-pin-${item.id}`, messageUid: messageId || matched?.messageUid || '', serverPinId: String(item.id || ''), text, type: matched?.type || encoded?.type || 'text', attachment: matched?.attachment || encoded?.attachment || null, senderName: matched?.senderName || encoded?.senderName || encoded?.from || '', timestamp: Number(matched?.displayTimestamp || matched?.timestamp || item.updateTime || item.createTime || Date.now()) }; } function sortConversations(conversations) { return [...conversations].sort((left, right) => { const leftPinned = Number(left.pinnedAt || left.top || 0); const rightPinned = Number(right.pinnedAt || right.top || 0); if (Boolean(leftPinned) !== Boolean(rightPinned)) { return rightPinned ? 1 : -1; } if (leftPinned && rightPinned && leftPinned !== rightPinned) { return rightPinned - leftPinned; } return Number(right.updatedAt || 0) - Number(left.updatedAt || 0); }); } function randomId() { if (window.crypto && window.crypto.randomUUID) { return window.crypto.randomUUID().replaceAll('-', ''); } return `${Date.now()}${Math.random().toString(16).slice(2)}`; } function messageKey(message) { return message.id || message.messageUid; } function messageStableKey(message) { return String(message?.messageUid || message?.id || ''); } function messageActivityTimestamp(message) { return Number(message?.activityTimestamp || message?.editedAt || message?.displayTimestamp || message?.timestamp || 0); } function isRecalledMessage(message) { return Boolean(message?.recalled) || message?.status === 'recalled'; } function attachmentLabel(message) { const attachment = message?.attachment; if (!attachment) { return ''; } if (attachment.type === 'image') { return '[图片]'; } return `[文件] ${attachment.name || '文件'}`; } function messagePreviewText(message) { if (isRecalledMessage(message)) { return `[${message?.recallStatus || '已撤回'}]`; } const text = String(message?.text || '').replace(/\s+/g, ' ').trim(); return text || attachmentLabel(message); } function quotePrefix(message) { const text = messagePreviewText(message); return text.length > 48 ? `${text.slice(0, 48)}...` : text; } async function writeClipboard(text) { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(text); return; } const element = document.createElement('textarea'); element.value = text; element.setAttribute('readonly', 'readonly'); element.style.position = 'fixed'; element.style.left = '-9999px'; document.body.appendChild(element); element.select(); document.execCommand('copy'); document.body.removeChild(element); } function isSameMessage(left, right) { if (left.messageUid && right.messageUid && left.messageUid === right.messageUid) { return true; } if (left.id && right.id && left.id === right.id) { return true; } return left.direction === right.direction && left.text === right.text && (left.type || 'text') === (right.type || 'text') && Math.abs(Number(left.displayTimestamp || left.timestamp || 0) - Number(right.displayTimestamp || right.timestamp || 0)) < 15000; } function hasExactMessage(messages, message) { return messages.some(item => { if (item.id && message.id && item.id === message.id) { return true; } return item.messageUid && message.messageUid && item.messageUid === message.messageUid; }); } function shouldUseMessagePolling() { return imClient.shouldUseMessagePolling ? imClient.shouldUseMessagePolling() : true; } function canMarkReadNow(options = {}) { if (typeof document === 'undefined') { return false; } if (document.visibilityState !== 'visible') { return false; } if (options.userAction) { return true; } return true; } function forwardedText(message) { return String(message?.text || '').replace(/^转发\s*[::]\s*/u, '').trim(); } function normalizeMessageForDisplay(message) { if (!message || message.attachment || String(message.text || '').trim()) { return message; } const contentType = Number(message.contentType || 0); const labels = { 3: '[图片加载失败]', 6: '[视频加载失败]', 90: '[红包]', 92: '以上是打招呼的内容', 93: '你们已经是好友了,可以开始聊天了。', 105: '[领取了红包]' }; if (!labels[contentType]) { return message; } return { ...message, type: 'text', text: labels[contentType] }; } function mergeVisibleMessages(currentMessages, syncedMessages) { const merged = [...syncedMessages].map(normalizeMessageForDisplay); currentMessages.forEach(currentMessage => { currentMessage = normalizeMessageForDisplay(currentMessage); const exists = merged.some(message => isSameMessage(message, currentMessage)); const shouldKeepLocal = currentMessage.status === 'sending' || currentMessage.status === 'failed' || currentMessage.direction === 'out' && currentMessage.status === 'sent' && Date.now() - Number(currentMessage.timestamp || 0) < 30000; if (!exists && shouldKeepLocal) { merged.push(currentMessage); } }); return merged.filter((message, index, messages) => { const key = messageKey(message); return messages.findIndex(item => messageKey(item) === key) === index; }).sort((a, b) => Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0)); } function incomingEditedMessages(previousMessages, nextMessages) { const previousByKey = new Map(); (previousMessages || []).forEach(message => { const key = messageStableKey(message); if (key) { previousByKey.set(key, message); } }); return (nextMessages || []).filter(message => { if (message.direction !== 'in') { return false; } const editedAt = Number(message.editedAt || 0); if (editedAt <= 0) { return false; } const previous = previousByKey.get(messageStableKey(message)); return previous && editedAt > Number(previous.editedAt || 0); }); } let notificationAudioContext = null; function playNotificationSound() { if (typeof window === 'undefined') { return; } try { const AudioContext = window.AudioContext || window.webkitAudioContext; if (!AudioContext) { return; } notificationAudioContext = notificationAudioContext || new AudioContext(); if (notificationAudioContext.state === 'suspended') { notificationAudioContext.resume().catch(() => {}); } const oscillator = notificationAudioContext.createOscillator(); const gain = notificationAudioContext.createGain(); const startAt = notificationAudioContext.currentTime; oscillator.type = 'sine'; oscillator.frequency.setValueAtTime(880, startAt); oscillator.frequency.setValueAtTime(660, startAt + 0.1); gain.gain.setValueAtTime(0.0001, startAt); gain.gain.exponentialRampToValueAtTime(0.12, startAt + 0.02); gain.gain.exponentialRampToValueAtTime(0.0001, startAt + 0.22); oscillator.connect(gain); gain.connect(notificationAudioContext.destination); oscillator.start(startAt); oscillator.stop(startAt + 0.24); } catch (error) { // Notification sound is best-effort; browsers may block audio until user interaction. } } const useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__/* .defineStore */ .nY)('conversations', { state: () => ({ activeId: '', conversations: [], messagesByConversation: {}, visibleMessagesByConversation: {}, eventsBound: false, usingDemoData: false, loading: false, syncTimer: null, conversationSyncTimer: null, readPresenceEventsBound: false, syncInFlight: false, pendingReadReceiptConversationId: '', conversationSyncInFlight: false, syncAfterSendTimer: null, optimisticMessagesByConversation: {}, quotedMessage: null, forwardingMessages: [], editingMessage: null, editingText: '', editingMode: '', messageDetailOpen: false, messageDetailLoading: false, messageDetailError: '', messageDetail: null, attentionMessageId: '', attentionMessageTimer: null, selectionMode: false, selectedMessageIds: [], favoriteMessages: [], pinnedMessagesByConversation: {}, groupPinnedSyncAt: {}, hiddenConversationIds: [], activeFavoriteKey: '', actionNotice: '', actionError: '', actionNoticeTimer: null, realtimeSyncTimer: null }), getters: { activeConversation(state) { return state.conversations.find(item => item.id === state.activeId) || state.conversations[0] || null; }, activeMessages(state) { return state.visibleMessagesByConversation[state.activeId] || []; }, totalUnread(state) { return state.conversations.reduce((sum, item) => sum + Number(item.unread || 0), 0); }, canSendActiveConversation(state) { const conversation = state.conversations.find(item => item.id === state.activeId) || state.conversations[0] || null; if (!conversation) { return false; } if (conversation.type !== 'channel') { return true; } return ['owner', 'admin'].includes(conversation.role || conversation.raw?.role || ''); }, favoriteMessageIds(state) { return state.favoriteMessages.map(message => message.key); }, activeFavorite(state) { return state.favoriteMessages.find(message => message.key === state.activeFavoriteKey) || state.favoriteMessages[0] || null; }, activePinnedMessage(state) { const pinned = state.pinnedMessagesByConversation[state.activeId] || null; if (!pinned) return null; const message = (state.visibleMessagesByConversation[state.activeId] || []).find(item => messageStableKey(item) === pinned.key); return message ? { ...pinned, ...message, key: pinned.key } : pinned; }, selectedMessages(state) { const selectedIds = new Set(state.selectedMessageIds); return (state.visibleMessagesByConversation[state.activeId] || []).filter(message => selectedIds.has(messageStableKey(message))); } }, actions: { bootstrapDemoData() { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); this.bindImEvents(); this.usingDemoData = false; if (!session.userId) { this.clearUserState(); return; } this.loadScopedLocalState(); this.startMessageSync(); _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__/* .realtimeNotifications */ .w.start(session.userId, payload => this.handleRealtimeNotification(payload)); }, loadScopedLocalState() { this.conversations = []; this.favoriteMessages = readFavoriteMessages(); this.pinnedMessagesByConversation = readPinnedMessages(); this.groupPinnedSyncAt = {}; this.hiddenConversationIds = readHiddenConversationIds(); this.activeFavoriteKey = this.favoriteMessages[0]?.key || ''; this.activeId = ''; this.messagesByConversation = {}; this.visibleMessagesByConversation = {}; this.optimisticMessagesByConversation = {}; this.quotedMessage = null; this.forwardingMessages = []; this.editingMessage = null; this.editingText = ''; this.editingMode = ''; this.messageDetailOpen = false; this.messageDetailLoading = false; this.messageDetailError = ''; this.messageDetail = null; this.selectionMode = false; this.selectedMessageIds = []; }, clearUserState() { window.clearInterval(this.syncTimer); window.clearInterval(this.conversationSyncTimer); window.clearTimeout(this.syncAfterSendTimer); window.clearTimeout(this.attentionMessageTimer); window.clearTimeout(this.actionNoticeTimer); window.clearTimeout(this.realtimeSyncTimer); _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__/* .realtimeNotifications */ .w.stop(); this.syncTimer = null; this.conversationSyncTimer = null; this.syncAfterSendTimer = null; this.attentionMessageTimer = null; this.actionNoticeTimer = null; this.realtimeSyncTimer = null; this.syncInFlight = false; this.conversationSyncInFlight = false; this.pendingReadReceiptConversationId = ''; this.activeId = ''; this.conversations = []; this.messagesByConversation = {}; this.visibleMessagesByConversation = {}; this.optimisticMessagesByConversation = {}; this.quotedMessage = null; this.forwardingMessages = []; this.editingMessage = null; this.editingText = ''; this.editingMode = ''; this.messageDetailOpen = false; this.messageDetailLoading = false; this.messageDetailError = ''; this.messageDetail = null; this.attentionMessageId = ''; this.selectionMode = false; this.selectedMessageIds = []; this.favoriteMessages = []; this.hiddenConversationIds = []; this.activeFavoriteKey = ''; this.actionNotice = ''; this.actionError = ''; }, bindImEvents() { if (this.eventsBound) { return; } this.eventsBound = true; _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.on('messageSent', message => { this.appendMessage(message.conversationId, message); }); _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.on('messageReceived', message => { this.appendMessage(message.conversationId, message); if (message.conversationId === this.activeId) { this.scheduleActiveMessagesSync({ allowReadReceipt: true }, 500); } }); _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.on('messageStatusChanged', message => { this.replaceMessage(message.conversationId, message); }); _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.on('conversationsChanged', remoteConversations => { this.usingDemoData = false; this.applyRemoteConversations(remoteConversations); }); }, setActiveConversation(id) { this.activeId = id; const conversation = this.conversations.find(item => item.id === id); if (conversation) { conversation.unread = 0; } this.loadActiveMessages({ allowReadReceipt: true, userAction: true }); }, sendText(payload) { const conversation = this.activeConversation; const text = typeof payload === 'string' ? payload : String(payload?.text || ''); const mentionedUserIds = Array.isArray(payload?.mentionedUserIds) ? payload.mentionedUserIds : []; if (!conversation || !text.trim()) { return; } let value = text.trim(); if (this.quotedMessage) { value = `引用:${quotePrefix(this.quotedMessage)}\n${value}`; this.quotedMessage = null; } const message = { id: randomId(), conversationId: conversation.id, from: 'me', direction: 'out', type: 'text', text: value, status: 'sending', deliveryStatus: 'sending', timestamp: Date.now(), displayTimestamp: Date.now() }; this.appendVisibleMessage(conversation.id, message); this.appendMessage(conversation.id, message); _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.sendTextMessage(conversation, value, message, { mentionedUserIds }); conversation.subtitle = value; conversation.updatedAt = Date.now(); writeLocalConversations(this.conversations); window.clearTimeout(this.syncAfterSendTimer); this.syncAfterSendTimer = window.setTimeout(() => this.syncActiveMessages(), 250); }, sendAttachment({ type, file, text = '' }) { const conversation = this.activeConversation; if (!conversation || !file || !['image', 'file'].includes(type)) { return; } let value = text.trim(); if (this.quotedMessage) { value = `引用:${quotePrefix(this.quotedMessage)}\n${value}`.trim(); this.quotedMessage = null; } const now = Date.now(); const message = { id: randomId(), conversationId: conversation.id, from: 'me', senderRole: conversation.role || conversation.raw?.role || '', direction: 'out', type, text: value, attachment: { type, name: file.name || (type === 'image' ? '图片' : '文件'), mime: file.type || '', size: file.size || 0, url: type === 'image' ? URL.createObjectURL(file) : '' }, status: 'sending', deliveryStatus: 'sending', timestamp: now, displayTimestamp: now }; this.appendVisibleMessage(conversation.id, message); this.appendMessage(conversation.id, message); _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.sendAttachmentMessage(conversation, { type, file, text: value }, message); conversation.subtitle = messagePreviewText(message); conversation.updatedAt = now; writeLocalConversations(this.conversations); window.clearTimeout(this.syncAfterSendTimer); this.syncAfterSendTimer = window.setTimeout(() => this.syncActiveMessages(), 350); }, async sendTextToConversation(conversation, text) { if (!conversation || !text.trim()) { return null; } const value = text.trim(); const message = { id: randomId(), conversationId: conversation.id, from: 'me', direction: 'out', type: 'text', text: value, status: 'sending', deliveryStatus: 'sending', timestamp: Date.now(), displayTimestamp: Date.now() }; this.appendMessage(conversation.id, message); const sentMessage = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.sendTextMessage(conversation, value, message); this.replaceMessage(conversation.id, sentMessage); return sentMessage; }, upsertConversation(conversation) { const index = this.conversations.findIndex(item => item.id === conversation.id); if (index >= 0) { this.conversations.splice(index, 1, { ...this.conversations[index], ...conversation }); } else { this.conversations.unshift(conversation); } this.usingDemoData = false; writeLocalConversations(this.conversations); }, removeConversation(conversationId) { if (!this.hiddenConversationIds.includes(conversationId)) { this.hiddenConversationIds = [...this.hiddenConversationIds, conversationId]; writeHiddenConversationIds(this.hiddenConversationIds); } this.conversations = this.conversations.filter(conversation => conversation.id !== conversationId); const { [conversationId]: removedMessages, ...messagesByConversation } = this.messagesByConversation; const { [conversationId]: removedVisibleMessages, ...visibleMessagesByConversation } = this.visibleMessagesByConversation; const { [conversationId]: removedOptimisticMessages, ...optimisticMessagesByConversation } = this.optimisticMessagesByConversation; void removedMessages; void removedVisibleMessages; void removedOptimisticMessages; this.messagesByConversation = messagesByConversation; this.visibleMessagesByConversation = visibleMessagesByConversation; this.optimisticMessagesByConversation = optimisticMessagesByConversation; if (this.activeId === conversationId) { this.activeId = this.conversations[0]?.id || ''; } writeLocalConversations(this.conversations); if (this.activeId) { this.loadActiveMessages(); } }, applyRemoteConversations(remoteConversations) { const hidden = new Set(this.hiddenConversationIds); const remote = (Array.isArray(remoteConversations) ? remoteConversations : []).filter(conversation => !hidden.has(conversation.id)); if (!remote.length && this.conversations.length) { return; } const merged = new Map(); this.conversations.forEach(conversation => { merged.set(conversation.id, conversation); }); remote.forEach(conversation => { const unread = conversation.id === this.activeId && canMarkReadNow() ? 0 : Number(conversation.unread || 0); merged.set(conversation.id, { ...(merged.get(conversation.id) || {}), ...conversation, unread }); }); this.conversations = sortConversations(Array.from(merged.values())).slice(0, 100); if (!this.conversations.length) { this.activeId = ''; this.messagesByConversation = {}; this.visibleMessagesByConversation = {}; this.optimisticMessagesByConversation = {}; writeLocalConversations(this.conversations); return; } if (!this.conversations.find(item => item.id === this.activeId)) { this.activeId = this.conversations[0].id; } writeLocalConversations(this.conversations); this.loadActiveMessages(); }, togglePinnedConversation(conversationId) { const conversation = this.conversations.find(item => item.id === conversationId); if (!conversation) return; conversation.pinnedAt = Number(conversation.pinnedAt || conversation.top || 0) > 0 ? 0 : Date.now(); conversation.top = conversation.pinnedAt; this.conversations = sortConversations(this.conversations); writeLocalConversations(this.conversations); }, appendMessage(conversationId, message) { if (message?.direction === 'in' && this.hiddenConversationIds.includes(conversationId)) { this.hiddenConversationIds = this.hiddenConversationIds.filter(id => id !== conversationId); writeHiddenConversationIds(this.hiddenConversationIds); } if (!this.messagesByConversation[conversationId]) { this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: [] }; } if (message.direction === 'out' && (message.status === 'sending' || message.status === 'sent')) { this.keepOptimisticMessage(conversationId, message); } if (!hasExactMessage(this.messagesByConversation[conversationId], message)) { this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: [...this.messagesByConversation[conversationId], message] }; } this.updateConversationFromMessage(conversationId, message); this.syncVisibleMessages(conversationId); writeLocalConversations(this.conversations); }, removeMessages(conversationId, messages) { const ids = new Set(messages.flatMap(message => [message.id, message.messageUid].filter(Boolean).map(String))); const filterMessages = list => (list || []).filter(message => { return ![message.id, message.messageUid].filter(Boolean).some(id => ids.has(String(id))); }); this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: filterMessages(this.messagesByConversation[conversationId]) }; this.visibleMessagesByConversation = { ...this.visibleMessagesByConversation, [conversationId]: filterMessages(this.visibleMessagesByConversation[conversationId]) }; this.optimisticMessagesByConversation = { ...this.optimisticMessagesByConversation, [conversationId]: filterMessages(this.optimisticMessagesByConversation[conversationId]) }; this.selectedMessageIds = this.selectedMessageIds.filter(id => !ids.has(String(id))); }, replaceLocalMessage(conversationId, targetMessage, nextMessage) { const keys = new Set([targetMessage.id, targetMessage.messageUid].filter(Boolean).map(String)); const replaceInList = list => (list || []).map(message => { const matched = [message.id, message.messageUid].filter(Boolean).some(id => keys.has(String(id))); return matched ? { ...message, ...nextMessage } : message; }); this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: replaceInList(this.messagesByConversation[conversationId]) }; this.visibleMessagesByConversation = { ...this.visibleMessagesByConversation, [conversationId]: replaceInList(this.visibleMessagesByConversation[conversationId]) }; }, updateConversationFromMessage(conversationId, message) { const conversation = this.conversations.find(item => item.id === conversationId); if (!conversation) { return; } conversation.subtitle = message.text || conversation.subtitle || ''; conversation.updatedAt = messageActivityTimestamp(message) || Date.now(); if (message.direction === 'in') { conversation.unread = conversationId === this.activeId ? 0 : Number(conversation.unread || 0) + 1; } this.conversations = [...this.conversations].sort((a, b) => Number(b.updatedAt || 0) - Number(a.updatedAt || 0)); }, appendVisibleMessage(conversationId, message) { const messages = this.visibleMessagesByConversation[conversationId] || []; this.visibleMessagesByConversation = { ...this.visibleMessagesByConversation, [conversationId]: [...messages.filter(item => item.id !== message.id), message].sort((a, b) => Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0)) }; }, replaceMessage(conversationId, message) { if (!this.messagesByConversation[conversationId]) { this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: [] }; } if (message.direction === 'out' && (message.status === 'sending' || message.status === 'sent' || message.status === 'failed')) { this.keepOptimisticMessage(conversationId, message); } const index = this.messagesByConversation[conversationId].findIndex(item => item.id === message.id); if (index >= 0) { const messages = [...this.messagesByConversation[conversationId]]; messages.splice(index, 1, message); this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: messages }; } else { this.messagesByConversation = { ...this.messagesByConversation, [conversationId]: [...this.messagesByConversation[conversationId], message] }; } this.syncVisibleMessages(conversationId); }, syncVisibleMessages(conversationId) { this.visibleMessagesByConversation = { ...this.visibleMessagesByConversation, [conversationId]: mergeVisibleMessages(this.optimisticMessagesByConversation[conversationId] || [], this.messagesByConversation[conversationId] || []) }; }, keepOptimisticMessage(conversationId, message) { if (!this.optimisticMessagesByConversation[conversationId]) { this.optimisticMessagesByConversation = { ...this.optimisticMessagesByConversation, [conversationId]: [] }; } const messages = this.optimisticMessagesByConversation[conversationId]; const index = messages.findIndex(item => item.id === message.id); let nextMessages; if (index >= 0) { nextMessages = [...messages]; nextMessages.splice(index, 1, message); } else { nextMessages = [...messages, message]; } this.optimisticMessagesByConversation = { ...this.optimisticMessagesByConversation, [conversationId]: nextMessages }; }, pruneOptimisticMessages(conversationId, syncedMessages) { const messages = this.optimisticMessagesByConversation[conversationId] || []; if (!messages.length) { return; } this.optimisticMessagesByConversation = { ...this.optimisticMessagesByConversation, [conversationId]: messages.filter(message => { const remoteMatched = syncedMessages.some(syncedMessage => { return syncedMessage.id !== message.id && isSameMessage(syncedMessage, message); }); if (remoteMatched && message.status !== 'failed') { return false; } return Date.now() - Number(message.displayTimestamp || message.timestamp || 0) < 30000 || message.status === 'failed'; }) }; }, loadActiveMessages(options = {}) { const syncOptions = typeof options === 'boolean' ? { allowReadReceipt: options } : options; const conversation = this.activeConversation; if (!conversation) { return; } this.loading = true; const messages = _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.getMessages(conversation, 30); this.pruneOptimisticMessages(conversation.id, messages); this.messagesByConversation = { ...this.messagesByConversation, [conversation.id]: mergeVisibleMessages(this.messagesByConversation[conversation.id] || [], messages) }; this.syncVisibleMessages(conversation.id); this.loading = false; this.syncActiveMessages(syncOptions); }, async syncActiveMessages(options = {}) { const conversation = this.activeConversation; if (!conversation) { return; } const wantsReadReceipt = Boolean(options.allowReadReceipt); const explicitReadReceipt = wantsReadReceipt && canMarkReadNow({ userAction: Boolean(options.userAction) }); const pollingReadReceipt = canMarkReadNow(); const markRead = explicitReadReceipt || pollingReadReceipt; if (this.syncInFlight) { if (wantsReadReceipt) { this.pendingReadReceiptConversationId = conversation.id; } return; } this.syncInFlight = true; const syncedConversationId = conversation.id; const previousMessages = this.messagesByConversation[syncedConversationId] || []; try { const messages = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchRemoteMessages(conversation, 1000, { markRead, includeConversations: Boolean(options.includeConversations) }); const isGroupConversation = ['group', 'channel'].includes(conversation.type) || ['group', 'channel', 1, '1'].includes(conversation.raw?.type); const shouldSyncGroupPin = isGroupConversation && Date.now() - Number(this.groupPinnedSyncAt[syncedConversationId] || 0) >= 3000; if (shouldSyncGroupPin) { try { const nativePins = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchGroupPinnedMessages(conversation); this.groupPinnedSyncAt = { ...this.groupPinnedSyncAt, [syncedConversationId]: Date.now() }; const nextPinned = { ...this.pinnedMessagesByConversation }; if (nativePins.length) { nextPinned[syncedConversationId] = parseNativePinnedMessage(nativePins[0], messages); } else { delete nextPinned[syncedConversationId]; } this.pinnedMessagesByConversation = nextPinned; writePinnedMessages(nextPinned); } catch (error) { console.warn('群置顶消息同步失败', error); } } const remotePinnedKey = String(messages.pinnedMessageUid || ''); if (!isGroupConversation && remotePinnedKey) { const pinnedMessage = messages.find(item => messageStableKey(item) === remotePinnedKey) || messages.pinnedMessage || (this.pinnedMessagesByConversation[syncedConversationId]?.key === remotePinnedKey ? this.pinnedMessagesByConversation[syncedConversationId] : null); this.pinnedMessagesByConversation = { ...this.pinnedMessagesByConversation, [syncedConversationId]: pinnedMessage ? { key: remotePinnedKey, id: remotePinnedKey, text: messagePreviewText(pinnedMessage), type: pinnedMessage.type || 'text', attachment: pinnedMessage.attachment ? { ...pinnedMessage.attachment } : null, senderName: pinnedMessage.senderName || pinnedMessage.from || '', timestamp: Number(pinnedMessage.displayTimestamp || pinnedMessage.timestamp || Date.now()) } : { key: remotePinnedKey, id: remotePinnedKey, text: '[置顶消息]' } }; writePinnedMessages(this.pinnedMessagesByConversation); } const editedIncomingMessages = incomingEditedMessages(previousMessages, messages); this.pruneOptimisticMessages(syncedConversationId, messages); this.messagesByConversation = { ...this.messagesByConversation, [syncedConversationId]: mergeVisibleMessages(this.messagesByConversation[syncedConversationId] || [], messages) }; this.syncVisibleMessages(syncedConversationId); if (editedIncomingMessages.length && syncedConversationId === this.activeId) { this.focusMessage(editedIncomingMessages.sort((a, b) => messageActivityTimestamp(b) - messageActivityTimestamp(a))[0]); playNotificationSound(); } const latest = messages.reduce((latestMessage, message) => { if (!latestMessage || messageActivityTimestamp(message) > messageActivityTimestamp(latestMessage)) { return message; } return latestMessage; }, null); if (latest) { conversation.subtitle = messagePreviewText(latest); conversation.updatedAt = messageActivityTimestamp(latest); writeLocalConversations(this.conversations); } } catch (error) { // Keep the local view usable if a polling request misses. } finally { this.syncInFlight = false; if (this.pendingReadReceiptConversationId === this.activeId && canMarkReadNow()) { this.pendingReadReceiptConversationId = ''; window.setTimeout(() => this.syncActiveMessages({ allowReadReceipt: true }), 0); } } }, scheduleActiveMessagesSync(options = {}, delay = 500) { if (!this.activeId || typeof document !== 'undefined' && document.visibilityState !== 'visible') { return; } window.clearTimeout(this.syncAfterSendTimer); this.syncAfterSendTimer = window.setTimeout(() => { this.syncAfterSendTimer = null; this.syncActiveMessages(options); }, Math.max(0, Number(delay) || 0)); }, startMessageSync() { this.bindReadPresenceEvents(); if (!this.syncTimer) { this.syncTimer = window.setInterval(() => { if (document.visibilityState === 'visible' && !_services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__/* .realtimeNotifications */ .w.isConnected()) { this.syncActiveMessages(); } }, Math.max(250, _config__WEBPACK_IMPORTED_MODULE_21__/* .appConfig */ .U.syncIntervalMs)); } if (!this.conversationSyncTimer) { this.conversationSyncTimer = window.setInterval(() => { if (document.visibilityState === 'visible' && !_services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__/* .realtimeNotifications */ .w.isConnected()) { this.refreshRemoteConversations(); } }, Math.max(5000, _config__WEBPACK_IMPORTED_MODULE_21__/* .appConfig */ .U.syncIntervalMs * 2)); this.refreshRemoteConversations(); } }, handleRealtimeNotification() { window.clearTimeout(this.realtimeSyncTimer); this.realtimeSyncTimer = window.setTimeout(() => { this.refreshRemoteConversations(); this.scheduleActiveMessagesSync({ allowReadReceipt: canMarkReadNow(), includeConversations: true }, 300); }, 300); }, bindReadPresenceEvents() { if (this.readPresenceEventsBound || typeof window === 'undefined' || typeof document === 'undefined') { return; } this.readPresenceEventsBound = true; const syncWhenReadable = () => { if (canMarkReadNow()) { this.refreshRemoteConversations(); this.scheduleActiveMessagesSync({ allowReadReceipt: true }, 200); } }; window.addEventListener('focus', syncWhenReadable); document.addEventListener('visibilitychange', syncWhenReadable); }, async refreshRemoteConversations() { this.bindImEvents(); this.usingDemoData = false; if (this.conversationSyncInFlight) { return; } this.conversationSyncInFlight = true; try { const remoteConversations = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchRemoteConversations(50); this.applyRemoteConversations(remoteConversations); } catch (error) { _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.refreshConversationList(); } finally { this.conversationSyncInFlight = false; } }, setActionNotice(message) { this.actionNotice = message; this.actionError = ''; window.clearTimeout(this.actionNoticeTimer); this.actionNoticeTimer = window.setTimeout(() => { this.actionNotice = ''; this.actionNoticeTimer = null; }, 3000); }, setActionError(message) { this.actionError = message; this.actionNotice = ''; window.clearTimeout(this.actionNoticeTimer); this.actionNoticeTimer = window.setTimeout(() => { this.actionError = ''; this.actionNoticeTimer = null; }, 3000); }, focusMessage(message) { const key = messageStableKey(message); if (!key) { return; } this.attentionMessageId = key; window.clearTimeout(this.attentionMessageTimer); this.attentionMessageTimer = window.setTimeout(() => { if (this.attentionMessageId === key) { this.attentionMessageId = ''; } }, 2800); }, async handleMessageAction({ action, message }) { if (!message) { return; } if (action === 'copy') { await this.copyMessages([message]); } else if (action === 'edit') { this.startEditMessage(message); } else if (action === 'delete') { this.deleteMessages([message]); } else if (action === 'forward') { this.startForward([message]); } else if (action === 'favorite') { this.toggleFavorite(message); } else if (action === 'pin') { this.togglePinnedMessage(message); } else if (action === 'detail') { await this.openMessageDetail(message); } else if (action === 'quote') { this.quoteMessage(message); } else if (action === 'select') { this.enterSelectionMode(message); } else if (action === 'recall') { await this.recallMessage(message); } }, async openMessageDetail(message) { const conversation = this.activeConversation; if (!conversation || !message) { return; } const key = messageStableKey(message); this.messageDetailOpen = true; this.messageDetailLoading = true; this.messageDetailError = ''; this.messageDetail = { messageUid: key, conversationType: conversation.type || conversation.raw?.type || 'single', sentAt: Number(message.displayTimestamp || message.timestamp || 0), editedAt: Number(message.editedAt || 0), recalled: isRecalledMessage(message), localOnly: true, sender: { uid: message.from || '', name: message.senderName || message.from || '' } }; try { if (!/^\d+$/.test(key)) { this.messageDetailError = '本地临时消息暂无送达/已读详情'; return; } const detail = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.getMessageDetail(conversation, message); this.messageDetail = detail || this.messageDetail; } catch (error) { this.messageDetailError = error.message || '消息详情加载失败'; } finally { this.messageDetailLoading = false; } }, closeMessageDetail() { this.messageDetailOpen = false; this.messageDetailLoading = false; this.messageDetailError = ''; this.messageDetail = null; }, async copyMessages(messages) { const text = messages.map(message => message.text || '').join('\n'); if (!text.trim()) { return; } try { await writeClipboard(text); this.setActionNotice(messages.length > 1 ? '已复制所选消息' : '已复制'); } catch (error) { this.setActionError('复制失败'); } }, deleteMessages(messages) { const conversation = this.activeConversation; if (!conversation || !messages.length) { return; } _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.hideMessages(conversation, messages); this.removeMessages(conversation.id, messages); if (!this.selectedMessageIds.length) { this.selectionMode = false; } this.setActionNotice(messages.length > 1 ? '已删除所选消息' : '已删除'); }, toggleFavorite(message) { const key = messageStableKey(message); if (!key) { return; } const index = this.favoriteMessages.findIndex(item => item.key === key); if (index >= 0) { this.favoriteMessages.splice(index, 1); if (this.activeFavoriteKey === key) { this.activeFavoriteKey = this.favoriteMessages[0]?.key || ''; } this.setActionNotice('已取消收藏'); } else { const conversation = this.conversations.find(item => item.id === message.conversationId) || {}; this.favoriteMessages.unshift({ key, id: message.id, messageUid: message.messageUid, conversationId: message.conversationId, conversationTitle: conversation.title || message.conversationTitle || '', type: message.type || 'text', text: message.text || '', preview: messagePreviewText(message), senderName: message.senderName || message.from || '', timestamp: Number(message.displayTimestamp || message.timestamp || Date.now()), editedAt: Number(message.editedAt || 0), recalled: isRecalledMessage(message), recallStatus: message.recallStatus || (isRecalledMessage(message) ? '已撤回' : ''), attachment: message.attachment ? { ...message.attachment } : null }); this.activeFavoriteKey = key; this.setActionNotice('已收藏'); } this.favoriteMessages = this.favoriteMessages.slice(0, 200); writeFavoriteMessages(this.favoriteMessages); }, async togglePinnedMessage(message) { const conversationId = message?.conversationId || this.activeId; const key = messageStableKey(message); if (!conversationId || !key) return; const current = this.pinnedMessagesByConversation[conversationId]; const next = { ...this.pinnedMessagesByConversation }; if (current && current.key === key) { delete next[conversationId]; this.pinnedMessagesByConversation = next; writePinnedMessages(next); this.setActionNotice('已取消置顶'); try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.setPinnedMessage(this.activeConversation, '', current); } catch (error) { this.setActionError(`已在本地取消,服务器同步失败:${error.message || '取消置顶失败'}`); } } else { next[conversationId] = { key, id: key, text: messagePreviewText(message), type: message.type || 'text', attachment: message.attachment ? { ...message.attachment } : null, senderName: message.senderName || message.from || '', timestamp: Number(message.displayTimestamp || message.timestamp || Date.now()) }; this.pinnedMessagesByConversation = next; writePinnedMessages(next); this.setActionNotice('消息已置顶'); try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.setPinnedMessage(this.activeConversation, key, message); const nativePins = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.fetchGroupPinnedMessages(this.activeConversation).catch(() => []); if (nativePins.length) { const refreshed = parseNativePinnedMessage(nativePins[0], this.activeMessages); this.pinnedMessagesByConversation = { ...this.pinnedMessagesByConversation, [conversationId]: refreshed }; writePinnedMessages(this.pinnedMessagesByConversation); } } catch (error) { const rollback = { ...this.pinnedMessagesByConversation }; delete rollback[conversationId]; this.pinnedMessagesByConversation = rollback; writePinnedMessages(rollback); this.setActionError(`置顶失败:${error.message || '服务器同步失败'}`); } } }, async clearPinnedMessage() { const current = this.pinnedMessagesByConversation[this.activeId] || null; const next = { ...this.pinnedMessagesByConversation }; delete next[this.activeId]; this.pinnedMessagesByConversation = next; writePinnedMessages(next); this.setActionNotice('已取消置顶'); try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.setPinnedMessage(this.activeConversation, '', current); } catch (error) { this.setActionError(`已在本地取消,服务器同步失败:${error.message || '取消置顶失败'}`); } }, setActiveFavorite(key) { this.activeFavoriteKey = String(key || ''); }, removeFavorite(key) { const value = String(key || ''); if (!value) { return; } this.favoriteMessages = this.favoriteMessages.filter(message => message.key !== value); if (this.activeFavoriteKey === value) { this.activeFavoriteKey = this.favoriteMessages[0]?.key || ''; } writeFavoriteMessages(this.favoriteMessages); }, quoteMessage(message) { this.quotedMessage = { ...message, quoteText: quotePrefix(message) }; this.setActionNotice('已引用,输入后发送'); }, cancelQuote() { this.quotedMessage = null; }, enterSelectionMode(message = null) { this.selectionMode = true; if (message) { const key = messageStableKey(message); this.selectedMessageIds = key ? [key] : []; } }, toggleSelectedMessage(message) { const key = messageStableKey(message); if (!key) { return; } const selected = new Set(this.selectedMessageIds); if (selected.has(key)) { selected.delete(key); } else { selected.add(key); } this.selectedMessageIds = Array.from(selected); this.selectionMode = this.selectedMessageIds.length > 0; }, clearSelection() { this.selectionMode = false; this.selectedMessageIds = []; }, copySelectedMessages() { return this.copyMessages(this.selectedMessages); }, deleteSelectedMessages() { this.deleteMessages(this.selectedMessages); }, startForward(messages) { this.forwardingMessages = messages.filter(message => message?.text || message?.attachment?.url); if (!this.forwardingMessages.length) { this.setActionError('没有可转发的消息'); } }, startForwardSelectedMessages() { this.startForward(this.selectedMessages); }, cancelForward() { this.forwardingMessages = []; }, startEditMessage(message) { const isResend = isRecalledMessage(message); if (!isResend && !message?.text) { this.setActionError('没有可编辑的文字内容'); return; } this.editingMessage = message; this.editingText = message.text || ''; this.editingMode = isResend ? 'resend' : 'edit'; }, cancelEditMessage() { this.editingMessage = null; this.editingText = ''; this.editingMode = ''; }, async completeEditMessage() { const conversation = this.activeConversation; const message = this.editingMessage; const text = this.editingText.trim(); const isResend = this.editingMode === 'resend' || isRecalledMessage(message); if (!conversation || !message) { this.cancelEditMessage(); return; } if (!text) { this.setActionError('编辑内容不能为空'); return; } if (!isResend && text === String(message.text || '').trim()) { this.cancelEditMessage(); return; } try { if (isResend) { await this.sendTextToConversation(conversation, text); this.cancelEditMessage(); this.setActionNotice('已重新发送'); return; } const editedMessage = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.editMessage(conversation, message, text); this.replaceLocalMessage(conversation.id, message, editedMessage); if (messageActivityTimestamp(editedMessage) >= Number(conversation.updatedAt || 0)) { conversation.subtitle = editedMessage.text; conversation.updatedAt = messageActivityTimestamp(editedMessage); writeLocalConversations(this.conversations); } this.cancelEditMessage(); this.setActionNotice('已编辑'); } catch (error) { this.setActionError(error.message || '编辑失败'); } }, async completeForward(targetConversationId) { const target = this.conversations.find(conversation => conversation.id === targetConversationId); if (!target || !this.forwardingMessages.length) { return; } const messages = [...this.forwardingMessages]; let successCount = 0; const errors = []; for (const message of messages) { try { if (message.attachment?.url) { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.forwardAttachmentMessage(target, message); } else if (message.text) { const text = forwardedText(message); if (!text) { throw new Error('消息内容为空'); } const sentMessage = await this.sendTextToConversation(target, text); if (sentMessage?.status === 'failed') { throw new Error(sentMessage.error || '转发失败'); } } successCount += 1; } catch (error) { errors.push(error.message || '转发失败'); } } if (successCount > 0) { this.forwardingMessages = []; this.clearSelection(); this.refreshRemoteConversations(); } if (errors.length) { this.setActionError(`成功 ${successCount} 条,失败 ${errors.length} 条:${errors[0]}`); } else { this.setActionNotice(`已转发 ${successCount} 条`); } }, async recallMessage(message) { const conversation = this.activeConversation; if (!conversation) { return; } try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.recallMessage(conversation, message); if (message.direction !== 'out') { this.removeMessages(conversation.id, [message]); this.setActionNotice('已撤回'); this.syncActiveMessages(); return; } this.replaceLocalMessage(conversation.id, message, { status: 'recalled', deliveryStatus: '', recalled: true, recallStatus: '已撤回' }); this.setActionNotice('已撤回'); } catch (error) { this.setActionError(error.message || '撤回失败'); } }, async createGroup(options = {}) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); if (!session.userId) { this.setActionError('请先登录'); return false; } try { const conversation = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.createGroup(session.userId, options); this.upsertConversation(conversation); this.setActiveConversation(conversation.id); this.setActionNotice(options.channel ? '公告群已创建' : '群组已创建'); this.refreshRemoteConversations(); return true; } catch (error) { this.setActionError(error.message || (options.channel ? '创建公告群失败' : '创建群组失败')); return false; } }, async joinGroup(groupKey) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); if (!session.userId) { this.setActionError('请先登录'); return false; } try { const conversation = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.joinGroup(session.userId, groupKey); this.upsertConversation(conversation); this.setActiveConversation(conversation.id); this.setActionNotice('已加入群组'); this.refreshRemoteConversations(); return true; } catch (error) { this.setActionError(error.message || '加入群组失败'); return false; } }, async broadcastMessage(targetIds, text) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); if (!session.userId) { this.setActionError('请先登录'); return false; } try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.broadcastMessage(session.userId, targetIds, text); const successCount = Number(result.successCount || 0); const failedCount = Number(result.failedCount || 0); this.setActionNotice(failedCount > 0 ? `已群发 ${successCount} 条,失败 ${failedCount} 条` : `已群发 ${successCount} 条`); this.refreshRemoteConversations(); return true; } catch (error) { this.setActionError(error.message || '群发失败'); return false; } }, async leaveGroup(conversation) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); if (!session.userId || !conversation?.target) { this.setActionError('缺少群组信息'); return false; } try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.leaveGroup(session.userId, conversation.target); this.removeConversation(conversation.id); this.setActionNotice('已退出群组'); this.refreshRemoteConversations(); return true; } catch (error) { this.setActionError(error.message || '退出群组失败'); return false; } }, async dismissGroup(conversation) { const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__/* .useSessionStore */ .B)(); if (!session.userId || !conversation?.target) { this.setActionError('缺少群组信息'); return false; } try { await _services_imClient__WEBPACK_IMPORTED_MODULE_20__/* .imClient */ .wD.dismissGroup(session.userId, conversation.target); this.removeConversation(conversation.id); this.setActionNotice('群组已解散'); this.refreshRemoteConversations(); return true; } catch (error) { this.setActionError(error.message || '解散群组失败'); return false; } } } }); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "w", 0, /* binding */ useConversationStore /* harmony export */ ]); /***/ }), /***/ 1414: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2261); const useNavigationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_0__/* .defineStore */ .nY)('navigation', { state: () => ({ section: 'messages' }), actions: { showMessages() { this.section = 'messages'; }, showContacts() { this.section = 'contacts'; }, showFavorites() { this.section = 'favorites'; } } }); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "l", 0, /* binding */ useNavigationStore /* harmony export */ ]); /***/ }), /***/ 926: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4423); /* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2261); /* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5051); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2169); const STORAGE_KEY = 'qmt-web-im-session'; function normalizeStoredPortrait(portrait) { return portrait || ''; } function nextProfilePortrait(profilePortrait, currentPortrait) { return normalizeStoredPortrait(profilePortrait) || normalizeStoredPortrait(currentPortrait); } function inferAccountType(account) { return String(account || '').includes('@') ? 2 : 1; } const useSessionStore = (0,pinia__WEBPACK_IMPORTED_MODULE_1__/* .defineStore */ .nY)('session', { state: () => ({ isAuthenticated: false, connecting: false, connected: false, connectionStatusText: '未连接', userId: '', token: '', displayName: '', portrait: '', error: '', sdkVersion: '', eventsBound: false }), actions: { restore() { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) { return; } try { const session = JSON.parse(raw); if (session.appServer !== _config__WEBPACK_IMPORTED_MODULE_3__/* .appConfig */ .U.appServer) { localStorage.removeItem(STORAGE_KEY); return; } if (session.userId && session.token) { if (!session.clientId) { localStorage.removeItem(STORAGE_KEY); return; } this.userId = session.userId; this.token = session.token; this.displayName = session.displayName || session.userId; this.portrait = normalizeStoredPortrait(session.portrait); this.isAuthenticated = true; _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.restoreClientId(session.clientId); this.connect(); this.refreshProfile(); } } catch (error) { localStorage.removeItem(STORAGE_KEY); } }, async loginWithPassword(account, password, type = inferAccountType(account)) { this.error = ''; this.connecting = true; try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.loginWithPassword(account, password, type); this.applyLoginResult(result); await this.connect(); } catch (error) { this.error = error.message || '登录失败'; } finally { this.connecting = false; } }, async loginWithCode(account, code) { this.error = ''; this.connecting = true; try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.loginWithCode(account, code); this.applyLoginResult(result); await this.connect(); } catch (error) { this.error = error.message || '登录失败'; } finally { this.connecting = false; } }, async completePcSessionLogin(result) { this.error = ''; this.connecting = true; try { this.applyLoginResult(result); await this.connect(); } catch (error) { this.error = error.message || '扫码登录失败'; } finally { this.connecting = false; } }, async register(payload) { this.error = ''; this.connecting = true; try { const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.register(payload); this.applyLoginResult(result); await this.connect(); return result; } catch (error) { this.error = error.message || '注册失败'; return null; } finally { this.connecting = false; } }, applyLoginResult(result) { this.userId = result.userId || result.uid || result.id || ''; this.token = result.token || result.imToken || ''; this.displayName = result.displayName || result.userName || result.name || this.userId; this.portrait = normalizeStoredPortrait(result.portrait); this.isAuthenticated = Boolean(this.userId && this.token); this.persistSession(); }, persistSession() { localStorage.setItem(STORAGE_KEY, JSON.stringify({ userId: this.userId, token: this.token, displayName: this.displayName, portrait: this.portrait, clientId: _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.getClientId(), appServer: _config__WEBPACK_IMPORTED_MODULE_3__/* .appConfig */ .U.appServer })); }, applyProfile(profile) { if (!profile) { return; } this.userId = profile.userId || profile.uid || this.userId; this.displayName = profile.displayName || profile.name || this.displayName || this.userId; this.portrait = nextProfilePortrait(profile.portrait, this.portrait); this.persistSession(); }, async refreshProfile() { if (!this.userId) { return null; } try { const profile = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.getProfile(this.userId); this.applyProfile(profile); return profile; } catch (error) { return null; } }, async saveProfile({ displayName, portraitFile }) { if (!this.userId) { throw new Error('请先登录'); } const profile = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.updateProfile(this.userId, { displayName, portraitFile }); this.applyProfile(profile); return profile; }, async changePassword({ oldPassword, newPassword }) { if (!this.userId) { throw new Error('请先登录'); } await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.changePassword({ oldPassword, newPassword }); await this.logout(); return true; }, async resetPasswordWithCode({ mobile, resetCode, newPassword }) { await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.resetPasswordWithCode({ mobile, resetCode, newPassword }); return true; }, async connect() { if (!this.userId || !this.token) { return; } await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.ensureSdk(); this.sdkVersion = _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.getSdkVersion(); this.bindImEvents(); await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.connect(this.userId, this.token); }, bindImEvents() { if (this.eventsBound) { return; } this.eventsBound = true; _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.on('connectionStatusChanged', status => { this.connected = status.connected; this.connectionStatusText = status.statusText || (status.connected ? '已连接' : '未连接'); }); }, async logout() { try { await _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.logout?.(); } catch (error) { this.error = error.message || '退出登录失败'; } finally { _services_imClient__WEBPACK_IMPORTED_MODULE_2__/* .imClient */ .wD.disconnect(); localStorage.removeItem(STORAGE_KEY); this.$reset(); } } } }); /* harmony export */ __webpack_require__.d(__webpack_exports__, [ /* harmony export */ "B", 0, /* binding */ useSessionStore /* harmony export */ ]); /***/ }), /***/ 7067: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4208); const __exports__ = _App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 9531: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6736); const __exports__ = _ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 3727: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4524); const __exports__ = _LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 7014: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9843); const __exports__ = _ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 1653: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5990); const __exports__ = _MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 9847: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3172); const __exports__ = _MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 3351: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9828); const __exports__ = _ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 163: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1880); const __exports__ = _FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 9123: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8040); const __exports__ = _FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 578: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(103); const __exports__ = _ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 371: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5896); const __exports__ = _ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 8328: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony import */ var _NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1169); const __exports__ = _NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .A; /* harmony default export */ __webpack_exports__.A = (__exports__); /***/ }), /***/ 4208: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4677); /***/ }), /***/ 6736: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2511); /***/ }), /***/ 4524: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8607); /***/ }), /***/ 9843: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7562); /***/ }), /***/ 5990: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6935); /***/ }), /***/ 3172: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4021); /***/ }), /***/ 9828: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3915); /***/ }), /***/ 1880: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9829); /***/ }), /***/ 8040: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6415); /***/ }), /***/ 103: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5684); /***/ }), /***/ 5896: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4621); /***/ }), /***/ 1169: /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: function() { return /* reexport safe */ _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__.A; } /* harmony export */ }); /* harmony import */ var _node_modules_thread_loader_dist_cjs_js_node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_1_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7420); /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ /******/ /* webpack/runtime/chunk loaded */ /******/ !function() { /******/ var deferred = []; /******/ __webpack_require__.O = function(result, chunkIds, fn, priority) { /******/ if(chunkIds) { /******/ priority = priority || 0; /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1]; /******/ deferred[i] = [chunkIds, fn, priority]; /******/ return; /******/ } /******/ var notFulfilled = Infinity; /******/ for (var i = 0; i < deferred.length; i++) { /******/ var chunkIds = deferred[i][0]; /******/ var fn = deferred[i][1]; /******/ var priority = deferred[i][2]; /******/ var fulfilled = true; /******/ for (var j = 0; j < chunkIds.length; j++) { /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) { /******/ chunkIds.splice(j--, 1); /******/ } else { /******/ fulfilled = false; /******/ if(priority < notFulfilled) notFulfilled = priority; /******/ } /******/ } /******/ if(fulfilled) { /******/ deferred.splice(i--, 1) /******/ var r = fn(); /******/ if (r !== undefined) result = r; /******/ } /******/ } /******/ return result; /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/compat get default export */ /******/ !function() { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function() { return module['default']; } : /******/ function() { return module; }; /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ !function() { /******/ // define getter/value functions for harmony exports /******/ __webpack_require__.d = function(exports, definition) { /******/ if(Array.isArray(definition)) { /******/ var i = 0; /******/ while(i < definition.length) { /******/ var key = definition[i++]; /******/ var binding = definition[i++]; /******/ if(!__webpack_require__.o(exports, key)) { /******/ if(binding === 0) { /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] }); /******/ } else { /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding }); /******/ } /******/ } else if(binding === 0) { i++; } /******/ } /******/ } else { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ } /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/global */ /******/ !function() { /******/ __webpack_require__.g = (function() { /******/ if (typeof globalThis === 'object') return globalThis; /******/ try { /******/ return this || new Function('return this')(); /******/ } catch (e) { /******/ if (typeof window === 'object') return window; /******/ } /******/ })(); /******/ }(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ !function() { /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } /******/ }(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ !function() { /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/set anonymous default export name */ /******/ !function() { /******/ // set .name for anonymous default exports per ES spec /******/ __webpack_require__.dn = function(x) { /******/ (Object.getOwnPropertyDescriptor(x, "name") || {}).writable || Object.defineProperty(x, "name", { value: "default", configurable: true }); /******/ }; /******/ }(); /******/ /******/ /* webpack/runtime/jsonp chunk loading */ /******/ !function() { /******/ // no baseURI /******/ /******/ // object to store loaded and loading chunks /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched /******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded /******/ var installedChunks = { /******/ 524: 0 /******/ }; /******/ /******/ // no chunk on demand loading /******/ /******/ // no prefetching /******/ /******/ // no preloaded /******/ /******/ // no HMR /******/ /******/ // no HMR manifest /******/ /******/ __webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; }; /******/ /******/ // install a JSONP callback for chunk loading /******/ var webpackJsonpCallback = function(parentChunkLoadingFunction, data) { /******/ var chunkIds = data[0]; /******/ var moreModules = data[1]; /******/ var runtime = data[2]; /******/ // add "moreModules" to the modules object, /******/ // then flag all "chunkIds" as loaded and fire callback /******/ var moduleId, chunkId, i = 0; /******/ if(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) { /******/ for(moduleId in moreModules) { /******/ if(__webpack_require__.o(moreModules, moduleId)) { /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; /******/ } /******/ } /******/ if(runtime) var result = runtime(__webpack_require__); /******/ } /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); /******/ for(;i < chunkIds.length; i++) { /******/ chunkId = chunkIds[i]; /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { /******/ installedChunks[chunkId][0](); /******/ } /******/ installedChunks[chunkId] = 0; /******/ } /******/ return __webpack_require__.O(result); /******/ } /******/ /******/ var chunkLoadingGlobal = self["webpackChunkjc_web_im"] = self["webpackChunkjc_web_im"] || []; /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); /******/ }(); /******/ /************************************************************************/ /******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module depends on other loaded chunks and execution need to be delayed /******/ var __webpack_exports__ = __webpack_require__.O(undefined, [504], function() { return __webpack_require__(1406); }) /******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__); /******/ /******/ })() ; //# sourceMappingURL=app.21e75967.js.map