Files
2026-10-09 22:49:53 +07:00

3213 lines
142 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******/ (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_DocumentedShell_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8409);
/* 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_DocumentedShell_vue__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A, {
key: 1
}));
};
}
});
/***/ }),
/***/ 865:
/***/ (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_session__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(926);
/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(2169);
const _hoisted_1 = {
class: "documented-shell"
};
const _hoisted_2 = {
class: "documented-rail"
};
const _hoisted_3 = {
class: "documented-avatar"
};
const _hoisted_4 = ["src"];
const _hoisted_5 = {
key: 1
};
const _hoisted_6 = {
class: "documented-rail-copy"
};
const _hoisted_7 = {
class: "documented-main"
};
const _hoisted_8 = {
class: "documented-header"
};
const _hoisted_9 = {
class: "documented-status"
};
const _hoisted_10 = {
class: "documented-card"
};
const _hoisted_11 = {
class: "documented-meta"
};
const _hoisted_12 = {
key: 0,
class: "form-error"
};
const _hoisted_13 = {
key: 1,
class: "form-info"
};
const _hoisted_14 = {
class: "modal-actions"
};
const _hoisted_15 = ["disabled"];
const _hoisted_16 = ["disabled"];
/* harmony default export */ __webpack_exports__.A = ({
__name: 'DocumentedShell',
setup(__props) {
const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_4__/* .useSessionStore */ .B)();
const passwordDialogOpen = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(false);
const passwordSaving = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)(false);
const passwordError = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)('');
const passwordNotice = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .ref */ .KR)('');
const passwordDraft = (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .reactive */ .Kh)({
oldPassword: '',
newPassword: '',
confirmPassword: ''
});
const initials = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .computed */ .EW)(() => String(session.displayName || session.userId || 'U').slice(0, 1).toUpperCase());
function resetPasswordDraft() {
passwordDraft.oldPassword = '';
passwordDraft.newPassword = '';
passwordDraft.confirmPassword = '';
}
function openPasswordDialog() {
passwordError.value = '';
passwordNotice.value = '';
resetPasswordDraft();
passwordDialogOpen.value = true;
}
function closePasswordDialog() {
if (passwordSaving.value) {
return;
}
passwordDialogOpen.value = false;
passwordError.value = '';
passwordNotice.value = '';
resetPasswordDraft();
}
async function savePassword() {
passwordError.value = '';
passwordNotice.value = '';
if (!passwordDraft.oldPassword || !passwordDraft.newPassword || !passwordDraft.confirmPassword) {
passwordError.value = '请填写完整密码';
return;
}
if (passwordDraft.newPassword !== passwordDraft.confirmPassword) {
passwordError.value = '两次输入的新密码不一致';
return;
}
if (passwordDraft.oldPassword === passwordDraft.newPassword) {
passwordError.value = '新密码不能与当前密码相同';
return;
}
passwordSaving.value = true;
try {
await session.changePassword({
oldPassword: passwordDraft.oldPassword,
newPassword: passwordDraft.newPassword
});
passwordNotice.value = '密码已修改,当前登录态会按文档要求失效。';
} catch (error) {
passwordError.value = error.message || '密码修改失败';
} finally {
passwordSaving.value = false;
}
}
async function logout() {
await session.logout();
}
return (_ctx, _cache) => {
return (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("main", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("aside", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("img", {
key: 0,
src: (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).portrait,
alt: ""
}, null, 8, _hoisted_4)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("span", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(initials.value), 1))]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).displayName || (0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).userId), 1), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("small", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).userId), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", {
class: "documented-rail-button",
type: "button",
onClick: openPasswordDialog
}, "修改密码"), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", {
class: "documented-rail-button ghost",
type: "button",
onClick: logout
}, "退出登录")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("section", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("header", _hoisted_8, [_cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("h1", null, "文档对接模式"), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("p", null, "当前界面只保留这两份文档已经明确提供的能力。")], -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_9, [_cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("span", null, "连接状态", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("strong", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).connectionStatusText || '已登录'), 1)])]), _cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createStaticVNode */ .Fv)("<section class=\"documented-card\"><h2>已按文档接入</h2><ul class=\"documented-list\"><li>`/auth/login_pwd` 密码登录</li><li>`/auth/register` 注册并返回 `imToken`、`accessToken`、`refreshToken`</li><li>`/auth/sendEmailCode` 邮箱验证码</li><li>`/auth/refreshToken` 过期自动刷新</li><li>`/auth/changePassword` 修改密码</li><li>`/auth/logout` 退出登录</li><li>扫码登录兼容接口:`/pc_session` 与 `/session_login/{token}`</li><li>AES-128-CBC 请求加密、响应解密、`X-Timestamp`、排除路径规则</li></ul></section><section class=\"documented-card\"><h2>当前按 1 比 1 已停用</h2><p class=\"documented-text\">下面这些旧页面功能已经不再走本地 PHP 或旧接口,因为你给的文档里没有对应定义。</p><ul class=\"documented-list muted\"><li>会话列表与消息列表</li><li>发送文字、图片、文件消息</li><li>联系人列表、添加联系人、备注</li><li>群详情、群成员、群管理</li><li>个人资料编辑与头像上传</li></ul></section>", 2)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("section", _hoisted_10, [_cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("h2", null, "当前登录态", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dl", _hoisted_11, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "用户 ID", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).userId || '-'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[6] || (_cache[6] = (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_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).displayName || '-'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "IM Token", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(session).token ? '已保存' : '未保存'), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[8] || (_cache[8] = (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dt", null, "App Server", -1)), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("dd", null, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(_config__WEBPACK_IMPORTED_MODULE_5__/* .appConfig */ .U).appServer), 1)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", null, [_cache[9] || (_cache[9] = (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_)((0,vue__WEBPACK_IMPORTED_MODULE_2__/* .unref */ .R1)(_config__WEBPACK_IMPORTED_MODULE_5__/* .appConfig */ .U).qrAppServer), 1)])])])]), passwordDialogOpen.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("div", {
key: 0,
class: "modal-backdrop",
onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .withModifiers */ .D$)(closePasswordDialog, ["self"])
}, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("form", {
class: "modal-panel documented-password-panel",
onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__/* .withModifiers */ .D$)(savePassword, ["prevent"])
}, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("header", null, [_cache[12] || (_cache[12] = (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: closePasswordDialog
}, "×")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("label", null, [_cache[13] || (_cache[13] = (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[0] || (_cache[0] = $event => passwordDraft.oldPassword = $event),
type: "password",
autocomplete: "current-password"
}, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_0__/* .vModelText */ .Jo, passwordDraft.oldPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("label", null, [_cache[14] || (_cache[14] = (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[1] || (_cache[1] = $event => passwordDraft.newPassword = $event),
type: "password",
autocomplete: "new-password"
}, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_0__/* .vModelText */ .Jo, passwordDraft.newPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("label", null, [_cache[15] || (_cache[15] = (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 => passwordDraft.confirmPassword = $event),
type: "password",
autocomplete: "new-password"
}, null, 512), [[vue__WEBPACK_IMPORTED_MODULE_0__/* .vModelText */ .Jo, passwordDraft.confirmPassword]])]), passwordError.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("p", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(passwordError.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createCommentVNode */ .Q3)("", true), passwordNotice.value ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__/* .openBlock */ .uX)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementBlock */ .CE)("p", _hoisted_13, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(passwordNotice.value), 1)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createCommentVNode */ .Q3)("", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("div", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", {
type: "button",
class: "ghost-inline-action",
disabled: passwordSaving.value,
onClick: closePasswordDialog
}, "取消", 8, _hoisted_15), (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createElementVNode */ .Lk)("button", {
class: "primary-inline-action",
disabled: passwordSaving.value
}, (0,vue__WEBPACK_IMPORTED_MODULE_3__/* .toDisplayString */ .v_)(passwordSaving.value ? '保存中...' : '保存'), 9, _hoisted_16)])], 32)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__/* .createCommentVNode */ .Q3)("", true)]);
};
}
});
/***/ }),
/***/ 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);
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)('');
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
}, " 返回登录 "))])]);
};
}
});
/***/ }),
/***/ 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),
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;
}
return message.status === 'sending' || message.status === 'failed';
});
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 deviceId = getUniqueEquipment(mobile, this.getClientId());
const response = await axios__WEBPACK_IMPORTED_MODULE_17__/* ["default"] */ .A.post(url, {
mobile,
password,
platform: _config__WEBPACK_IMPORTED_MODULE_18__/* .appConfig */ .U.platform,
clientId: deviceId,
uniqueEquipment: deviceId
}, {
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 deviceId = getUniqueEquipment(mobile, this.getClientId());
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;
}
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)
}, {
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
}));
const userId = this.currentUser?.userId || '';
const messagesByConversation = readLocalMessages(userId);
messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);
writeLocalMessages(messagesByConversation, userId);
return messagesByConversation[conversation.id];
}
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) {
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
}, {
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;
}
}
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() : 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;
}
}
}
/***/ }),
/***/ 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__);
/***/ }),
/***/ 8409:
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
/* harmony import */ var _DocumentedShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1106);
const __exports__ = _DocumentedShell_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__);
/***/ }),
/***/ 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);
/***/ }),
/***/ 1106:
/***/ (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_DocumentedShell_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_DocumentedShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(865);
/***/ }),
/***/ 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);
/***/ })
/******/ });
/************************************************************************/
/******/ // 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.26bc1008.js.map