当前按 1 比 1 已停用
下面这些旧页面功能已经不再走本地 PHP 或旧接口,因为你给的文档里没有对应定义。
- 会话列表与消息列表
- 发送文字、图片、文件消息
- 联系人列表、添加联系人、备注
- 群详情、群成员、群管理
- 个人资料编辑与头像上传
", 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