if (typeof Promise !== "undefined" && !Promise.prototype.finally) { Promise.prototype.finally = function(callback) { const promise = this.constructor; return this.then( (value) => promise.resolve(callback()).then(() => value), (reason) => promise.resolve(callback()).then(() => { throw reason; }) ); }; } ; if (typeof uni !== "undefined" && uni && uni.requireGlobal) { const global2 = uni.requireGlobal(); ArrayBuffer = global2.ArrayBuffer; Int8Array = global2.Int8Array; Uint8Array = global2.Uint8Array; Uint8ClampedArray = global2.Uint8ClampedArray; Int16Array = global2.Int16Array; Uint16Array = global2.Uint16Array; Int32Array = global2.Int32Array; Uint32Array = global2.Uint32Array; Float32Array = global2.Float32Array; Float64Array = global2.Float64Array; BigInt64Array = global2.BigInt64Array; BigUint64Array = global2.BigUint64Array; } ; if (uni.restoreGlobal) { uni.restoreGlobal(Vue, weex, plus, setTimeout, clearTimeout, setInterval, clearInterval); } (function(vue) { "use strict"; const ON_SHOW = "onShow"; function formatAppLog(type, filename, ...args) { if (uni.__log__) { uni.__log__(type, filename, ...args); } else { console[type].apply(console, [...args, filename]); } } function resolveEasycom(component, easycom) { return typeof component === "string" ? easycom : component; } const createLifeCycleHook = (lifecycle, flag = 0) => (hook, target = vue.getCurrentInstance()) => { !vue.isInSSRComponentSetup && vue.injectHook(lifecycle, hook, target); }; const onShow = /* @__PURE__ */ createLifeCycleHook( ON_SHOW, 1 | 2 /* HookFlags.PAGE */ ); const BASE_URL = "https://cloudtest.yuxindazhineng.com"; const login = async (username, password) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/login`, method: "POST", data: { "username": username, "password": password, "login_type": "phone" }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const token = res.data.access_token; if (token) { uni.setStorageSync("token", token); resolve(token); } else { const msg = res.data.error || "检查用户名和密码"; reject(msg); } } else { reject(`请求失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getUserConversations = async (token) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/get_user_conversations`, method: "POST", data: { "access_token": token }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const conversations = res.data.conversations; resolve(conversations); } else { reject(`请求失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getConversationMessages = async (token, conversatio_id) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/get_conversation_messages`, method: "POST", data: { "access_token": token, "conversation_id": conversatio_id }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const messagesInfo = res.data; if (messagesInfo) { formatAppLog("log", "at utils/cloud-api.js:88", "工作区id为:", messagesInfo.workspace_id); uni.setStorageSync("workspace_id", messagesInfo.workspace_id); resolve(messagesInfo.messages); } else { const msg = res.data.error || "获取消息出错啦"; reject(msg); } } else { reject(`请求失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const addMessageDict = async (token, role, conversation_id, message) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/add_message_dict`, method: "POST", data: { "access_token": token, "conversation_id": conversation_id, "message": { "role": role, "content": message } }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const message_id = res.data.message_id; if (message_id) { resolve(message_id); } else { const msg = res.data.error || "用户发送消息出错啦"; reject(msg); } } else { reject(`用户发送失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const createWorkspace = async (token, name2) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/create_workspace`, method: "POST", data: { "access_token": token, "name": name2 }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const workspaceId = res.data.workspace_id; if (workspaceId) { resolve(workspaceId); } else { const msg = res.data.error || "创建工作区id出错啦"; reject(msg); } } else { reject(`创建工作区id失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const createConversation = async (token, workspaceId, title, sender) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/create_conversation`, method: "POST", data: { "access_token": token, "workspace_id": workspaceId, "title": title, "sender": sender }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const conversationId = res.data.conversation_id; if (conversationId) { resolve(conversationId); } else { const msg = res.data.error || "创建新对话id出错啦"; reject(msg); } } else { reject(`创建新对话失败:${res.statusCode}`); } } }); }); }; const deleteConversation = async (token, conversation_ids) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/delete_conversation`, method: "POST", data: { "access_token": token, "conversation_ids": conversation_ids }, header: { "Content-Type": "application/json" }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond == null ? void 0 : respond.success) { resolve(respond.message); } else { const msg = respond.failed_ids.error || "删除对话出错啦"; reject(msg); } } else { reject(`删除对话失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getUserInfo = async (token) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/get_user_info`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token }, success: (res) => { var _a, _b; if (res.statusCode === 200) { const respond = res.data; if (respond == null ? void 0 : respond._id) { uni.setStorageSync("userId", respond._id); resolve(respond); } else { const msg = ((_b = (_a = respond == null ? void 0 : respond.detail) == null ? void 0 : _a[0]) == null ? void 0 : _b.msg) || "获取用户信息出错啦"; reject(msg); } } else { reject(`获取用户信息失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getUserAvatar = (token, userIds) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/get_user_avatar`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "user_ids": userIds }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.users); } else { const msg = (respond == null ? void 0 : respond.error) || "获取用户头像出错啦"; reject(msg); } } else { reject(`获取用户头像失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const searchUsers = (token, keyword) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/search_users`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "keyword": keyword }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.users); } else { const msg = (respond == null ? void 0 : respond.error) || "通过用户名或邮箱来去查询用户出错啦"; reject(msg); } } else { reject(`通过用户名或邮箱来去查询用户失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getWorkspaceList = (token, workspacesId) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/phone/workspace/list`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "workspaces_id": workspacesId, "format": "tree", "parent_path": "", "filter_type": "" }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.data); } else { const msg = (respond == null ? void 0 : respond.error) || "获取工作区文件目录出错啦"; reject(msg); } } else { reject(`获取工作区文件目录失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const daleteWorkspace = (token, workspacesId, path) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/phone/workspace/delete`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "workspaces_id": workspacesId, "file_path": path }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.message); } else { const msg = (respond == null ? void 0 : respond.error) || "删除工作区文件出错啦"; reject(msg); } } else { reject(`删除工作区文件失败:${res.statusCode}`); } } }); }); }; const createWorkspaceFolder = (token, workspacesId, path) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/phone/workspace/create`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "workspaces_id": workspacesId, "dir_path": path }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.message); } else { const msg = (respond == null ? void 0 : respond.error) || "创建工作区文件夹出错啦"; reject(msg); } } else { reject(`创建工作区文件夹失败:${res.statusCode}`); } } }); }); }; const getWorkspaceFileURL = (token, workspacesId, path) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_URL}/cloud_api/phone/workspace/downloadFile`, method: "POST", header: { "Content-Type": "application/json" }, data: { "access_token": token, "workspaces_id": workspacesId, "file_path": path }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.success) { resolve(respond.message || respond.data); } else if (Array.isArray(respond)) { resolve(respond); } else { const msg = (respond == null ? void 0 : respond.error) || "获取工作区文URL出错啦"; reject(msg); } } else { reject(`获取工作区文URL失败:${res.statusCode}`); } } }); }); }; const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const _sfc_main$a = { __name: "Login", setup(__props, { expose: __expose }) { __expose(); const UsernameValue = vue.ref(""); const isUsernameFocused = vue.ref(false); const isUsernameError = vue.ref(false); const usernameFocused = () => { isUsernameFocused.value = true; formDataHasNull.value = false; }; const handleUsernameBlur = () => { isUsernameFocused.value = false; }; const validateUsername = () => { }; const PasswordValue = vue.ref(""); const isPasswordFocused = vue.ref(false); const isPasswordError = vue.ref(false); const passwordFocused = () => { isPasswordFocused.value = true; formDataHasNull.value = false; }; const handlePasswordBlur = () => { isPasswordFocused.value = false; }; const form = vue.reactive({ username: vue.computed(() => UsernameValue.value), password: vue.computed(() => PasswordValue.value), remember: true }); const loading = vue.ref(false); const formDataHasNull = vue.ref(false); const handleLogin = async () => { checkFormData(); if (formDataHasNull.value) return; loading.value = true; try { const token = await login(UsernameValue.value, PasswordValue.value); saveLoginInfo(); uni.reLaunch({ url: "/pages/Chat/Chat" }); } catch (err) { formatAppLog("log", "at pages/Login/Login.vue:124", "登录失败", err); uni.showToast({ title: err || "失败", icon: "error" }); } finally { loading.value = false; } }; const checkFormData = () => { if (!UsernameValue.value || !PasswordValue.value) { formDataHasNull.value = true; } }; const saveLoginInfo = () => { if (form.remember) { const loginInfo = { username: form.username, password: form.password, remember: true }; uni.setStorageSync("login_info", loginInfo); uni.setStorageSync("chatType", 0); } else { uni.removeStorageSync("login_info"); } }; const loadLoginInfo = () => { try { const loginInfo = uni.getStorageSync("login_info"); if (loginInfo) { UsernameValue.value = loginInfo.username || ""; PasswordValue.value = loginInfo.password || ""; form.remember = loginInfo.remember ?? true; } } catch (e2) { formatAppLog("error", "at pages/Login/Login.vue:168", "读取登录信息失败", e2); } }; vue.onMounted(() => { loadLoginInfo(); }); const __returned__ = { UsernameValue, isUsernameFocused, isUsernameError, usernameFocused, handleUsernameBlur, validateUsername, PasswordValue, isPasswordFocused, isPasswordError, passwordFocused, handlePasswordBlur, form, loading, formDataHasNull, handleLogin, checkFormData, saveLoginInfo, loadLoginInfo, reactive: vue.reactive, ref: vue.ref, computed: vue.computed, onMounted: vue.onMounted, get login() { return login; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), vue.createElementVNode("view", { class: "login-container page-container" }, [ vue.createElementVNode("view", { class: "login-card" }, [ vue.createElementVNode("view", { class: "login-header" }, [ vue.createElementVNode("view", { class: "login-header-logo" }, [ vue.createElementVNode("view", { class: "icon-wrapper" }, [ vue.createElementVNode("view", { class: "iconfont icon-brain-2-fill danao-style" }) ]), vue.createElementVNode("text", null, "YXD") ]), vue.createElementVNode("view", { class: "sub-title" }, "File Handling Chat") ]), vue.createElementVNode("view", { class: "form-wrapper" }, [ vue.createElementVNode("view", { class: "form-item" }, [ vue.createElementVNode("view", { class: "form-label" }, [ vue.createElementVNode("text", null, "用户名") ]), vue.withDirectives(vue.createElementVNode( "input", { class: vue.normalizeClass(["form-input", { focused: $setup.isUsernameFocused, error: $setup.isUsernameError }]), "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.UsernameValue = $event), onFocus: $setup.usernameFocused, onBlur: $setup.handleUsernameBlur, onInput: $setup.validateUsername, placeholder: "请输入用户名" }, null, 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vModelText, $setup.UsernameValue] ]) ]), vue.createElementVNode("view", { class: "form-item" }, [ vue.createElementVNode("view", { class: "form-label" }, [ vue.createElementVNode("text", null, "密码") ]), vue.withDirectives(vue.createElementVNode( "input", { type: "password", class: vue.normalizeClass(["form-input", { focused: $setup.isPasswordFocused, error: $setup.isPasswordError }]), "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $setup.PasswordValue = $event), onFocus: $setup.passwordFocused, onBlur: $setup.handlePasswordBlur, placeholder: "请输入密码" }, null, 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vModelText, $setup.PasswordValue] ]) ]), $setup.formDataHasNull ? (vue.openBlock(), vue.createElementBlock("text", { key: 0, class: "error-info" }, "用户名或密码不能为空")) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "form-option" }, [ vue.createElementVNode("view", { class: "checkbox-wrapper", onClick: _cache[2] || (_cache[2] = ($event) => $setup.form.remember = !$setup.form.remember) }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["checkbox", { checked: $setup.form.remember }]) }, [ $setup.form.remember ? (vue.openBlock(), vue.createElementBlock("text", { key: 0 }, "✓")) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ ), vue.createElementVNode("text", { class: "checkbox-text" }, "记住密码") ]), vue.createElementVNode("text", { class: "forget-pwd" }, "忘记密码?") ]), vue.createElementVNode("button", { class: "login-btn", disabled: $setup.loading, loading: $setup.loading, onClick: $setup.handleLogin }, vue.toDisplayString($setup.loading ? "Loading..." : "登录"), 9, ["disabled", "loading"]) ]) ]) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesLoginLogin = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$9], ["__scopeId", "data-v-461d1d79"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/Login/Login.vue"]]); const fontData = [ { "font_class": "arrow-down", "unicode": "" }, { "font_class": "arrow-left", "unicode": "" }, { "font_class": "arrow-right", "unicode": "" }, { "font_class": "arrow-up", "unicode": "" }, { "font_class": "auth", "unicode": "" }, { "font_class": "auth-filled", "unicode": "" }, { "font_class": "back", "unicode": "" }, { "font_class": "bars", "unicode": "" }, { "font_class": "calendar", "unicode": "" }, { "font_class": "calendar-filled", "unicode": "" }, { "font_class": "camera", "unicode": "" }, { "font_class": "camera-filled", "unicode": "" }, { "font_class": "cart", "unicode": "" }, { "font_class": "cart-filled", "unicode": "" }, { "font_class": "chat", "unicode": "" }, { "font_class": "chat-filled", "unicode": "" }, { "font_class": "chatboxes", "unicode": "" }, { "font_class": "chatboxes-filled", "unicode": "" }, { "font_class": "chatbubble", "unicode": "" }, { "font_class": "chatbubble-filled", "unicode": "" }, { "font_class": "checkbox", "unicode": "" }, { "font_class": "checkbox-filled", "unicode": "" }, { "font_class": "checkmarkempty", "unicode": "" }, { "font_class": "circle", "unicode": "" }, { "font_class": "circle-filled", "unicode": "" }, { "font_class": "clear", "unicode": "" }, { "font_class": "close", "unicode": "" }, { "font_class": "closeempty", "unicode": "" }, { "font_class": "cloud-download", "unicode": "" }, { "font_class": "cloud-download-filled", "unicode": "" }, { "font_class": "cloud-upload", "unicode": "" }, { "font_class": "cloud-upload-filled", "unicode": "" }, { "font_class": "color", "unicode": "" }, { "font_class": "color-filled", "unicode": "" }, { "font_class": "compose", "unicode": "" }, { "font_class": "contact", "unicode": "" }, { "font_class": "contact-filled", "unicode": "" }, { "font_class": "down", "unicode": "" }, { "font_class": "bottom", "unicode": "" }, { "font_class": "download", "unicode": "" }, { "font_class": "download-filled", "unicode": "" }, { "font_class": "email", "unicode": "" }, { "font_class": "email-filled", "unicode": "" }, { "font_class": "eye", "unicode": "" }, { "font_class": "eye-filled", "unicode": "" }, { "font_class": "eye-slash", "unicode": "" }, { "font_class": "eye-slash-filled", "unicode": "" }, { "font_class": "fire", "unicode": "" }, { "font_class": "fire-filled", "unicode": "" }, { "font_class": "flag", "unicode": "" }, { "font_class": "flag-filled", "unicode": "" }, { "font_class": "folder-add", "unicode": "" }, { "font_class": "folder-add-filled", "unicode": "" }, { "font_class": "font", "unicode": "" }, { "font_class": "forward", "unicode": "" }, { "font_class": "gear", "unicode": "" }, { "font_class": "gear-filled", "unicode": "" }, { "font_class": "gift", "unicode": "" }, { "font_class": "gift-filled", "unicode": "" }, { "font_class": "hand-down", "unicode": "" }, { "font_class": "hand-down-filled", "unicode": "" }, { "font_class": "hand-up", "unicode": "" }, { "font_class": "hand-up-filled", "unicode": "" }, { "font_class": "headphones", "unicode": "" }, { "font_class": "heart", "unicode": "" }, { "font_class": "heart-filled", "unicode": "" }, { "font_class": "help", "unicode": "" }, { "font_class": "help-filled", "unicode": "" }, { "font_class": "home", "unicode": "" }, { "font_class": "home-filled", "unicode": "" }, { "font_class": "image", "unicode": "" }, { "font_class": "image-filled", "unicode": "" }, { "font_class": "images", "unicode": "" }, { "font_class": "images-filled", "unicode": "" }, { "font_class": "info", "unicode": "" }, { "font_class": "info-filled", "unicode": "" }, { "font_class": "left", "unicode": "" }, { "font_class": "link", "unicode": "" }, { "font_class": "list", "unicode": "" }, { "font_class": "location", "unicode": "" }, { "font_class": "location-filled", "unicode": "" }, { "font_class": "locked", "unicode": "" }, { "font_class": "locked-filled", "unicode": "" }, { "font_class": "loop", "unicode": "" }, { "font_class": "mail-open", "unicode": "" }, { "font_class": "mail-open-filled", "unicode": "" }, { "font_class": "map", "unicode": "" }, { "font_class": "map-filled", "unicode": "" }, { "font_class": "map-pin", "unicode": "" }, { "font_class": "map-pin-ellipse", "unicode": "" }, { "font_class": "medal", "unicode": "" }, { "font_class": "medal-filled", "unicode": "" }, { "font_class": "mic", "unicode": "" }, { "font_class": "mic-filled", "unicode": "" }, { "font_class": "micoff", "unicode": "" }, { "font_class": "micoff-filled", "unicode": "" }, { "font_class": "minus", "unicode": "" }, { "font_class": "minus-filled", "unicode": "" }, { "font_class": "more", "unicode": "" }, { "font_class": "more-filled", "unicode": "" }, { "font_class": "navigate", "unicode": "" }, { "font_class": "navigate-filled", "unicode": "" }, { "font_class": "notification", "unicode": "" }, { "font_class": "notification-filled", "unicode": "" }, { "font_class": "paperclip", "unicode": "" }, { "font_class": "paperplane", "unicode": "" }, { "font_class": "paperplane-filled", "unicode": "" }, { "font_class": "person", "unicode": "" }, { "font_class": "person-filled", "unicode": "" }, { "font_class": "personadd", "unicode": "" }, { "font_class": "personadd-filled", "unicode": "" }, { "font_class": "personadd-filled-copy", "unicode": "" }, { "font_class": "phone", "unicode": "" }, { "font_class": "phone-filled", "unicode": "" }, { "font_class": "plus", "unicode": "" }, { "font_class": "plus-filled", "unicode": "" }, { "font_class": "plusempty", "unicode": "" }, { "font_class": "pulldown", "unicode": "" }, { "font_class": "pyq", "unicode": "" }, { "font_class": "qq", "unicode": "" }, { "font_class": "redo", "unicode": "" }, { "font_class": "redo-filled", "unicode": "" }, { "font_class": "refresh", "unicode": "" }, { "font_class": "refresh-filled", "unicode": "" }, { "font_class": "refreshempty", "unicode": "" }, { "font_class": "reload", "unicode": "" }, { "font_class": "right", "unicode": "" }, { "font_class": "scan", "unicode": "" }, { "font_class": "search", "unicode": "" }, { "font_class": "settings", "unicode": "" }, { "font_class": "settings-filled", "unicode": "" }, { "font_class": "shop", "unicode": "" }, { "font_class": "shop-filled", "unicode": "" }, { "font_class": "smallcircle", "unicode": "" }, { "font_class": "smallcircle-filled", "unicode": "" }, { "font_class": "sound", "unicode": "" }, { "font_class": "sound-filled", "unicode": "" }, { "font_class": "spinner-cycle", "unicode": "" }, { "font_class": "staff", "unicode": "" }, { "font_class": "staff-filled", "unicode": "" }, { "font_class": "star", "unicode": "" }, { "font_class": "star-filled", "unicode": "" }, { "font_class": "starhalf", "unicode": "" }, { "font_class": "trash", "unicode": "" }, { "font_class": "trash-filled", "unicode": "" }, { "font_class": "tune", "unicode": "" }, { "font_class": "tune-filled", "unicode": "" }, { "font_class": "undo", "unicode": "" }, { "font_class": "undo-filled", "unicode": "" }, { "font_class": "up", "unicode": "" }, { "font_class": "top", "unicode": "" }, { "font_class": "upload", "unicode": "" }, { "font_class": "upload-filled", "unicode": "" }, { "font_class": "videocam", "unicode": "" }, { "font_class": "videocam-filled", "unicode": "" }, { "font_class": "vip", "unicode": "" }, { "font_class": "vip-filled", "unicode": "" }, { "font_class": "wallet", "unicode": "" }, { "font_class": "wallet-filled", "unicode": "" }, { "font_class": "weibo", "unicode": "" }, { "font_class": "weixin", "unicode": "" } ]; const getVal = (val) => { const reg = /^[0-9]*$/g; return typeof val === "number" || reg.test(val) ? val + "px" : val; }; const _sfc_main$9 = { name: "UniIcons", emits: ["click"], props: { type: { type: String, default: "" }, color: { type: String, default: "#333333" }, size: { type: [Number, String], default: 16 }, customPrefix: { type: String, default: "" }, fontFamily: { type: String, default: "" } }, data() { return { icons: fontData }; }, computed: { unicode() { let code = this.icons.find((v) => v.font_class === this.type); if (code) { return code.unicode; } return ""; }, iconSize() { return getVal(this.size); }, styleObj() { if (this.fontFamily !== "") { return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`; } return `color: ${this.color}; font-size: ${this.iconSize};`; } }, methods: { _onClick(e2) { this.$emit("click", e2); } } }; function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock( "text", { style: vue.normalizeStyle($options.styleObj), class: vue.normalizeClass(["uni-icons", ["uniui-" + $props.type, $props.customPrefix, $props.customPrefix ? $props.type : ""]]), onClick: _cache[0] || (_cache[0] = (...args) => $options._onClick && $options._onClick(...args)) }, [ vue.renderSlot(_ctx.$slots, "default", {}, void 0, true) ], 6 /* CLASS, STYLE */ ); } const __easycom_0 = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$8], ["__scopeId", "data-v-d31e1c47"], ["__file", "D:/Projects/uniapp/app-test/test1/uni_modules/uni-icons/components/uni-icons/uni-icons.vue"]]); const getToken = () => { return uni.getStorageSync("token"); }; const getCurrentSessionId = () => { const sessionId = uni.getStorageSync("currentSessionId"); if (!isNaN(Number(sessionId))) { return sessionId; } return sessionId.replace(/-/g, ""); }; const getTaskCallId = () => { return uni.getStorageSync("taskCallId"); }; const getUserId = () => { formatAppLog("log", "at utils/user-info.js:50", "用户Id(UserId)", uni.getStorageSync("userId")); return uni.getStorageSync("userId"); }; const getChatType = () => { return uni.getStorageSync("chatType"); }; const getReceiverId = () => { return uni.getStorageSync("receiverId"); }; const getWorkspaceId = () => { return uni.getStorageSync("workspace_id"); }; const _sfc_main$8 = /* @__PURE__ */ Object.assign({ name: "ChatSidebar" }, { __name: "ChatSidebar", props: { chatList: { type: Array, required: true }, showNewChatModal: { type: Boolean, default: false }, currentSessionId: { type: [String, Number], required: true }, chatType: { type: Number, required: true } }, emits: [ "update:showNewChatModal", "update:currentSessionId", "refresh-conversations", "update:chatType" ], setup(__props, { expose: __expose, emit: __emit }) { __expose(); const props = __props; const emit = __emit; const UserConversations = vue.toRef(props, "chatList"); const showNewChatModal = vue.toRef(props, "showNewChatModal"); const chatType = vue.toRef(props, "chatType"); const openUserCardVisible = () => { uni.navigateTo({ url: "/pages/UserProfileModal/UserProfileModal" }); }; const isSelectMode = vue.ref(false); const selectedHistoryIds = vue.ref([]); const deleteConversations = () => { if (selectedHistoryIds.value.length === 0) return; uni.showModal({ title: "确认删除", content: `确定要删除全部 ${selectedHistoryIds.value.length} 个对话吗?此操作不可恢复。`, confirmText: "确认删除", confirmColor: "#ff0000", success: async (res) => { if (res.confirm) { try { const userToken = getToken(); await deleteConversation(userToken, selectedHistoryIds.value); uni.showToast({ title: "删除成功", icon: "success" }); selectedHistoryIds.value = []; isSelectMode.value = false; emit("refresh-conversations"); } catch (error) { formatAppLog("error", "at components/ChatSidebar.vue:209", "删除会话失败:", error); uni.showToast({ title: "删除失败,请重试", icon: "none" }); } } } }); }; const clearAllConversations = () => { if (!UserConversations.value.length) { uni.showToast({ title: "没有可删除的会话", icon: "none" }); return; } uni.showModal({ title: "确认删除", content: `确定要删除全部 ${UserConversations.value.length} 个对话吗?此操作不可恢复。`, confirmText: "删除全部", confirmColor: "#ff0000", success: async (res) => { if (res.confirm) { try { const userToken = getToken(); const allIds = UserConversations.value.map((item) => item._id); await deleteConversation(userToken, allIds); uni.showToast({ title: "已删除全部对话", icon: "success" }); emit("refresh-conversations"); } catch (error) { formatAppLog("error", "at components/ChatSidebar.vue:241", "清空全部对话失败:", error); uni.showToast({ title: "删除失败,请重试", icon: "none" }); } } } }); }; const isAllHistorySelected = vue.computed(() => { return UserConversations.value.length > 0 && selectedHistoryIds.value.length === UserConversations.value.length; }); const currentChatId = vue.toRef(props, "currentSessionId"); const selectChat = (chatId, receiverId = "") => { formatAppLog("log", "at components/ChatSidebar.vue:259", "选择的id是:", chatId); if (receiverId) { uni.setStorageSync("receiverId", receiverId); } uni.setStorageSync("currentSessionId", chatId); emit("update:currentSessionId", chatId); }; const openNewChatModal = () => { formatAppLog("log", "at components/ChatSidebar.vue:270", "点击了新建会话"); emit("update:showNewChatModal", true); }; const goContactPages = () => { uni.navigateTo({ url: "/pages/ContactPages/ContactPages" }); }; const chatHistoryQuery = vue.ref(""); const isHistorySearchFocused = vue.ref(false); const toggleSelectMode = () => { isSelectMode.value = !isSelectMode.value; if (!isSelectMode.value) { selectedHistoryIds.value = []; } }; const toggleHistorySelect = (chatId) => { const index = selectedHistoryIds.value.indexOf(chatId); if (index === -1) { selectedHistoryIds.value.push(chatId); } else { selectedHistoryIds.value.splice(index, 1); } }; const toggleSelectAllHistory = () => { if (isAllHistorySelected.value) { selectedHistoryIds.value = []; } else { selectedHistoryIds.value = UserConversations.value.map((chat) => chat._id); } }; const UserToken = vue.ref(""); const UserAvatar = vue.ref(""); const UserName = vue.ref(""); vue.onMounted(async () => { UserToken.value = getToken(); const UserInfo = await getUserInfo(UserToken.value); UserAvatar.value = UserInfo.avatar || ""; UserName.value = UserInfo.username || ""; formatAppLog("log", "at components/ChatSidebar.vue:320", "菜单收到的会话列表:", UserConversations.value); }); const __returned__ = { props, emit, UserConversations, showNewChatModal, chatType, openUserCardVisible, isSelectMode, selectedHistoryIds, deleteConversations, clearAllConversations, isAllHistorySelected, currentChatId, selectChat, openNewChatModal, goContactPages, chatHistoryQuery, isHistorySearchFocused, toggleSelectMode, toggleHistorySelect, toggleSelectAllHistory, UserToken, UserAvatar, UserName, computed: vue.computed, onMounted: vue.onMounted, onUnmounted: vue.onUnmounted, ref: vue.ref, toRef: vue.toRef, get deleteConversation() { return deleteConversation; }, get getToken() { return getToken; }, get getUserInfo() { return getUserInfo; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }); function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock("view", { class: "chat-sidebar-container" }, [ vue.createElementVNode("view", { class: "status-bar" }), vue.createElementVNode("view", { class: "sidebar-header" }, [ vue.createElementVNode("view", { class: "user-profile-card", onClick: $setup.openUserCardVisible }, [ vue.createElementVNode("view", { class: "left" }, [ $setup.UserAvatar ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "avatar-preview" }, [ vue.createElementVNode("image", { src: $setup.UserAvatar, mode: "aspectFill" }, null, 8, ["src"]) ])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "avatar-placeholder" }, [ vue.createVNode(_component_uni_icons, { type: "contact-filled", size: "50", color: "#007aff" }) ])) ]), vue.createElementVNode("view", { class: "center" }, [ vue.createElementVNode("text", null, "欢迎回来"), vue.createElementVNode( "text", null, vue.toDisplayString($setup.UserName), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "right" }, [ vue.createElementVNode("view", { class: "status-dot" }), vue.createElementVNode("view", { class: "status-text" }, [ vue.createElementVNode("text", null, "在线") ]) ]) ]), vue.createElementVNode("view", { class: "new-chat-btn", onClick: $setup.goContactPages }, [ vue.createElementVNode("text", null, "+ 聊天列表") ]) ]), vue.createElementVNode("view", { class: "chat-history" }, [ vue.createElementVNode("view", { class: "history-header" }, [ vue.createElementVNode("view", { class: "history-title-section" }, [ vue.createElementVNode("text", null, "历史会话"), vue.createElementVNode( "text", null, vue.toDisplayString($setup.UserConversations.length) + "个对话", 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "history-management" }, [ !$setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "history-management-btn iconfont icon-jia icon-jia-style", onClick: $setup.openNewChatModal })) : vue.createCommentVNode("v-if", true), !$setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "history-management-btn iconfont icon-duoxuan icon-duoxuan-style", onClick: $setup.toggleSelectMode })) : vue.createCommentVNode("v-if", true), !$setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 2, class: "history-management-btn iconfont icon-saochu icon-saochu-style", onClick: $setup.clearAllConversations })) : vue.createCommentVNode("v-if", true), $setup.isSelectMode && $setup.selectedHistoryIds.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 3, class: "history-management-btn iconfont icon-shanchu icon-shanchu-style", onClick: $setup.deleteConversations })) : vue.createCommentVNode("v-if", true), $setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock( "view", { key: 4, class: vue.normalizeClass(["history-management-btn iconfont icon-total_selection icon-total_selection-style", { active: $setup.isAllHistorySelected }]), onClick: $setup.toggleSelectAllHistory }, null, 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true), $setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 5, class: "history-management-btn iconfont icon-quxiao icon-quxiao-style", onClick: $setup.toggleSelectMode })) : vue.createCommentVNode("v-if", true) ]) ]), !$setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "history-search-wrap" }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["history-search-inner", { "has-value": $setup.chatHistoryQuery || $setup.isHistorySearchFocused }]) }, [ vue.createVNode(_component_uni_icons, { type: "search", class: vue.normalizeClass([$setup.chatHistoryQuery || $setup.isHistorySearchFocused ? "chat-search-icon" : "search-icon"]) }, null, 8, ["class"]), vue.withDirectives(vue.createElementVNode( "input", { "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.chatHistoryQuery = $event), onFocus: _cache[1] || (_cache[1] = ($event) => $setup.isHistorySearchFocused = true), onBlur: _cache[2] || (_cache[2] = ($event) => $setup.isHistorySearchFocused = false), type: "text", placeholder: "搜索会话..." }, null, 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.chatHistoryQuery] ]) ], 2 /* CLASS */ ) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "chat-history-list" }, [ $setup.chatType === 0 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 0 }, vue.renderList($setup.UserConversations, (chat) => { return vue.openBlock(), vue.createElementBlock("view", { key: chat._id, "data-chat-id": chat._id, class: vue.normalizeClass(["chat-history-card", { "is-select-chat": $setup.currentChatId === chat._id || $setup.selectedHistoryIds.includes(chat._id) }]), onClick: ($event) => $setup.isSelectMode ? $setup.toggleHistorySelect(chat._id) : $setup.selectChat(chat._id) }, [ $setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "history-chat-checkbox" }, [ $setup.selectedHistoryIds.includes(chat._id) ? (vue.openBlock(), vue.createBlock(_component_uni_icons, { key: 0, type: "checkmarkempty", size: "20", color: "#007aff" })) : vue.createCommentVNode("v-if", true) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "history-chat-avatar" }, [ vue.createVNode(_component_uni_icons, { type: "chat-filled", size: "26", color: "#007aff" }) ]), chat.agent_id ? (vue.openBlock(), vue.createElementBlock( "view", { key: 1 }, vue.toDisplayString(chat.agent_data.title), 1 /* TEXT */ )) : (vue.openBlock(), vue.createElementBlock( "view", { key: 2 }, vue.toDisplayString(chat.title), 1 /* TEXT */ )) ], 10, ["data-chat-id", "onClick"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true), $setup.chatType === 1 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 1 }, vue.renderList($setup.UserConversations, (chat) => { return vue.openBlock(), vue.createElementBlock("view", { key: chat.sessionId, "data-chat-id": chat.sessionId, class: vue.normalizeClass(["chat-history-card", { "is-select-chat": $setup.currentChatId === chat.sessionId || $setup.selectedHistoryIds.includes(chat.sessionId) }]), onClick: ($event) => $setup.isSelectMode ? $setup.toggleHistorySelect(chat.sessionId) : $setup.selectChat(chat.sessionId, chat.receiver) }, [ $setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "history-chat-checkbox" }, [ $setup.selectedHistoryIds.includes(chat.sessionId) ? (vue.openBlock(), vue.createBlock(_component_uni_icons, { key: 0, type: "checkmarkempty", size: "20", color: "#007aff" })) : vue.createCommentVNode("v-if", true) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "history-chat-avatar" }, [ chat.avatar ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: chat.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : vue.createCommentVNode("v-if", true) ]), vue.createElementVNode( "view", null, vue.toDisplayString(chat.friendNickName), 1 /* TEXT */ ) ], 10, ["data-chat-id", "onClick"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true), $setup.chatType === 2 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 2 }, vue.renderList($setup.UserConversations, (chat) => { return vue.openBlock(), vue.createElementBlock("view", { key: chat.id, "data-chat-id": chat.id, class: vue.normalizeClass(["chat-history-card", { "is-select-chat": $setup.currentChatId === chat.id || $setup.selectedHistoryIds.includes(chat.id) }]), onClick: ($event) => $setup.isSelectMode ? $setup.toggleHistorySelect(chat.id) : $setup.selectChat(chat.id) }, [ $setup.isSelectMode ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "history-chat-checkbox" }, [ $setup.selectedHistoryIds.includes(chat.id) ? (vue.openBlock(), vue.createBlock(_component_uni_icons, { key: 0, type: "checkmarkempty", size: "20", color: "#007aff" })) : vue.createCommentVNode("v-if", true) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "history-chat-avatar" }, [ vue.createElementVNode("view", { class: "iconfont icon-qunliao", style: { "font-size": "80rpx", "color": "#fff" } }) ]), vue.createElementVNode( "view", null, vue.toDisplayString(chat.name), 1 /* TEXT */ ) ], 10, ["data-chat-id", "onClick"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true) ]) ]) ]); } const ChatSidebar = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$7], ["__scopeId", "data-v-0c6c7315"], ["__file", "D:/Projects/uniapp/app-test/test1/components/ChatSidebar.vue"]]); var e = { "": ["", ""], _: ["", ""], "*": ["", ""], "~": ["", ""], "\n": ["
"], " ": ["
"], "-": ["
"] }; function n(e2) { return e2.replace(RegExp("^" + (e2.match(/^(\t| )+/) || "")[0], "gm"), ""); } function r(e2) { return (e2 + "").replace(/"/g, """).replace(//g, ">"); } function t(a, c) { var o, l, g, s, p, u = /((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^``` *(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:!\[([^\]]*?)\]\(([^)]+?)\))|(\[)|(\](?:\(([^)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,6})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*]|~~)/gm, m = [], h = "", i = c || {}, d = 0; function f(n2) { var r2 = e[n2[1] || ""], t2 = m[m.length - 1] == n2; return r2 ? r2[1] ? (t2 ? m.pop() : m.push(n2), r2[0 | t2]) : r2[0] : n2; } function $() { for (var e2 = ""; m.length; ) e2 += f(m[m.length - 1]); return e2; } for (a = a.replace(/^\[(.+?)\]:\s*(.+)$/gm, function(e2, n2, r2) { return i[n2.toLowerCase()] = r2, ""; }).replace(/^\n+|\n+$/g, ""); g = u.exec(a); ) l = a.substring(d, g.index), d = u.lastIndex, o = g[0], l.match(/[^\\](\\\\)*\\$/) || ((p = g[3] || g[4]) ? o = '
" + n(r(p).replace(/^\n+|\n+$/g, "")) + "
" : (p = g[6]) ? (p.match(/\./) && (g[5] = g[5].replace(/^\d+/gm, "")), s = t(n(g[5].replace(/^\s*[>*+.-]/gm, ""))), ">" == p ? p = "blockquote" : (p = p.match(/\./) ? "ol" : "ul", s = s.replace(/^(.*)(\n|$)/gm, "
  • $1
  • ")), o = "<" + p + ">" + s + "") : g[8] ? o = '' + r(g[7]) + '' : g[10] ? (h = h.replace("", ''), o = $() + "") : g[9] ? o = "" : g[12] || g[14] ? o = "<" + (p = "h" + (g[14] ? g[14].length : g[13] > "=" ? 1 : 2)) + ">" + t(g[12] || g[15], i) + "" : g[16] ? o = "" + r(g[16]) + "" : (g[17] || g[1]) && (o = f(g[17] || "--"))), h += l, h += o; return (h + a.substring(d) + $()).replace(/^\n+|\n+$/g, ""); } var isVue2 = false; function set(target, key, val) { if (Array.isArray(target)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val; } target[key] = val; return val; } function del(target, key) { if (Array.isArray(target)) { target.splice(key, 1); return; } delete target[key]; } function getDevtoolsGlobalHook() { return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__; } function getTarget() { return typeof navigator !== "undefined" && typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; } const isProxyAvailable = typeof Proxy === "function"; const HOOK_SETUP = "devtools-plugin:setup"; const HOOK_PLUGIN_SETTINGS_SET = "plugin:settings:set"; let supported; let perf; function isPerformanceSupported() { var _a; if (supported !== void 0) { return supported; } if (typeof window !== "undefined" && window.performance) { supported = true; perf = window.performance; } else if (typeof global !== "undefined" && ((_a = global.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) { supported = true; perf = global.perf_hooks.performance; } else { supported = false; } return supported; } function now() { return isPerformanceSupported() ? perf.now() : Date.now(); } class ApiProxy { constructor(plugin, hook) { this.target = null; this.targetQueue = []; this.onQueue = []; this.plugin = plugin; this.hook = hook; const defaultSettings = {}; if (plugin.settings) { for (const id in plugin.settings) { const item = plugin.settings[id]; defaultSettings[id] = item.defaultValue; } } const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`; let currentSettings = Object.assign({}, defaultSettings); try { const raw = localStorage.getItem(localSettingsSaveId); const data = JSON.parse(raw); Object.assign(currentSettings, data); } catch (e2) { } this.fallbacks = { getSettings() { return currentSettings; }, setSettings(value) { try { localStorage.setItem(localSettingsSaveId, JSON.stringify(value)); } catch (e2) { } currentSettings = value; }, now() { return now(); } }; if (hook) { hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => { if (pluginId === this.plugin.id) { this.fallbacks.setSettings(value); } }); } this.proxiedOn = new Proxy({}, { get: (_target, prop) => { if (this.target) { return this.target.on[prop]; } else { return (...args) => { this.onQueue.push({ method: prop, args }); }; } } }); this.proxiedTarget = new Proxy({}, { get: (_target, prop) => { if (this.target) { return this.target[prop]; } else if (prop === "on") { return this.proxiedOn; } else if (Object.keys(this.fallbacks).includes(prop)) { return (...args) => { this.targetQueue.push({ method: prop, args, resolve: () => { } }); return this.fallbacks[prop](...args); }; } else { return (...args) => { return new Promise((resolve) => { this.targetQueue.push({ method: prop, args, resolve }); }); }; } } }); } async setRealTarget(target) { this.target = target; for (const item of this.onQueue) { this.target.on[item.method](...item.args); } for (const item of this.targetQueue) { item.resolve(await this.target[item.method](...item.args)); } } } function setupDevtoolsPlugin(pluginDescriptor, setupFn) { const descriptor = pluginDescriptor; const target = getTarget(); const hook = getDevtoolsGlobalHook(); const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy; if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) { hook.emit(HOOK_SETUP, pluginDescriptor, setupFn); } else { const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null; const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || []; list.push({ pluginDescriptor: descriptor, setupFn, proxy }); if (proxy) setupFn(proxy.proxiedTarget); } } /*! * pinia v2.1.7 * (c) 2023 Eduardo San Martin Morote * @license MIT */ let activePinia; const setActivePinia = (pinia) => activePinia = pinia; const piniaSymbol = Symbol("pinia"); function isPlainObject(o) { return o && typeof o === "object" && Object.prototype.toString.call(o) === "[object Object]" && typeof o.toJSON !== "function"; } var MutationType; (function(MutationType2) { MutationType2["direct"] = "direct"; MutationType2["patchObject"] = "patch object"; MutationType2["patchFunction"] = "patch function"; })(MutationType || (MutationType = {})); const IS_CLIENT = typeof window !== "undefined"; const USE_DEVTOOLS = IS_CLIENT; const _global = /* @__PURE__ */ (() => typeof window === "object" && window.window === window ? window : typeof self === "object" && self.self === self ? self : typeof global === "object" && global.global === global ? global : typeof globalThis === "object" ? globalThis : { HTMLElement: null })(); function bom(blob, { autoBom = false } = {}) { if (autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { return new Blob([String.fromCharCode(65279), blob], { type: blob.type }); } return blob; } function download(url, name2, opts) { const xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.responseType = "blob"; xhr.onload = function() { saveAs(xhr.response, name2, opts); }; xhr.onerror = function() { console.error("could not download file"); }; xhr.send(); } function corsEnabled(url) { const xhr = new XMLHttpRequest(); xhr.open("HEAD", url, false); try { xhr.send(); } catch (e2) { } return xhr.status >= 200 && xhr.status <= 299; } function click(node) { try { node.dispatchEvent(new MouseEvent("click")); } catch (e2) { const evt = document.createEvent("MouseEvents"); evt.initMouseEvent("click", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); node.dispatchEvent(evt); } } const _navigator = typeof navigator === "object" ? navigator : { userAgent: "" }; const isMacOSWebView = /* @__PURE__ */ (() => /Macintosh/.test(_navigator.userAgent) && /AppleWebKit/.test(_navigator.userAgent) && !/Safari/.test(_navigator.userAgent))(); const saveAs = !IS_CLIENT ? () => { } : ( // Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView or mini program typeof HTMLAnchorElement !== "undefined" && "download" in HTMLAnchorElement.prototype && !isMacOSWebView ? downloadSaveAs : ( // Use msSaveOrOpenBlob as a second approach "msSaveOrOpenBlob" in _navigator ? msSaveAs : ( // Fallback to using FileReader and a popup fileSaverSaveAs ) ) ); function downloadSaveAs(blob, name2 = "download", opts) { const a = document.createElement("a"); a.download = name2; a.rel = "noopener"; if (typeof blob === "string") { a.href = blob; if (a.origin !== location.origin) { if (corsEnabled(a.href)) { download(blob, name2, opts); } else { a.target = "_blank"; click(a); } } else { click(a); } } else { a.href = URL.createObjectURL(blob); setTimeout(function() { URL.revokeObjectURL(a.href); }, 4e4); setTimeout(function() { click(a); }, 0); } } function msSaveAs(blob, name2 = "download", opts) { if (typeof blob === "string") { if (corsEnabled(blob)) { download(blob, name2, opts); } else { const a = document.createElement("a"); a.href = blob; a.target = "_blank"; setTimeout(function() { click(a); }); } } else { navigator.msSaveOrOpenBlob(bom(blob, opts), name2); } } function fileSaverSaveAs(blob, name2, opts, popup) { popup = popup || open("", "_blank"); if (popup) { popup.document.title = popup.document.body.innerText = "downloading..."; } if (typeof blob === "string") return download(blob, name2, opts); const force = blob.type === "application/octet-stream"; const isSafari = /constructor/i.test(String(_global.HTMLElement)) || "safari" in _global; const isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent); if ((isChromeIOS || force && isSafari || isMacOSWebView) && typeof FileReader !== "undefined") { const reader = new FileReader(); reader.onloadend = function() { let url = reader.result; if (typeof url !== "string") { popup = null; throw new Error("Wrong reader.result type"); } url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, "data:attachment/file;"); if (popup) { popup.location.href = url; } else { location.assign(url); } popup = null; }; reader.readAsDataURL(blob); } else { const url = URL.createObjectURL(blob); if (popup) popup.location.assign(url); else location.href = url; popup = null; setTimeout(function() { URL.revokeObjectURL(url); }, 4e4); } } function toastMessage(message, type) { const piniaMessage = "🍍 " + message; if (typeof __VUE_DEVTOOLS_TOAST__ === "function") { __VUE_DEVTOOLS_TOAST__(piniaMessage, type); } else if (type === "error") { console.error(piniaMessage); } else if (type === "warn") { console.warn(piniaMessage); } else { console.log(piniaMessage); } } function isPinia(o) { return "_a" in o && "install" in o; } function checkClipboardAccess() { if (!("clipboard" in navigator)) { toastMessage(`Your browser doesn't support the Clipboard API`, "error"); return true; } } function checkNotFocusedError(error) { if (error instanceof Error && error.message.toLowerCase().includes("document is not focused")) { toastMessage('You need to activate the "Emulate a focused page" setting in the "Rendering" panel of devtools.', "warn"); return true; } return false; } async function actionGlobalCopyState(pinia) { if (checkClipboardAccess()) return; try { await navigator.clipboard.writeText(JSON.stringify(pinia.state.value)); toastMessage("Global state copied to clipboard."); } catch (error) { if (checkNotFocusedError(error)) return; toastMessage(`Failed to serialize the state. Check the console for more details.`, "error"); console.error(error); } } async function actionGlobalPasteState(pinia) { if (checkClipboardAccess()) return; try { loadStoresState(pinia, JSON.parse(await navigator.clipboard.readText())); toastMessage("Global state pasted from clipboard."); } catch (error) { if (checkNotFocusedError(error)) return; toastMessage(`Failed to deserialize the state from clipboard. Check the console for more details.`, "error"); console.error(error); } } async function actionGlobalSaveState(pinia) { try { saveAs(new Blob([JSON.stringify(pinia.state.value)], { type: "text/plain;charset=utf-8" }), "pinia-state.json"); } catch (error) { toastMessage(`Failed to export the state as JSON. Check the console for more details.`, "error"); console.error(error); } } let fileInput; function getFileOpener() { if (!fileInput) { fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.accept = ".json"; } function openFile() { return new Promise((resolve, reject) => { fileInput.onchange = async () => { const files = fileInput.files; if (!files) return resolve(null); const file = files.item(0); if (!file) return resolve(null); return resolve({ text: await file.text(), file }); }; fileInput.oncancel = () => resolve(null); fileInput.onerror = reject; fileInput.click(); }); } return openFile; } async function actionGlobalOpenStateFile(pinia) { try { const open2 = getFileOpener(); const result = await open2(); if (!result) return; const { text, file } = result; loadStoresState(pinia, JSON.parse(text)); toastMessage(`Global state imported from "${file.name}".`); } catch (error) { toastMessage(`Failed to import the state from JSON. Check the console for more details.`, "error"); console.error(error); } } function loadStoresState(pinia, state) { for (const key in state) { const storeState = pinia.state.value[key]; if (storeState) { Object.assign(storeState, state[key]); } else { pinia.state.value[key] = state[key]; } } } function formatDisplay(display) { return { _custom: { display } }; } const PINIA_ROOT_LABEL = "🍍 Pinia (root)"; const PINIA_ROOT_ID = "_root"; function formatStoreForInspectorTree(store) { return isPinia(store) ? { id: PINIA_ROOT_ID, label: PINIA_ROOT_LABEL } : { id: store.$id, label: store.$id }; } function formatStoreForInspectorState(store) { if (isPinia(store)) { const storeNames = Array.from(store._s.keys()); const storeMap = store._s; const state2 = { state: storeNames.map((storeId) => ({ editable: true, key: storeId, value: store.state.value[storeId] })), getters: storeNames.filter((id) => storeMap.get(id)._getters).map((id) => { const store2 = storeMap.get(id); return { editable: false, key: id, value: store2._getters.reduce((getters, key) => { getters[key] = store2[key]; return getters; }, {}) }; }) }; return state2; } const state = { state: Object.keys(store.$state).map((key) => ({ editable: true, key, value: store.$state[key] })) }; if (store._getters && store._getters.length) { state.getters = store._getters.map((getterName) => ({ editable: false, key: getterName, value: store[getterName] })); } if (store._customProperties.size) { state.customProperties = Array.from(store._customProperties).map((key) => ({ editable: true, key, value: store[key] })); } return state; } function formatEventData(events) { if (!events) return {}; if (Array.isArray(events)) { return events.reduce((data, event) => { data.keys.push(event.key); data.operations.push(event.type); data.oldValue[event.key] = event.oldValue; data.newValue[event.key] = event.newValue; return data; }, { oldValue: {}, keys: [], operations: [], newValue: {} }); } else { return { operation: formatDisplay(events.type), key: formatDisplay(events.key), oldValue: events.oldValue, newValue: events.newValue }; } } function formatMutationType(type) { switch (type) { case MutationType.direct: return "mutation"; case MutationType.patchFunction: return "$patch"; case MutationType.patchObject: return "$patch"; default: return "unknown"; } } let isTimelineActive = true; const componentStateTypes = []; const MUTATIONS_LAYER_ID = "pinia:mutations"; const INSPECTOR_ID = "pinia"; const { assign: assign$1 } = Object; const getStoreType = (id) => "🍍 " + id; function registerPiniaDevtools(app, pinia) { setupDevtoolsPlugin({ id: "dev.esm.pinia", label: "Pinia 🍍", logo: "https://pinia.vuejs.org/logo.svg", packageName: "pinia", homepage: "https://pinia.vuejs.org", componentStateTypes, app }, (api) => { if (typeof api.now !== "function") { toastMessage("You seem to be using an outdated version of Vue Devtools. Are you still using the Beta release instead of the stable one? You can find the links at https://devtools.vuejs.org/guide/installation.html."); } api.addTimelineLayer({ id: MUTATIONS_LAYER_ID, label: `Pinia 🍍`, color: 15064968 }); api.addInspector({ id: INSPECTOR_ID, label: "Pinia 🍍", icon: "storage", treeFilterPlaceholder: "Search stores", actions: [ { icon: "content_copy", action: () => { actionGlobalCopyState(pinia); }, tooltip: "Serialize and copy the state" }, { icon: "content_paste", action: async () => { await actionGlobalPasteState(pinia); api.sendInspectorTree(INSPECTOR_ID); api.sendInspectorState(INSPECTOR_ID); }, tooltip: "Replace the state with the content of your clipboard" }, { icon: "save", action: () => { actionGlobalSaveState(pinia); }, tooltip: "Save the state as a JSON file" }, { icon: "folder_open", action: async () => { await actionGlobalOpenStateFile(pinia); api.sendInspectorTree(INSPECTOR_ID); api.sendInspectorState(INSPECTOR_ID); }, tooltip: "Import the state from a JSON file" } ], nodeActions: [ { icon: "restore", tooltip: 'Reset the state (with "$reset")', action: (nodeId) => { const store = pinia._s.get(nodeId); if (!store) { toastMessage(`Cannot reset "${nodeId}" store because it wasn't found.`, "warn"); } else if (typeof store.$reset !== "function") { toastMessage(`Cannot reset "${nodeId}" store because it doesn't have a "$reset" method implemented.`, "warn"); } else { store.$reset(); toastMessage(`Store "${nodeId}" reset.`); } } } ] }); api.on.inspectComponent((payload, ctx) => { const proxy = payload.componentInstance && payload.componentInstance.proxy; if (proxy && proxy._pStores) { const piniaStores = payload.componentInstance.proxy._pStores; Object.values(piniaStores).forEach((store) => { payload.instanceData.state.push({ type: getStoreType(store.$id), key: "state", editable: true, value: store._isOptionsAPI ? { _custom: { value: vue.toRaw(store.$state), actions: [ { icon: "restore", tooltip: "Reset the state of this store", action: () => store.$reset() } ] } } : ( // NOTE: workaround to unwrap transferred refs Object.keys(store.$state).reduce((state, key) => { state[key] = store.$state[key]; return state; }, {}) ) }); if (store._getters && store._getters.length) { payload.instanceData.state.push({ type: getStoreType(store.$id), key: "getters", editable: false, value: store._getters.reduce((getters, key) => { try { getters[key] = store[key]; } catch (error) { getters[key] = error; } return getters; }, {}) }); } }); } }); api.on.getInspectorTree((payload) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { let stores = [pinia]; stores = stores.concat(Array.from(pinia._s.values())); payload.rootNodes = (payload.filter ? stores.filter((store) => "$id" in store ? store.$id.toLowerCase().includes(payload.filter.toLowerCase()) : PINIA_ROOT_LABEL.toLowerCase().includes(payload.filter.toLowerCase())) : stores).map(formatStoreForInspectorTree); } }); api.on.getInspectorState((payload) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { const inspectedStore = payload.nodeId === PINIA_ROOT_ID ? pinia : pinia._s.get(payload.nodeId); if (!inspectedStore) { return; } if (inspectedStore) { payload.state = formatStoreForInspectorState(inspectedStore); } } }); api.on.editInspectorState((payload, ctx) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { const inspectedStore = payload.nodeId === PINIA_ROOT_ID ? pinia : pinia._s.get(payload.nodeId); if (!inspectedStore) { return toastMessage(`store "${payload.nodeId}" not found`, "error"); } const { path } = payload; if (!isPinia(inspectedStore)) { if (path.length !== 1 || !inspectedStore._customProperties.has(path[0]) || path[0] in inspectedStore.$state) { path.unshift("$state"); } } else { path.unshift("state"); } isTimelineActive = false; payload.set(inspectedStore, path, payload.state.value); isTimelineActive = true; } }); api.on.editComponentState((payload) => { if (payload.type.startsWith("🍍")) { const storeId = payload.type.replace(/^🍍\s*/, ""); const store = pinia._s.get(storeId); if (!store) { return toastMessage(`store "${storeId}" not found`, "error"); } const { path } = payload; if (path[0] !== "state") { return toastMessage(`Invalid path for store "${storeId}": ${path} Only state can be modified.`); } path[0] = "$state"; isTimelineActive = false; payload.set(store, path, payload.state.value); isTimelineActive = true; } }); }); } function addStoreToDevtools(app, store) { if (!componentStateTypes.includes(getStoreType(store.$id))) { componentStateTypes.push(getStoreType(store.$id)); } setupDevtoolsPlugin({ id: "dev.esm.pinia", label: "Pinia 🍍", logo: "https://pinia.vuejs.org/logo.svg", packageName: "pinia", homepage: "https://pinia.vuejs.org", componentStateTypes, app, settings: { logStoreChanges: { label: "Notify about new/deleted stores", type: "boolean", defaultValue: true } // useEmojis: { // label: 'Use emojis in messages ⚡️', // type: 'boolean', // defaultValue: true, // }, } }, (api) => { const now2 = typeof api.now === "function" ? api.now.bind(api) : Date.now; store.$onAction(({ after, onError, name: name2, args }) => { const groupId = runningActionId++; api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: { time: now2(), title: "🛫 " + name2, subtitle: "start", data: { store: formatDisplay(store.$id), action: formatDisplay(name2), args }, groupId } }); after((result) => { activeAction = void 0; api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: { time: now2(), title: "🛬 " + name2, subtitle: "end", data: { store: formatDisplay(store.$id), action: formatDisplay(name2), args, result }, groupId } }); }); onError((error) => { activeAction = void 0; api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: { time: now2(), logType: "error", title: "💥 " + name2, subtitle: "end", data: { store: formatDisplay(store.$id), action: formatDisplay(name2), args, error }, groupId } }); }); }, true); store._customProperties.forEach((name2) => { vue.watch(() => vue.unref(store[name2]), (newValue, oldValue) => { api.notifyComponentUpdate(); api.sendInspectorState(INSPECTOR_ID); if (isTimelineActive) { api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: { time: now2(), title: "Change", subtitle: name2, data: { newValue, oldValue }, groupId: activeAction } }); } }, { deep: true }); }); store.$subscribe(({ events, type }, state) => { api.notifyComponentUpdate(); api.sendInspectorState(INSPECTOR_ID); if (!isTimelineActive) return; const eventData = { time: now2(), title: formatMutationType(type), data: assign$1({ store: formatDisplay(store.$id) }, formatEventData(events)), groupId: activeAction }; if (type === MutationType.patchFunction) { eventData.subtitle = "⤵️"; } else if (type === MutationType.patchObject) { eventData.subtitle = "🧩"; } else if (events && !Array.isArray(events)) { eventData.subtitle = events.type; } if (events) { eventData.data["rawEvent(s)"] = { _custom: { display: "DebuggerEvent", type: "object", tooltip: "raw DebuggerEvent[]", value: events } }; } api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: eventData }); }, { detached: true, flush: "sync" }); const hotUpdate = store._hotUpdate; store._hotUpdate = vue.markRaw((newStore) => { hotUpdate(newStore); api.addTimelineEvent({ layerId: MUTATIONS_LAYER_ID, event: { time: now2(), title: "🔥 " + store.$id, subtitle: "HMR update", data: { store: formatDisplay(store.$id), info: formatDisplay(`HMR update`) } } }); api.notifyComponentUpdate(); api.sendInspectorTree(INSPECTOR_ID); api.sendInspectorState(INSPECTOR_ID); }); const { $dispose } = store; store.$dispose = () => { $dispose(); api.notifyComponentUpdate(); api.sendInspectorTree(INSPECTOR_ID); api.sendInspectorState(INSPECTOR_ID); api.getSettings().logStoreChanges && toastMessage(`Disposed "${store.$id}" store 🗑`); }; api.notifyComponentUpdate(); api.sendInspectorTree(INSPECTOR_ID); api.sendInspectorState(INSPECTOR_ID); api.getSettings().logStoreChanges && toastMessage(`"${store.$id}" store installed 🆕`); }); } let runningActionId = 0; let activeAction; function patchActionForGrouping(store, actionNames, wrapWithProxy) { const actions = actionNames.reduce((storeActions, actionName) => { storeActions[actionName] = vue.toRaw(store)[actionName]; return storeActions; }, {}); for (const actionName in actions) { store[actionName] = function() { const _actionId = runningActionId; const trackedStore = wrapWithProxy ? new Proxy(store, { get(...args) { activeAction = _actionId; return Reflect.get(...args); }, set(...args) { activeAction = _actionId; return Reflect.set(...args); } }) : store; activeAction = _actionId; const retValue = actions[actionName].apply(trackedStore, arguments); activeAction = void 0; return retValue; }; } } function devtoolsPlugin({ app, store, options }) { if (store.$id.startsWith("__hot:")) { return; } store._isOptionsAPI = !!options.state; patchActionForGrouping(store, Object.keys(options.actions), store._isOptionsAPI); const originalHotUpdate = store._hotUpdate; vue.toRaw(store)._hotUpdate = function(newStore) { originalHotUpdate.apply(this, arguments); patchActionForGrouping(store, Object.keys(newStore._hmrPayload.actions), !!store._isOptionsAPI); }; addStoreToDevtools( app, // FIXME: is there a way to allow the assignment from Store to StoreGeneric? store ); } function createPinia() { const scope = vue.effectScope(true); const state = scope.run(() => vue.ref({})); let _p = []; let toBeInstalled = []; const pinia = vue.markRaw({ install(app) { setActivePinia(pinia); { pinia._a = app; app.provide(piniaSymbol, pinia); app.config.globalProperties.$pinia = pinia; if (USE_DEVTOOLS) { registerPiniaDevtools(app, pinia); } toBeInstalled.forEach((plugin) => _p.push(plugin)); toBeInstalled = []; } }, use(plugin) { if (!this._a && !isVue2) { toBeInstalled.push(plugin); } else { _p.push(plugin); } return this; }, _p, // it's actually undefined here // @ts-expect-error _a: null, _e: scope, _s: /* @__PURE__ */ new Map(), state }); if (USE_DEVTOOLS && typeof Proxy !== "undefined") { pinia.use(devtoolsPlugin); } return pinia; } function patchObject(newState, oldState) { for (const key in oldState) { const subPatch = oldState[key]; if (!(key in newState)) { continue; } const targetValue = newState[key]; if (isPlainObject(targetValue) && isPlainObject(subPatch) && !vue.isRef(subPatch) && !vue.isReactive(subPatch)) { newState[key] = patchObject(targetValue, subPatch); } else { { newState[key] = subPatch; } } } return newState; } const noop = () => { }; function addSubscription(subscriptions, callback, detached, onCleanup = noop) { subscriptions.push(callback); const removeSubscription = () => { const idx = subscriptions.indexOf(callback); if (idx > -1) { subscriptions.splice(idx, 1); onCleanup(); } }; if (!detached && vue.getCurrentScope()) { vue.onScopeDispose(removeSubscription); } return removeSubscription; } function triggerSubscriptions(subscriptions, ...args) { subscriptions.slice().forEach((callback) => { callback(...args); }); } const fallbackRunWithContext = (fn) => fn(); function mergeReactiveObjects(target, patchToApply) { if (target instanceof Map && patchToApply instanceof Map) { patchToApply.forEach((value, key) => target.set(key, value)); } if (target instanceof Set && patchToApply instanceof Set) { patchToApply.forEach(target.add, target); } for (const key in patchToApply) { if (!patchToApply.hasOwnProperty(key)) continue; const subPatch = patchToApply[key]; const targetValue = target[key]; if (isPlainObject(targetValue) && isPlainObject(subPatch) && target.hasOwnProperty(key) && !vue.isRef(subPatch) && !vue.isReactive(subPatch)) { target[key] = mergeReactiveObjects(targetValue, subPatch); } else { target[key] = subPatch; } } return target; } const skipHydrateSymbol = Symbol("pinia:skipHydration"); function shouldHydrate(obj) { return !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol); } const { assign } = Object; function isComputed(o) { return !!(vue.isRef(o) && o.effect); } function createOptionsStore(id, options, pinia, hot) { const { state, actions, getters } = options; const initialState = pinia.state.value[id]; let store; function setup() { if (!initialState && !hot) { { pinia.state.value[id] = state ? state() : {}; } } const localState = hot ? ( // use ref() to unwrap refs inside state TODO: check if this is still necessary vue.toRefs(vue.ref(state ? state() : {}).value) ) : vue.toRefs(pinia.state.value[id]); return assign(localState, actions, Object.keys(getters || {}).reduce((computedGetters, name2) => { if (name2 in localState) { console.warn(`[🍍]: A getter cannot have the same name as another state property. Rename one of them. Found with "${name2}" in store "${id}".`); } computedGetters[name2] = vue.markRaw(vue.computed(() => { setActivePinia(pinia); const store2 = pinia._s.get(id); return getters[name2].call(store2, store2); })); return computedGetters; }, {})); } store = createSetupStore(id, setup, options, pinia, hot, true); return store; } function createSetupStore($id, setup, options = {}, pinia, hot, isOptionsStore) { let scope; const optionsForPlugin = assign({ actions: {} }, options); if (!pinia._e.active) { throw new Error("Pinia destroyed"); } const $subscribeOptions = { deep: true // flush: 'post', }; { $subscribeOptions.onTrigger = (event) => { if (isListening) { debuggerEvents = event; } else if (isListening == false && !store._hotUpdating) { if (Array.isArray(debuggerEvents)) { debuggerEvents.push(event); } else { console.error("🍍 debuggerEvents should be an array. This is most likely an internal Pinia bug."); } } }; } let isListening; let isSyncListening; let subscriptions = []; let actionSubscriptions = []; let debuggerEvents; const initialState = pinia.state.value[$id]; if (!isOptionsStore && !initialState && !hot) { { pinia.state.value[$id] = {}; } } const hotState = vue.ref({}); let activeListener; function $patch(partialStateOrMutator) { let subscriptionMutation; isListening = isSyncListening = false; { debuggerEvents = []; } if (typeof partialStateOrMutator === "function") { partialStateOrMutator(pinia.state.value[$id]); subscriptionMutation = { type: MutationType.patchFunction, storeId: $id, events: debuggerEvents }; } else { mergeReactiveObjects(pinia.state.value[$id], partialStateOrMutator); subscriptionMutation = { type: MutationType.patchObject, payload: partialStateOrMutator, storeId: $id, events: debuggerEvents }; } const myListenerId = activeListener = Symbol(); vue.nextTick().then(() => { if (activeListener === myListenerId) { isListening = true; } }); isSyncListening = true; triggerSubscriptions(subscriptions, subscriptionMutation, pinia.state.value[$id]); } const $reset = isOptionsStore ? function $reset2() { const { state } = options; const newState = state ? state() : {}; this.$patch(($state) => { assign($state, newState); }); } : ( /* istanbul ignore next */ () => { throw new Error(`🍍: Store "${$id}" is built using the setup syntax and does not implement $reset().`); } ); function $dispose() { scope.stop(); subscriptions = []; actionSubscriptions = []; pinia._s.delete($id); } function wrapAction(name2, action) { return function() { setActivePinia(pinia); const args = Array.from(arguments); const afterCallbackList = []; const onErrorCallbackList = []; function after(callback) { afterCallbackList.push(callback); } function onError(callback) { onErrorCallbackList.push(callback); } triggerSubscriptions(actionSubscriptions, { args, name: name2, store, after, onError }); let ret; try { ret = action.apply(this && this.$id === $id ? this : store, args); } catch (error) { triggerSubscriptions(onErrorCallbackList, error); throw error; } if (ret instanceof Promise) { return ret.then((value) => { triggerSubscriptions(afterCallbackList, value); return value; }).catch((error) => { triggerSubscriptions(onErrorCallbackList, error); return Promise.reject(error); }); } triggerSubscriptions(afterCallbackList, ret); return ret; }; } const _hmrPayload = /* @__PURE__ */ vue.markRaw({ actions: {}, getters: {}, state: [], hotState }); const partialStore = { _p: pinia, // _s: scope, $id, $onAction: addSubscription.bind(null, actionSubscriptions), $patch, $reset, $subscribe(callback, options2 = {}) { const removeSubscription = addSubscription(subscriptions, callback, options2.detached, () => stopWatcher()); const stopWatcher = scope.run(() => vue.watch(() => pinia.state.value[$id], (state) => { if (options2.flush === "sync" ? isSyncListening : isListening) { callback({ storeId: $id, type: MutationType.direct, events: debuggerEvents }, state); } }, assign({}, $subscribeOptions, options2))); return removeSubscription; }, $dispose }; const store = vue.reactive(assign( { _hmrPayload, _customProperties: vue.markRaw(/* @__PURE__ */ new Set()) // devtools custom properties }, partialStore // must be added later // setupStore )); pinia._s.set($id, store); const runWithContext = pinia._a && pinia._a.runWithContext || fallbackRunWithContext; const setupStore = runWithContext(() => pinia._e.run(() => (scope = vue.effectScope()).run(setup))); for (const key in setupStore) { const prop = setupStore[key]; if (vue.isRef(prop) && !isComputed(prop) || vue.isReactive(prop)) { if (hot) { set(hotState.value, key, vue.toRef(setupStore, key)); } else if (!isOptionsStore) { if (initialState && shouldHydrate(prop)) { if (vue.isRef(prop)) { prop.value = initialState[key]; } else { mergeReactiveObjects(prop, initialState[key]); } } { pinia.state.value[$id][key] = prop; } } { _hmrPayload.state.push(key); } } else if (typeof prop === "function") { const actionValue = hot ? prop : wrapAction(key, prop); { setupStore[key] = actionValue; } { _hmrPayload.actions[key] = prop; } optionsForPlugin.actions[key] = prop; } else { if (isComputed(prop)) { _hmrPayload.getters[key] = isOptionsStore ? ( // @ts-expect-error options.getters[key] ) : prop; if (IS_CLIENT) { const getters = setupStore._getters || // @ts-expect-error: same (setupStore._getters = vue.markRaw([])); getters.push(key); } } } } { assign(store, setupStore); assign(vue.toRaw(store), setupStore); } Object.defineProperty(store, "$state", { get: () => hot ? hotState.value : pinia.state.value[$id], set: (state) => { if (hot) { throw new Error("cannot set hotState"); } $patch(($state) => { assign($state, state); }); } }); { store._hotUpdate = vue.markRaw((newStore) => { store._hotUpdating = true; newStore._hmrPayload.state.forEach((stateKey) => { if (stateKey in store.$state) { const newStateTarget = newStore.$state[stateKey]; const oldStateSource = store.$state[stateKey]; if (typeof newStateTarget === "object" && isPlainObject(newStateTarget) && isPlainObject(oldStateSource)) { patchObject(newStateTarget, oldStateSource); } else { newStore.$state[stateKey] = oldStateSource; } } set(store, stateKey, vue.toRef(newStore.$state, stateKey)); }); Object.keys(store.$state).forEach((stateKey) => { if (!(stateKey in newStore.$state)) { del(store, stateKey); } }); isListening = false; isSyncListening = false; pinia.state.value[$id] = vue.toRef(newStore._hmrPayload, "hotState"); isSyncListening = true; vue.nextTick().then(() => { isListening = true; }); for (const actionName in newStore._hmrPayload.actions) { const action = newStore[actionName]; set(store, actionName, wrapAction(actionName, action)); } for (const getterName in newStore._hmrPayload.getters) { const getter = newStore._hmrPayload.getters[getterName]; const getterValue = isOptionsStore ? ( // special handling of options api vue.computed(() => { setActivePinia(pinia); return getter.call(store, store); }) ) : getter; set(store, getterName, getterValue); } Object.keys(store._hmrPayload.getters).forEach((key) => { if (!(key in newStore._hmrPayload.getters)) { del(store, key); } }); Object.keys(store._hmrPayload.actions).forEach((key) => { if (!(key in newStore._hmrPayload.actions)) { del(store, key); } }); store._hmrPayload = newStore._hmrPayload; store._getters = newStore._getters; store._hotUpdating = false; }); } if (USE_DEVTOOLS) { const nonEnumerable = { writable: true, configurable: true, // avoid warning on devtools trying to display this property enumerable: false }; ["_p", "_hmrPayload", "_getters", "_customProperties"].forEach((p) => { Object.defineProperty(store, p, assign({ value: store[p] }, nonEnumerable)); }); } pinia._p.forEach((extender) => { if (USE_DEVTOOLS) { const extensions = scope.run(() => extender({ store, app: pinia._a, pinia, options: optionsForPlugin })); Object.keys(extensions || {}).forEach((key) => store._customProperties.add(key)); assign(store, extensions); } else { assign(store, scope.run(() => extender({ store, app: pinia._a, pinia, options: optionsForPlugin }))); } }); if (store.$state && typeof store.$state === "object" && typeof store.$state.constructor === "function" && !store.$state.constructor.toString().includes("[native code]")) { console.warn(`[🍍]: The "state" must be a plain object. It cannot be state: () => new MyClass() Found in store "${store.$id}".`); } if (initialState && isOptionsStore && options.hydrate) { options.hydrate(store.$state, initialState); } isListening = true; isSyncListening = true; return store; } function defineStore(idOrOptions, setup, setupOptions) { let id; let options; const isSetupStore = typeof setup === "function"; if (typeof idOrOptions === "string") { id = idOrOptions; options = isSetupStore ? setupOptions : setup; } else { options = idOrOptions; id = idOrOptions.id; if (typeof id !== "string") { throw new Error(`[🍍]: "defineStore()" must be passed a store id as its first argument.`); } } function useStore(pinia, hot) { const hasContext = vue.hasInjectionContext(); pinia = // in test mode, ignore the argument provided as we can always retrieve a // pinia instance with getActivePinia() pinia || (hasContext ? vue.inject(piniaSymbol, null) : null); if (pinia) setActivePinia(pinia); if (!activePinia) { throw new Error(`[🍍]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"? See https://pinia.vuejs.org/core-concepts/outside-component-usage.html for help. This will fail in production.`); } pinia = activePinia; if (!pinia._s.has(id)) { if (isSetupStore) { createSetupStore(id, setup, options, pinia); } else { createOptionsStore(id, options, pinia); } { useStore._pinia = pinia; } } const store = pinia._s.get(id); if (hot) { const hotId = "__hot:" + id; const newStore = isSetupStore ? createSetupStore(hotId, setup, options, pinia, true) : createOptionsStore(hotId, assign({}, options), pinia, true); hot._hotUpdate(newStore); delete pinia.state.value[hotId]; pinia._s.delete(hotId); } if (IS_CLIENT) { const currentInstance = vue.getCurrentInstance(); if (currentInstance && currentInstance.proxy && // avoid adding stores that are just built for hot module replacement !hot) { const vm = currentInstance.proxy; const cache = "_pStores" in vm ? vm._pStores : vm._pStores = {}; cache[id] = store; } } return store; } useStore.$id = id; return useStore; } const WS_APP_URL = "ws://cloud_test.yuxindazhineng.com"; let WebSocketManager$1 = class WebSocketManager { constructor() { this.ws = null; this.url = `${WS_APP_URL}/cloud_api/phone/app_ws`; this.options = { token: "", conversationId: "", onMessage: null, onError: null, onReconnect: null, onOpen: null, onClose: null }; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.reconnectDelay = 3e3; this.reconnectTimer = null; this.heartbeatTimer = null; this.isManualClose = false; } /** * 初始化连接 * @param {string} url WebSocket URL * @param {Object} options 配置选项 */ connect(options = {}) { this.options = { ...this.options, ...options }; this.isManualClose = false; if (this.ws) { this.close(); } try { this.ws = uni.connectSocket({ url: this.url, success: () => { formatAppLog("log", "at utils/socket.js:43", "WebSocket 连接请求已发送"); }, fail: (err) => { formatAppLog("error", "at utils/socket.js:46", "WebSocket 连接失败:", err); this.handleError(err); } }); this.initEventHandlers(); } catch (err) { this.handleError(err); } } /** * 初始化事件处理 */ initEventHandlers() { if (!this.ws) return; this.ws.onOpen((event) => { var _a, _b, _c, _d; formatAppLog("log", "at utils/socket.js:73", "WebSocket 已连接"); if (this.reconnectAttempts > 0) { (_b = (_a = this.options).onReconnect) == null ? void 0 : _b.call(_a); } (_d = (_c = this.options).onOpen) == null ? void 0 : _d.call(_c, event); this.reconnectAttempts = 0; }); this.ws.onMessage((event) => { try { const data = JSON.parse(event.data); formatAppLog("log", "at utils/socket.js:86", "收到了返回消息:", data); this.handleMessage(data); } catch (err) { formatAppLog("error", "at utils/socket.js:90", "消息解析失败:", err); uni.setStorageSync("currentSessionId", event.data.task_call_id); } }); this.ws.onError((err) => { formatAppLog("error", "at utils/socket.js:95", "WebSocket 错误:", err); this.handleError(err); }); this.ws.onClose((event) => { var _a, _b; formatAppLog("log", "at utils/socket.js:99", "WebSocket 已关闭:", event.code, event.reason); (_b = (_a = this.options).onClose) == null ? void 0 : _b.call(_a, event); this.stopHeartbeat(); if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnect(); } }); } /** * 处理服务端推送的消息 * @param {Object} msg - 服务端返回的原始消息对象 */ handleMessage(msg) { var _a, _b; (_b = (_a = this.options).onMessage) == null ? void 0 : _b.call(_a, msg); const type = msg.type; if (type === "auth_ok") { formatAppLog("log", "at utils/socket.js:161", "认证成功,socket连接成功"); return; } if (type === "auth_fail") { if ((msg == null ? void 0 : msg.reason) === "pc offline") formatAppLog("log", "at utils/socket.js:168", "pc端不在线,不可聊天"); this.isManualClose = true; this.close(); return; } } /** * 统一发送消息方法 * 兼容 APP / 微信小程序 环境 * @param {Object} data - 要发送的消息对象 * @returns {Promise} 发送结果 */ send(data) { return new Promise((resolve, reject) => { if (!this.isConnected()) { reject(new Error("WebSocket 未连接")); return; } const msg = JSON.stringify(data); formatAppLog("log", "at utils/socket.js:192", "发送的消息是:", msg); this.ws.send({ data: msg, success: () => resolve(), fail: (err) => { formatAppLog("error", "at utils/socket.js:200", "发送消息失败:", err); reject(err); } }); }); } /** * 自动重连机制 * 指数退避重连,避免频繁重连 */ reconnect() { if (this.reconnectTimer) return; this.reconnectAttempts++; formatAppLog("log", "at utils/socket.js:226", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; if (!this.isManualClose) { this.connect(this.options); } }, this.reconnectDelay * this.reconnectAttempts); } /** * 启动心跳定时器 * 每30秒发送一次 ping 保持连接 */ startHeartbeat() { this.stopHeartbeat(); this.heartbeatTimer = setInterval(() => { if (this.isConnected()) { this.send({ ws_event: "ping" }).catch(() => { formatAppLog("log", "at utils/socket.js:248", "心跳发送失败,准备重连"); if (!this.reconnectTimer && !this.isManualClose) { this.reconnect(); } }); } else if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnect(); } }, 3e4); } /** * 停止心跳定时器 */ stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } } /** * 统一错误处理 * @param {Error} error - 错误对象 */ handleError(error) { var _a, _b; formatAppLog("error", "at utils/socket.js:276", "WebSocket 错误处理:", JSON.stringify(error)); (_b = (_a = this.options).onError) == null ? void 0 : _b.call(_a, error); } /** * 判断 WebSocket 是否处于已连接状态 * @returns {boolean} */ isConnected() { if (!this.ws) return false; return this.ws.readyState === 1; } /** * 方便外部获取连接状态码 * @returns {number} 0:连接中,1:已连接,2:关闭中,3:已关闭 */ getReadyState() { if (!this.ws) return 3; return this.ws.readyState; } /** * 手动关闭 WebSocket 连接 * 清理所有定时器、标记手动关闭、停止重连 */ close() { formatAppLog("log", "at utils/socket.js:312", "手动关闭 WebSocket 连接"); this.isManualClose = true; this.stopHeartbeat(); if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } if (this.ws) { if (this.ws.onOpen) this.ws.onOpen(null); if (this.ws.onMessage) this.ws.onMessage(null); if (this.ws.onError) this.ws.onError(null); if (this.ws.onClose) this.ws.onClose(null); try { this.ws.close({ success: () => formatAppLog("log", "at utils/socket.js:334", "连接已关闭"), fail: (err) => formatAppLog("error", "at utils/socket.js:335", "关闭失败:", err) }); } catch (error) { formatAppLog("error", "at utils/socket.js:343", "关闭连接出错:", error); } this.ws = null; } this.reconnectAttempts = 0; } /** * 更新配置项 * 合并新配置,不覆盖原有配置 * @param {Object} options - 新配置 */ updateOptions(options) { this.options = { ...this.options, ...options }; } }; const socketManager = new WebSocketManager$1(); const useSocketStore = defineStore("socket", () => { const connectionStatus = vue.ref("disconnected"); const messages = vue.ref([]); const messageString = vue.ref(""); const isThinking = vue.ref(false); const config = vue.ref({ token: "", conversationId: "" }); vue.ref(""); const logs = vue.ref([]); const maxLogCount = vue.ref(20); const isConnected = vue.computed(() => connectionStatus.value === "connected"); const isConnecting = vue.computed(() => connectionStatus.value === "connecting"); const isDisconnected = vue.computed(() => connectionStatus.value === "disconnected"); const isError = vue.computed(() => connectionStatus.value === "error"); const lastMessage = vue.computed(() => messages.value[messages.value.length - 1]); function addLog(type, connect2) { const now2 = /* @__PURE__ */ new Date(); const time = `${now2.getHours().toString().padStart(2, "0")}:${now2.getMinutes().toString().padStart(2, "0")}:${now2.getSeconds().toString().padStart(2, "0")}`; logs.value.push({ type, connect: connect2, time }); if (logs.value.length > maxLogCount.value) { logs.value = logs.value.slice(-maxLogCount.value); } formatAppLog("log", "at stores/socket.js:52", `[${type.toUpperCase()}] ${connect2}`); } function clearLogs() { logs.value = []; } function connect(options = {}) { messages.value = []; messageString.value = ""; config.value = { ...config.value, ...options }; addLog( "info", `准备连接WebSocket。Token:${config.value.token || "未设置"}。ConversationId: ${config.value.conversationId || "未设置"}` ); if (!config.value.token || !config.value.conversationId) { addLog("error", "Token和ConversationId都不能为空"); return; } connectionStatus.value = "connecting"; socketManager.connect({ token: config.value.token, conversationId: config.value.conversationId, onMessage: handleMessage, onError: handleError, onOpen: handleOpen, onClose: handleClose, onReconnect: handleReconnecting }); setConnectionTimeout(); } function disconnect() { socketManager.close(); connectionStatus.value = "disconnected"; addLog("warn", "已主动断开连接"); } async function send(message) { formatAppLog("log", "at stores/socket.js:96", "检查到要发生消息为:", message); if (!isConnected.value) { addLog("error", "发送失败: 连接未建立"); throw new Error("连接未建立"); } try { await socketManager.send(message); addLog("send", typeof message === "string" ? message : JSON.stringify(message)); return true; } catch (error) { addLog("error", `发送失败: ${error.message || error}`); throw error; } } function handleOpen() { connectionStatus.value = "connected"; addLog("success", "连接成功!发送auth"); formatAppLog("log", "at stores/socket.js:115", "连接成功!发送auth"); sendAuth(); } function handleClose() { if (connectionStatus.value !== "disconnected") { connectionStatus.value = "disconnected"; addLog("warn", "连接已断开"); } } function handleError(error) { addLog("error", `Socket错误: ${JSON.stringify(error)}`); connectionStatus.value = "error"; } function handleReconnecting(attempts) { connectionStatus.value = "connecting"; addLog("warn", `重连中... (${attempts}/5)`); } function setConnectionTimeout() { const timer = setTimeout(() => { if (connectionStatus.value === "connecting") { connectionStatus.value = "error"; addLog("error", "连接超时(10s)"); } }, 1e4); return timer; } function handleMessage(messageData) { addLog("receive", `收到: ${JSON.stringify(messageData)}`); const { type, conversation_id, message_id, data } = messageData || {}; formatAppLog("log", "at stores/socket.js:160", "[handleMessage] type =", type, ", data =", JSON.stringify(data)); switch (type) { case "auth_ok": addLog("success", "连接成功"); break; case "chat_ack": addLog("warn", "AI成功收到用户发送的消息"); break; case "render": addLog("warn", "AI正在回复信息"); handleBusinessMessage(data); break; default: addLog("info", `未知事件类型: ${type}`); } } function sendAuth() { config.value.token; socketManager.send({ "type": "auth", "access_token": config.value.token }); } function handleBusinessMessage(data) { if (data === "exit") { formatAppLog("log", "at stores/socket.js:212", "ai结束思考"); isThinking.value = false; return; } if (!data || typeof data !== "object") return; const { role, chunk, message_role, meaasge_uuid, message_type, task_call_id } = data; if (!isThinking.value && (chunk || message_role === "assistant")) { formatAppLog("log", "at stores/socket.js:233", "ai开始思考"); messageString.value = ""; isThinking.value = true; } if (chunk) { messageString.value += chunk; } } function getStatusText() { const statusMap = { connecting: "连接中", connected: "已连接", disconnected: "未连接", error: "连接错误" }; return statusMap[connectionStatus.value] || "未知状态"; } return { // 状态 connectionStatus, messageString, isThinking, logs, config, // 计算属性 isConnected, isConnecting, isDisconnected, isError, lastMessage, // 方法 connect, disconnect, send, addLog, clearLogs, getStatusText }; }); const BASE_Friend_URL = "http://chat.yuxindazhineng.com"; const getChatFriend = async (sendId) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_Friend_URL}/api/chatList/getChatFriend`, method: "POST", header: { "Content-Type": "application/json" }, data: { size: 500, current: 1, sendId }, success: (res) => { var _a; if (res.statusCode === 200) { const respond = res.data; formatAppLog("log", "at utils/friend-api.js:20", "获取到的好友列表消息", respond); if ((respond == null ? void 0 : respond.code) === 0 || (respond == null ? void 0 : respond.msg) === "成功") { const friendList = (_a = respond.data) == null ? void 0 : _a.records; if (friendList.length > 0) { const receiverId = friendList[0].receiver; if (receiverId) { uni.setStorageSync("receiverId", receiverId); } } resolve(friendList); } else { const msg = res.data.error || "获取好友列表出错啦"; reject(msg); } } else { reject(`获取好友列表失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getGroup = async (sendId) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_Friend_URL}/api/group/getGroup`, method: "POST", header: { "Content-Type": "application/json" }, data: { size: 500, current: 1, contactId: sendId }, success: (res) => { var _a; if (res.statusCode === 200) { const respond = res.data; if ((respond == null ? void 0 : respond.code) === 0 || (respond == null ? void 0 : respond.msg) === "成功") { const groupList = (_a = respond.data) == null ? void 0 : _a.records; resolve(groupList); } else { const msg = res.data.error || "获取群聊列表出错啦"; reject(msg); } } else { reject(`获取群聊列表失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getFriendMessages = async (sessionId, current = 1) => { formatAppLog("log", "at utils/friend-api.js:88", "请求的好友消息id:", sessionId); return new Promise((resolve, reject) => { uni.request({ url: `${BASE_Friend_URL}/api/message/list`, method: "POST", data: { "sessionId": sessionId, "size": 100, "current": current, "beginTime": "", "endTime": "" }, header: { "Content-Type": "application/json" }, success: (res) => { var _a; if (res.statusCode === 200) { const messagesInfo = res.data; if (messagesInfo.code === 0) { const messageList = ((_a = messagesInfo == null ? void 0 : messagesInfo.data) == null ? void 0 : _a.records) || []; const reversedList = messageList.reverse(); resolve(reversedList); } else { const msg = res.data.error || "获取好友消息出错啦"; reject(msg); } } else { reject(`请求失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getGroupMessages = async (groupId, current = 1) => { formatAppLog("log", "at utils/friend-api.js:134", "请求的群聊消息id:", groupId); return new Promise((resolve, reject) => { uni.request({ url: `${BASE_Friend_URL}/api/group/getGroupList`, method: "POST", data: { "current": current, "size": 100, "groupId": groupId, "beginTime": "", "endTime": "" }, header: { "Content-Type": "application/json" }, success: (res) => { var _a; if (res.statusCode === 200) { const messagesInfo = res.data; formatAppLog("log", "at utils/friend-api.js:152", "获取到的群聊信息:", messagesInfo); if (messagesInfo.code === 0) { const messageList = ((_a = messagesInfo == null ? void 0 : messagesInfo.data) == null ? void 0 : _a.records) || []; const reversedList = messageList.reverse(); resolve(reversedList); } else { const msg = res.data.error || "获取群聊消息出错啦"; reject(msg); } } else { reject(`请求失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const getGroupMemberList = async (groupId) => { return new Promise((resolve, reject) => { uni.request({ url: `${BASE_Friend_URL}/api/group/getGroupMemberList`, method: "POST", header: { "Content-Type": "application/json" }, data: { "groupId": groupId, "current": 1, "size": 100 }, success: (res) => { if (res.statusCode === 200) { const respond = res.data; if (respond.code === 0) { const groupMemberList = respond.data.records; resolve(groupMemberList); } else { const msg = res.data.error || "获取群成员出错啦"; reject(msg); } } else { reject(`请求群成员失败:${res.statusCode}`); } }, fail: (err) => { const msg = err.errMsg || "网络错误"; reject(msg); } }); }); }; const uploadFileToServer = (filePath) => { return new Promise((resolve, reject) => { uni.uploadFile({ url: `${BASE_Friend_URL}/api/file/upload`, filePath, name: "file", success: (res) => { const data = JSON.parse(res.data); if (data.code === 0) { resolve(data.data); } else { reject(data.msg || "上传失败"); } }, fail: (err) => { reject(err.errMsg || "网络错误"); } }); }); }; const WS_Friend_URL = "wss://wss.yuxindazhineng.com"; class WebSocketManager { constructor() { this.ws = null; this.url = `${WS_Friend_URL}/ws`; this.options = { token: "", UserId: "", onMessage: null, onError: null, onReconnect: null, onOpen: null, onClose: null }; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.reconnectDelay = 3e3; this.reconnectTimer = null; this.heartbeatTimer = null; this.isManualClose = false; } /** * 初始化连接 * @param {string} url WebSocket URL * @param {Object} options 配置选项 */ connect(options = {}) { this.options = { ...this.options, ...options }; this.isManualClose = false; if (this.ws) { this.close(); } try { this.ws = uni.connectSocket({ url: this.url, success: () => { formatAppLog("log", "at utils/friend-socket.js:44", "WebSocket 连接请求已发送"); }, fail: (err) => { formatAppLog("error", "at utils/friend-socket.js:47", "WebSocket 连接失败:", err); this.handleError(err); } }); this.initEventHandlers(); } catch (err) { this.handleError(err); } } /** * 初始化事件处理 */ initEventHandlers() { if (!this.ws) return; this.ws.onOpen((event) => { var _a, _b, _c, _d; formatAppLog("log", "at utils/friend-socket.js:74", "WebSocket 已连接"); if (this.reconnectAttempts > 0) { (_b = (_a = this.options).onReconnect) == null ? void 0 : _b.call(_a); } (_d = (_c = this.options).onOpen) == null ? void 0 : _d.call(_c, event); this.reconnectAttempts = 0; }); this.ws.onMessage((event) => { try { const data = JSON.parse(event.data); formatAppLog("log", "at utils/friend-socket.js:87", "收到了返回消息:", data); this.handleMessage(data); } catch (err) { formatAppLog("error", "at utils/friend-socket.js:90", "消息解析失败:", err); uni.setStorageSync("currentSessionId", event.data.task_call_id); } }); this.ws.onError((err) => { formatAppLog("error", "at utils/friend-socket.js:95", "WebSocket 错误:", err); this.handleError(err); }); this.ws.onClose((event) => { var _a, _b; formatAppLog("log", "at utils/friend-socket.js:99", "WebSocket 已关闭:", event.code, event.reason); (_b = (_a = this.options).onClose) == null ? void 0 : _b.call(_a, event); if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnect(); } }); } /** * 处理服务端推送的消息 * @param {Object} msg - 服务端返回的原始消息对象 */ handleMessage(msg) { var _a, _b; (_b = (_a = this.options).onMessage) == null ? void 0 : _b.call(_a, msg); } /** * 统一发送消息方法 * 兼容 APP / 微信小程序 环境 * @param {Object} data - 要发送的消息对象 * @returns {Promise} 发送结果 */ send(data) { return new Promise((resolve, reject) => { if (!this.isConnected()) { reject(new Error("WebSocket 未连接")); return; } const msg = JSON.stringify(data); formatAppLog("log", "at utils/friend-socket.js:170", "发送的消息是:", msg); this.ws.send({ data: msg, success: () => resolve(), fail: (err) => { formatAppLog("error", "at utils/friend-socket.js:178", "发送消息失败:", err); reject(err); } }); }); } /** * 自动重连机制 * 指数退避重连,避免频繁重连 */ reconnect() { if (this.reconnectTimer) return; this.reconnectAttempts++; formatAppLog("log", "at utils/friend-socket.js:204", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; if (!this.isManualClose) { this.connect(this.options); } }, this.reconnectDelay * this.reconnectAttempts); } /** * 启动心跳定时器 * 每30秒发送一次 ping 保持连接 */ startHeartbeat() { this.stopHeartbeat(); this.heartbeatTimer = setInterval(() => { if (this.isConnected()) { this.send({ ws_event: "ping" }).catch(() => { formatAppLog("log", "at utils/friend-socket.js:226", "心跳发送失败,准备重连"); if (!this.reconnectTimer && !this.isManualClose) { this.reconnect(); } }); } else if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnect(); } }, 3e4); } /** * 停止心跳定时器 */ stopHeartbeat() { if (this.heartbeatTimer) { clearInterval(this.heartbeatTimer); this.heartbeatTimer = null; } } /** * 统一错误处理 * @param {Error} error - 错误对象 */ handleError(error) { var _a, _b; formatAppLog("error", "at utils/friend-socket.js:254", "WebSocket 错误处理:", JSON.stringify(error)); (_b = (_a = this.options).onError) == null ? void 0 : _b.call(_a, error); } /** * 判断 WebSocket 是否处于已连接状态 * @returns {boolean} */ isConnected() { if (!this.ws) return false; return this.ws.readyState === 1; } /** * 方便外部获取连接状态码 * @returns {number} 0:连接中,1:已连接,2:关闭中,3:已关闭 */ getReadyState() { if (!this.ws) return 3; return this.ws.readyState; } /** * 手动关闭 WebSocket 连接 * 清理所有定时器、标记手动关闭、停止重连 */ close() { formatAppLog("log", "at utils/friend-socket.js:290", "手动关闭 WebSocket 连接"); this.isManualClose = true; this.stopHeartbeat(); if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } if (this.ws) { if (this.ws.onOpen) this.ws.onOpen(null); if (this.ws.onMessage) this.ws.onMessage(null); if (this.ws.onError) this.ws.onError(null); if (this.ws.onClose) this.ws.onClose(null); try { this.ws.close({ success: () => formatAppLog("log", "at utils/friend-socket.js:312", "连接已关闭"), fail: (err) => formatAppLog("error", "at utils/friend-socket.js:313", "关闭失败:", err) }); } catch (error) { formatAppLog("error", "at utils/friend-socket.js:321", "关闭连接出错:", error); } this.ws = null; } this.reconnectAttempts = 0; } /** * 更新配置项 * 合并新配置,不覆盖原有配置 * @param {Object} options - 新配置 */ updateOptions(options) { this.options = { ...this.options, ...options }; } } const friendSocketManager = new WebSocketManager(); const useFriendSocketStore = defineStore("friendSocket", () => { const connectionStatus = vue.ref("disconnected"); const messages = vue.ref([]); const messageString = vue.ref(""); const config = vue.ref({ token: "", UserId: "" }); vue.ref(""); const command = vue.ref(null); const groupId = vue.ref(null); const MessageReceived = vue.ref(false); const logs = vue.ref([]); const maxLogCount = vue.ref(20); const isConnected = vue.computed(() => connectionStatus.value === "connected"); const isConnecting = vue.computed(() => connectionStatus.value === "connecting"); const isDisconnected = vue.computed(() => connectionStatus.value === "disconnected"); const isError = vue.computed(() => connectionStatus.value === "error"); const lastMessage = vue.computed(() => messages.value[messages.value.length - 1]); function addLog(type, connect2) { const now2 = /* @__PURE__ */ new Date(); const time = `${now2.getHours().toString().padStart(2, "0")}:${now2.getMinutes().toString().padStart(2, "0")}:${now2.getSeconds().toString().padStart(2, "0")}`; logs.value.push({ type, connect: connect2, time }); if (logs.value.length > maxLogCount.value) { logs.value = logs.value.slice(-maxLogCount.value); } formatAppLog("log", "at stores/friend-socket.js:57", `[${type.toUpperCase()}] ${connect2}`); } function clearLogs() { logs.value = []; } function connect(options = {}) { messages.value = []; messageString.value = ""; config.value = { ...config.value, ...options }; addLog( "info", `准备连接FriendsWebSocket。Token:${config.value.token || "未设置"}。UserId: ${config.value.UserId || "未设置"}` ); if (!config.value.token || !config.value.UserId) { addLog("error", "Token和UserId都不能为空"); return; } connectionStatus.value = "connecting"; friendSocketManager.connect({ token: config.value.token, UserId: config.value.UserId, onMessage: handleMessage, onError: handleError, onOpen: handleOpen, onClose: handleClose, onReconnect: handleReconnecting }); setConnectionTimeout(); } function disconnect() { friendSocketManager.close(); connectionStatus.value = "disconnected"; addLog("warn", "已主动断开连接"); } async function send(message) { if (!isConnected.value) { addLog("error", "发送失败: 连接未建立"); throw new Error("连接未建立"); } try { await friendSocketManager.send(message); addLog("send", typeof message === "string" ? message : JSON.stringify(message)); return true; } catch (error) { addLog("error", `发送失败: ${error.message || error}`); throw error; } } async function sendAuthData() { const userId = getUserId(); const authData = { "version": "1.1", "body": { "command": 7, "sender": userId, "avatar": "", "sessionId": "", "message": "", "callBackMessage": false } }; try { await friendSocketManager.send(authData); addLog("send", typeof authData === "string" ? authData : JSON.stringify(authData)); return true; } catch (error) { addLog("error", `发送验证失败: ${error.message || error}`); throw error; } } function handleOpen() { connectionStatus.value = "connected"; addLog("success", "连接成功!"); sendAuthData(); } function handleClose() { if (connectionStatus.value !== "disconnected") { connectionStatus.value = "disconnected"; addLog("warn", "连接已断开"); } } function handleError(error) { addLog("error", `Socket错误: ${JSON.stringify(error)}`); connectionStatus.value = "error"; } function handleReconnecting(attempts) { connectionStatus.value = "connecting"; addLog("warn", `重连中... (${attempts}/5)`); } function setConnectionTimeout() { const timer = setTimeout(() => { if (connectionStatus.value === "connecting") { connectionStatus.value = "error"; addLog("error", "连接超时(10s)"); } }, 1e4); return timer; } function handleMessage(messageData) { addLog("receive", `收到: ${JSON.stringify(messageData)}`); const msgBody = messageData.body || messageData; const { callBackMessage, groupName, command: msgCommand, groupId: msgGroupId } = msgBody || {}; switch (msgCommand) { case 3: command.value = msgCommand; groupId.value = msgGroupId; break; case 7: command.value = msgCommand; break; case 1: formatAppLog("log", "at stores/friend-socket.js:199", "有好友消息"); MessageReceived.value = true; break; case 9: formatAppLog("log", "at stores/friend-socket.js:204", "群消息发送成功/有新群消息"); MessageReceived.value = true; break; default: addLog("info", `未知事件类型`); } } function getStatusText() { const statusMap = { connecting: "连接中", connected: "已连接", disconnected: "未连接", error: "连接错误" }; return statusMap[connectionStatus.value] || "未知状态"; } return { // 状态 connectionStatus, //属性变量 messageString, logs, config, command, groupId, MessageReceived, // 计算属性 isConnected, isConnecting, isDisconnected, isError, lastMessage, // 方法 connect, disconnect, send, addLog, clearLogs, getStatusText }; }); const { registerUTSInterface, initUTSProxyClass, initUTSProxyFunction, initUTSPackageName, initUTSIndexClassName, initUTSClassName } = uni; const name = "limeChooseFile"; const moduleName = "lime-choose-file 文件选择"; const moduleType = ""; const errMsg = ``; const is_uni_modules = true; const pkg = /* @__PURE__ */ initUTSPackageName(name, is_uni_modules); const cls = /* @__PURE__ */ initUTSIndexClassName(name, is_uni_modules); const exports$1 = { __esModule: true }; exports$1.chooseFile = /* @__PURE__ */ initUTSProxyFunction(false, { moduleName, moduleType, errMsg, main: true, package: pkg, class: cls, name: "chooseFileByJs", keepAlive: false, params: [{ "name": "options", "type": "UTSSDKModulesLimeChooseFileChooseFileOptionJSONObject" }], return: "" }); uni.registerUTSPlugin("uni_modules/lime-choose-file", exports$1); const limeChooseFile_utsProxy = uni.requireUTSPlugin("uni_modules/lime-choose-file"); const pageInfoNumber = 100; const _sfc_main$7 = { __name: "Chat", setup(__props, { expose: __expose }) { __expose(); const friendSocketStore = useFriendSocketStore(); const handleFriendConnect = () => { if (friendSocketStore.isConnected) return; if (!userToken.value || !UserId.value) { formatAppLog("warn", "at pages/Chat/Chat.vue:265", "Token或UserId未准备好"); return; } friendSocketStore.connect({ token: userToken.value, UserId: UserId.value }); }; const socketStore = useSocketStore(); const ChatType = vue.ref(0); const convertMarkdownTable = (text) => { const lines = text.split("\n"); let result = []; let inTable = false; let tableRows = []; let alignments = []; for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); const isTableLine = /^\|.+|$/.test(line) && line.includes("|"); if (isTableLine) { if (/^\|[\s\-:]+\|[\s\-:|]+\|$/.test(line)) { alignments = line.split("|").filter((c) => c.trim()).map((c) => { if (c.trim().startsWith(":") && c.trim().endsWith(":")) return "center"; if (c.trim().endsWith(":")) return "right"; return "left"; }); continue; } tableRows.push(line); inTable = true; } else { if (inTable && tableRows.length > 0) { result.push(renderTable(tableRows, alignments)); tableRows = []; alignments = []; inTable = false; } result.push(line); } } if (inTable && tableRows.length > 0) { result.push(renderTable(tableRows, alignments)); } return result.join("\n"); }; const renderTable = (rows, alignments) => { let html = ''; rows.forEach((row, index) => { const tag = index === 0 ? "th" : "td"; const cells = row.split("|").filter((c) => c.trim() !== ""); html += ""; cells.forEach((cell, ci) => { const align = alignments[ci] ? ` style="text-align:${alignments[ci]}"` : ""; html += `<${tag}${align} style="padding:6px 10px;border:1px solid #ddd">${cell.trim()}`; }); html += ""; }); html += "
    "; return html; }; const pareseMarkdown = (content) => { if (!content) return ""; content = sanitizeContent(content); try { content = convertMarkdownTable(content); const html = t(content); return html; } catch (e2) { formatAppLog("error", "at pages/Chat/Chat.vue:363", "解析失败", e2); return content; } }; const sanitizeContent = (str) => { const hasScript = /]*>([\s\S]*?)<\/script>/i.test(str); const hasFormTags = /<(form|input|select|textarea|button)\b[^>]*>/i.test(str); let cleanedStr = str.replace(/]*>([\s\S]*?)<\/script>/gi, ""); cleanedStr = cleanedStr.replace(/<\/?minimax:tool_call>/g, (m) => m.replace(//g, ">")).replace(/<\|[\w]+?\|>/g, (m) => m.replace(//g, ">")); if (hasScript || hasFormTags) { const warningHtml = '

    表单仅预览,不可操作!!!

    '; return warningHtml + cleanedStr; } return cleanedStr; }; const previewImage = (url) => { uni.previewImage({ urls: [url] }); }; const openFile = (url) => { uni.downloadFile({ url, success: (res) => { uni.openDocument({ filePath: res.tempFilePath, showMenu: true }); } }); }; const formatFileSize = (size) => { if (!size) return "0KB"; if (size < 1) { return (size * 1024).toFixed(0) + "KB"; } return size.toFixed(2) + "MB"; }; const selectNormalChat = async () => { try { const chars = "0123456789abcdef"; let name2 = ""; for (let i = 0; i < 24; i++) { name2 += chars[Math.floor(Math.random() * chars.length)]; } const workspaceId = await createWorkspace(userToken.value, name2); if (!workspaceId) { uni.showToast({ title: "工作区创建失败", icon: "none" }); return; } const loginInfo = uni.getStorageSync("yxd_login_info"); let userName = ""; if (loginInfo) { userName = loginInfo.username || ""; } const conversationId = await createConversation(userToken.value, workspaceId, "新会话", userName); if (!conversationId) { uni.showToast({ title: "新会话创建失败", icon: "none" }); return; } takeUserConversations(); } catch (error) { formatAppLog("error", "at pages/Chat/Chat.vue:457", "新建普通会话失败:", error); uni.showToast({ title: "创建会话失败,请重试", icon: "none" }); } }; const showNewChatModal = vue.ref(false); const closeNewChatModal = () => { showNewChatModal.value = false; }; const isChatSidebar = vue.ref(false); const handleChatSidebar = () => { isChatSidebar.value = !isChatSidebar.value; }; const goWorkSpace = () => { if (currentSessionId.value) { uni.setStorageSync("currentSessionId", currentSessionId.value); } uni.navigateTo({ url: "/pages/WorkSpace/WorkSpace" }); }; const logOut = () => { uni.reLaunch({ url: "/pages/Login/Login" }); }; const previewFileArray = vue.ref([]); const uploadPhoto = () => { formatAppLog("log", "at pages/Chat/Chat.vue:495", "点击了拍照上传"); uni.chooseImage({ count: 1, sourceType: ["camera", "album"], success: (res) => { const tempFiles = res.tempFiles; const tempFilePaths = res.tempFilePaths; tempFiles.forEach((file, index) => { previewFileArray.value.push({ path: tempFilePaths[index], // 图片路径(用于显示) name: file.name || `photo_${Date.now()}_${index}.jpg`, // 文件名 size: file.size, // 文件大小 type: "image", // 文件类型标识 tempFile: file // 原始文件对象 }); }); }, fail: (err) => { formatAppLog("error", "at pages/Chat/Chat.vue:513", "选择图片失败", err); } }); }; const deleteImage = (index) => { uni.showModal({ title: "提示", content: "确定要删除这张图片吗?", success: (res) => { if (res.confirm) { previewFileArray.value.splice(index, 1); uni.showToast({ title: "删除成功", icon: "success" }); } } }); }; const fileList = vue.ref([]); const uploadFile = () => { formatAppLog("log", "at pages/Chat/Chat.vue:536", "点击了上传文件"); limeChooseFile_utsProxy.chooseFile({ count: 5, type: "all", success: (res) => { formatAppLog("log", "at pages/Chat/Chat.vue:541", "成功了"); fileList.value = res.tempFiles; previewFileArray.value.push(...res.tempFiles); uni.showToast({ title: `已选择 ${res.tempFiles.length} 个文件`, icon: "success" }); }, fail: (err) => { formatAppLog("error", "at pages/Chat/Chat.vue:552", "选择失败:", err); uni.showToast({ title: "选择失败", icon: "error" }); } }); }; const handleConnect = () => { return new Promise((resolve, reject) => { if (socketStore.isConnected) return resolve(); const unwatch = vue.watch(() => socketStore.isConnected, (connected) => { if (connected) { unwatch(); resolve(); } }); const unwatchError = vue.watch(() => socketStore.connectionStatus, (status) => { if (status === "error") { unwatch(); unwatchError(); reject(new Error("连接失败")); } }); socketStore.connect({ token: userToken.value, conversationId: currentSessionId.value }); }); }; const isThinking = vue.ref(false); const isUploading = vue.ref(false); const uploadedFiles = vue.ref([]); const sendMessage = async () => { const message = textMessage.value.trim(); if (!message && previewFileArray.value.length === 0) return; if (previewFileArray.value.length > 0) { isUploading.value = true; uni.showLoading({ title: "上传文件中...", mask: true }); try { const results = []; for (const item of previewFileArray.value) { const result = await uploadFileToServer(item.path); results.push(result); } uploadedFiles.value = results; previewFileArray.value = []; } catch (err) { uni.hideLoading(); formatAppLog("error", "at pages/Chat/Chat.vue:619", "文件上传失败:", err); uni.showToast({ title: "文件上传失败,请重试", icon: "error" }); isUploading.value = false; return; } uni.hideLoading(); isUploading.value = false; } if (ChatType.value === 0) sendAIMessage(); if (ChatType.value === 1) sendFriendMessage(); if (ChatType.value === 2) sendGroupMessage(); }; const sendFriendMessage = async () => { if (!friendSocketStore.isConnecting) await handleFriendConnect(); const receiverId = getReceiverId(); const hasFiles = uploadedFiles.value.length > 0; const body = { "command": 1, "sender": UserId.value, "receiver": receiverId, "avatar": "", "sessionId": currentSessionId.value, "message": textMessage.value, "callBackMessage": false }; if (hasFiles) { body.contentType = 1; body.uploadVos = uploadedFiles.value; } const data = { "version": "1.1", "body": body }; friendSocketStore.send(data); const newMessageData = { "sender": UserId.value, "receiver": receiverId, "content": textMessage.value, "taskId": null, "avatar": null, "createTime": "", "messageType": "null", "contentJson": hasFiles ? JSON.stringify(uploadedFiles.value) : "null" }; allmessages.value = [...allmessages.value, newMessageData]; textMessage.value = ""; uploadedFiles.value = []; setTimeout(() => { takeFriendMessages(); }, 1e3); }; const sendGroupMessage = async () => { if (!friendSocketStore.isConnecting) await handleFriendConnect(); const hasFiles = uploadedFiles.value.length > 0; const body = { "command": 9, "groupId": currentSessionId.value, "message": textMessage.value || "", "callBackMessage": hasFiles ? false : true, "messageType": hasFiles ? 1 : 0, "sender": UserId.value }; if (hasFiles) { body.uploadVos = uploadedFiles.value; } const data = { "version": "1.1", "body": body }; friendSocketStore.send(data); const newMessageData = { "id": allmessages.value.length + 1, "message": textMessage.value, "messageType": hasFiles ? 1 : 0, "groupId": null, "createTime": "", "contentJson": hasFiles ? JSON.stringify(uploadedFiles.value) : "", "sender": UserId.value }; allmessages.value = [...allmessages.value, newMessageData]; textMessage.value = ""; uploadedFiles.value = []; setTimeout(() => { takeGroupMessages(); }, 1e3); }; let aiResponseTimer = null; const sendAIMessage = async () => { try { await handleConnect(); let messageContent = textMessage.value; if (uploadedFiles.value.length) { const fileJson = JSON.stringify(uploadedFiles.value); messageContent = messageContent ? `${messageContent} [文件信息:${fileJson}]` : `[文件信息:${fileJson}]`; } const data = { "type": "chat", "conversation_id": currentSessionId.value, "content": messageContent }; socketStore.send(data); isThinking.value = true; aiResponseTimer = setTimeout(() => { uni.showToast({ title: "AI回复超时,请重试", icon: "none" }); isThinking.value = false; textMessage.value = ""; uploadedFiles.value = []; }, 18e4); } catch (error) { isThinking.value = false; uni.showToast({ title: `用户发送消息失败${error}`, icon: "error" }); } }; vue.watch(() => socketStore.isThinking, (newVal, oldVal) => { formatAppLog("log", "at pages/Chat/Chat.vue:781", "isThinking 变化:", oldVal, "→", newVal); if (oldVal && !newVal && socketStore.messageString) { clearTimeout(aiResponseTimer); formatAppLog("log", "at pages/Chat/Chat.vue:785", "ai返回的消息:", socketStore.messageString); formatAppLog("log", "at pages/Chat/Chat.vue:786", "AI回复结束,刷新消息列表"); takeConversationMessages(); isThinking.value = false; textMessage.value = ""; uploadedFiles.value = []; } }); const textMessage = vue.ref(""); const UserConversations = vue.ref([]); const currentSessionId = vue.ref(""); const userToken = vue.ref(""); const UserId = vue.ref(""); const UserAvatar = vue.ref(""); const UserData = vue.ref(null); const takeUserInfo = async () => { try { userToken.value = getToken(); UserData.value = await getUserInfo(userToken.value); UserId.value = UserData.value._id; UserAvatar.value = UserData.value.avatar || ""; formatAppLog("log", "at pages/Chat/Chat.vue:812", "用户信息已加载:", UserId.value, UserAvatar.value); } catch (error) { formatAppLog("error", "at pages/Chat/Chat.vue:814", "获取用户信息失败:", error); } }; const takeUserConversations = async () => { try { userToken.value = getToken(); formatAppLog("log", "at pages/Chat/Chat.vue:822", "token:", userToken.value); UserConversations.value = await getUserConversations(userToken.value) || []; formatAppLog("log", "at pages/Chat/Chat.vue:824", "UserConversations:", UserConversations.value); const savedSessionId = getCurrentSessionId(); if (savedSessionId && UserConversations.value.some((c) => c._id === savedSessionId)) { currentSessionId.value = savedSessionId; } else if (UserConversations.value.length > 0) { currentSessionId.value = UserConversations.value[0]._id; } else { currentSessionId.value = ""; } formatAppLog("log", "at pages/Chat/Chat.vue:834", "保存会话id:", currentSessionId.value); uni.setStorageSync("currentSessionId", currentSessionId.value); } catch (error) { uni.showToast({ title: `获取会话列表失败${error}`, icon: "error" }); } }; const FriendInfoList = vue.ref([]); const takeFriendList = async () => { try { formatAppLog("log", "at pages/Chat/Chat.vue:849", "开始获取好友列表"); const friendList = await getChatFriend(UserId.value); formatAppLog("log", "at pages/Chat/Chat.vue:852", "friendList:", friendList); if (friendList && friendList.length) { FriendInfoList.value = await takeUserAvatar(friendList); } else { FriendInfoList.value = []; formatAppLog("log", "at pages/Chat/Chat.vue:857", "好友列表为空"); } } catch (error) { formatAppLog("error", "at pages/Chat/Chat.vue:860", "获取好友列表失败:", error); FriendInfoList.value = []; } finally { UserConversations.value = FriendInfoList.value; } }; const takeTalkUserAvatar = (userId) => { if (!userId) return null; const user = FriendInfoList.value.find((item) => item.receiver === userId); return (user == null ? void 0 : user.avatar) || null; }; const takeUserAvatar = async (friendList) => { if (!(friendList == null ? void 0 : friendList.length)) return []; try { const friendIds = friendList.map((item) => item.receiver); const friendAvatarList = await getUserAvatar(userToken.value, friendIds); const userMap = new Map(friendAvatarList.map((user) => [user.user_id, user]) || []); return friendList.map((friend) => { const userInfo = userMap.get(friend.receiver); return { ...friend, avatar: (userInfo == null ? void 0 : userInfo.avatar) || null }; }); } catch (err) { formatAppLog("error", "at pages/Chat/Chat.vue:890", "获取好友头像失败", err); return friendList; } }; const GroupList = vue.ref([]); const takeGroupList = async () => { try { formatAppLog("log", "at pages/Chat/Chat.vue:900", "开始获取群聊列表"); GroupList.value = await getGroup(UserId.value); } catch (error) { formatAppLog("error", "at pages/Chat/Chat.vue:905", "获取群聊列表失败:", error); GroupList.value = []; } finally { UserConversations.value = GroupList.value; } }; const groupMemberList = vue.ref([]); const takeGroupMemberAvatar = async (memberList) => { if (!(memberList == null ? void 0 : memberList.length)) return []; try { const memberIds = memberList.map((item) => item.groupContactId); formatAppLog("log", "at pages/Chat/Chat.vue:919", "请求头像的ID列表:", memberIds); const memberAvatarList = await getUserAvatar(userToken.value, memberIds); formatAppLog("log", "at pages/Chat/Chat.vue:921", "头像接口返回数据:", memberAvatarList); const userMap = new Map(memberAvatarList.map((user) => [user.user_id, user]) || []); formatAppLog("log", "at pages/Chat/Chat.vue:924", "userMap的keys:", Array.from(userMap.keys())); return memberList.map((member) => { const memberId = member.groupContactId; const userInfo = userMap.get(memberId); formatAppLog("log", "at pages/Chat/Chat.vue:929", `查找 ${memberId} 的头像:`, userInfo); return { ...member, avatar: (userInfo == null ? void 0 : userInfo.avatar) || null }; }); } catch (err) { formatAppLog("error", "at pages/Chat/Chat.vue:936", "获取群成员头像失败", err); return memberList; } }; const getGroupMemberAvatarById = (userId) => { if (!userId) return null; const member = groupMemberList.value.find((item) => item.groupContactId === userId); return (member == null ? void 0 : member.avatar) || null; }; const allmessages = vue.ref([]); const scrollToView = vue.ref(""); const isLoadingMore = vue.ref(false); const currentPage = vue.ref(1); const currentMessages = vue.computed(() => { return allmessages.value.slice(-pageInfoNumber); }); const takeConversationMessages = async () => { try { allmessages.value = await getConversationMessages(userToken.value, currentSessionId.value) || []; scrollToBottom(); } catch (error) { uni.showToast({ title: `获取ai会话内容失败${error}`, icon: "none" }); } }; const takeFriendMessages = async () => { try { allmessages.value = await getFriendMessages(currentSessionId.value) || []; formatAppLog("log", "at pages/Chat/Chat.vue:981", "好友消息:", JSON.stringify(allmessages.value)); scrollToBottom(); } catch (error) { uni.showToast({ title: `获取好友会话消息失败${error}`, icon: "none" }); } }; const takeGroupMessages = async () => { try { allmessages.value = await getGroupMessages(currentSessionId.value) || []; formatAppLog("log", "at pages/Chat/Chat.vue:994", "群聊消息:", allmessages.value); const memberList = await getGroupMemberList(currentSessionId.value); formatAppLog("log", "at pages/Chat/Chat.vue:997", "获取到的群成员列表:", memberList); if (memberList && memberList.length) { groupMemberList.value = await takeGroupMemberAvatar(memberList); formatAppLog("log", "at pages/Chat/Chat.vue:1000", "群成员列表(带头像):", groupMemberList.value); } else { groupMemberList.value = []; } scrollToBottom(); } catch (error) { uni.showToast({ title: `获取群聊会话失败${error}`, icon: "none" }); } }; const loadMoreMessages = async () => { formatAppLog("log", "at pages/Chat/Chat.vue:1015", "加载更多信息"); if (allmessages.value.length > pageInfoNumber * currentPage.value) { currentPage.value += 1; const newMessages = allmessages.value.slice(-pageInfoNumber * currentPage.value); const addMessage = newMessages.length - currentMessages.value.length; currentMessages.value = newMessages; await vue.nextTick(); scrollToView.value = "msg-" + (addMessage + 1); } }; const onScroll = (e2) => { }; const scrollToBottom = async () => { await vue.nextTick(); if (currentMessages.value.length > 0) { scrollToView.value = "msg-" + (currentMessages.value.length - 1); } }; vue.watch(() => friendSocketStore.MessageReceived, (newId) => { formatAppLog("log", "at pages/Chat/Chat.vue:1043", "收到了好友消息"); if (newId) { formatAppLog("log", "at pages/Chat/Chat.vue:1045", "ChatType:", ChatType.value); switch (ChatType.value) { case 0: takeConversationMessages(); friendSocketStore.MessageReceived = false; break; case 1: takeFriendMessages(); friendSocketStore.MessageReceived = false; break; case 2: takeGroupMessages(); friendSocketStore.MessageReceived = false; break; default: formatAppLog("log", "at pages/Chat/Chat.vue:1061", "default 分支"); friendSocketStore.MessageReceived = false; break; } } }, { immediate: true }); vue.watch(currentSessionId, (newId) => { if (newId) { uni.setStorageSync("currentSessionId", currentSessionId.value); switch (ChatType.value) { case 0: takeConversationMessages(); break; case 1: takeFriendMessages(); break; case 2: takeGroupMessages(); break; default: takeConversationMessages(); break; } } }, { immediate: true }); vue.onMounted(() => { }); onShow(async () => { await takeUserInfo(); const chatType = getChatType(); ChatType.value = chatType; const sessionId = getCurrentSessionId(); if (sessionId) { currentSessionId.value = sessionId; } if (chatType === 0) { await takeUserConversations(); if (currentSessionId.value) { takeConversationMessages(); } } else if (chatType === 1) { await takeFriendList(); takeFriendMessages(); handleFriendConnect(); } else if (chatType === 2) { await takeGroupList(); await handleFriendConnect(); await takeGroupMessages(); } }); const __returned__ = { friendSocketStore, handleFriendConnect, socketStore, ChatType, convertMarkdownTable, renderTable, pareseMarkdown, sanitizeContent, previewImage, openFile, formatFileSize, selectNormalChat, showNewChatModal, closeNewChatModal, isChatSidebar, handleChatSidebar, goWorkSpace, logOut, previewFileArray, uploadPhoto, deleteImage, fileList, uploadFile, handleConnect, isThinking, isUploading, uploadedFiles, sendMessage, sendFriendMessage, sendGroupMessage, get aiResponseTimer() { return aiResponseTimer; }, set aiResponseTimer(v) { aiResponseTimer = v; }, sendAIMessage, textMessage, UserConversations, currentSessionId, userToken, UserId, UserAvatar, UserData, takeUserInfo, takeUserConversations, FriendInfoList, takeFriendList, takeTalkUserAvatar, takeUserAvatar, GroupList, takeGroupList, groupMemberList, takeGroupMemberAvatar, getGroupMemberAvatarById, allmessages, pageInfoNumber, scrollToView, isLoadingMore, currentPage, currentMessages, takeConversationMessages, takeFriendMessages, takeGroupMessages, loadMoreMessages, onScroll, scrollToBottom, computed: vue.computed, getCurrentInstance: vue.getCurrentInstance, nextTick: vue.nextTick, onMounted: vue.onMounted, ref: vue.ref, watch: vue.watch, get onShow() { return onShow; }, ChatSidebar, get getUserConversations() { return getUserConversations; }, get getConversationMessages() { return getConversationMessages; }, get addMessageDict() { return addMessageDict; }, get createWorkspace() { return createWorkspace; }, get createConversation() { return createConversation; }, get getUserInfo() { return getUserInfo; }, get getUserAvatar() { return getUserAvatar; }, get getToken() { return getToken; }, get getCurrentSessionId() { return getCurrentSessionId; }, get getTaskCallId() { return getTaskCallId; }, get getChatType() { return getChatType; }, get getReceiverId() { return getReceiverId; }, get snarkdown() { return t; }, get useSocketStore() { return useSocketStore; }, get getChatFriend() { return getChatFriend; }, get getGroup() { return getGroup; }, get getFriendMessages() { return getFriendMessages; }, get getGroupMessages() { return getGroupMessages; }, get getGroupMemberList() { return getGroupMemberList; }, get uploadFileToServer() { return uploadFileToServer; }, get useFriendSocketStore() { return useFriendSocketStore; }, get chooseFile() { return limeChooseFile_utsProxy.chooseFile; }, get socketManager() { return socketManager; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), $setup.showNewChatModal ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "ncd-overlay", onClick: $setup.closeNewChatModal }, [ vue.createElementVNode("view", { class: "ncd-card", onClick: _cache[0] || (_cache[0] = vue.withModifiers(() => { }, ["stop"])) }, [ vue.createElementVNode("view", { class: "ncd-header" }, [ vue.createElementVNode("view", { class: "ncd-title-eng" }, [ vue.createElementVNode("text", null, "NEW") ]), vue.createElementVNode("text", { class: "ncd-title-zh" }, "创建对话"), vue.createVNode(_component_uni_icons, { type: "closeempty", color: "#ff0000", size: "24", onClick: $setup.closeNewChatModal }) ]), vue.createElementVNode("text", null, "选择对话类型,开启全新会话体验"), vue.createElementVNode("view", { class: "ncd-options" }, [ vue.createElementVNode("view", { class: "ncd-option ncd-normal" }, [ vue.createElementVNode("view", { class: "ncd-opt-icon" }, [ vue.createVNode(_component_uni_icons, { type: "chat", color: "#000000", size: "30" }) ]), vue.createElementVNode("view", { class: "ncd-opt-title", onClick: $setup.selectNormalChat }, [ vue.createElementVNode("view", { class: "ncd-opt-title-1" }, "普通会话"), vue.createElementVNode("view", { class: "ncd-opt-title-2" }, "与AI自由对话,探索任何话题") ]), vue.createVNode(_component_uni_icons, { type: "arrow-right", class: "arrow-right-style" }) ]), vue.createElementVNode("view", { class: "ncd-option ncd-intelligence" }, [ vue.createElementVNode("view", { class: "ncd-opt-icon" }, [ vue.createVNode(_component_uni_icons, { type: "star", color: "#ffffff", size: "30" }) ]), vue.createElementVNode("view", { class: "ncd-opt-title" }, [ vue.createElementVNode("view", { class: "ncd-opt-title-1" }, "智能体会话"), vue.createElementVNode("view", { class: "ncd-opt-title-2" }, "选择专属智能体,获得精准专业服务") ]), vue.createVNode(_component_uni_icons, { type: "arrow-right", class: "arrow-right-style" }) ]) ]) ]) ])) : vue.createCommentVNode("v-if", true), $setup.isThinking ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "ncd-overlay", onClick: $setup.closeNewChatModal }, [ vue.createElementVNode("view", { class: "ncd-card ai-card", onClick: _cache[1] || (_cache[1] = vue.withModifiers(() => { }, ["stop"])) }, [ vue.createElementVNode("view", { class: "thinking-content" }, [ vue.createElementVNode("view", { class: "loading-dots" }, [ vue.createElementVNode("view", { class: "dot" }), vue.createElementVNode("view", { class: "dot" }), vue.createElementVNode("view", { class: "dot" }) ]), vue.createElementVNode("text", { class: "thinking-text" }, "AI 正在思考中...") ]) ]) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "chat-page page-container" }, [ $setup.isChatSidebar ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "mask", onClick: $setup.handleChatSidebar })) : vue.createCommentVNode("v-if", true), vue.createElementVNode( "view", { class: vue.normalizeClass(["chat-sidebar", { "sidebar-show": $setup.isChatSidebar }]) }, [ vue.createVNode($setup["ChatSidebar"], { chatList: $setup.UserConversations, showNewChatModal: $setup.showNewChatModal, "onUpdate:showNewChatModal": _cache[2] || (_cache[2] = ($event) => $setup.showNewChatModal = $event), currentSessionId: $setup.currentSessionId, "onUpdate:currentSessionId": _cache[3] || (_cache[3] = ($event) => $setup.currentSessionId = $event), chatType: $setup.ChatType, "onUpdate:chatType": _cache[4] || (_cache[4] = ($event) => $setup.ChatType = $event), onRefreshConversations: $setup.takeUserConversations }, null, 8, ["chatList", "showNewChatModal", "currentSessionId", "chatType"]) ], 2 /* CLASS */ ), vue.createElementVNode("view", { class: "chat-wrapper" }, [ vue.createElementVNode("view", { class: "chat-hearder" }, [ vue.createElementVNode("view", { class: "chat-btn-group" }, [ vue.createElementVNode("view", { class: "head-btn", onClick: $setup.handleChatSidebar }, [ vue.createElementVNode("view", { class: "iconfont icon-caidan" }) ]), vue.createElementVNode("view", { class: "head-btn", onClick: $setup.goWorkSpace }, [ vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }) ]), vue.createElementVNode("view", { class: "head-btn log-out", onClick: $setup.logOut }, [ vue.createElementVNode("view", { class: "iconfont icon-tuichu" }) ]) ]) ]), vue.createElementVNode("view", { class: "main-chat" }, [ vue.createElementVNode("scroll-view", { class: "chat-messages", direction: "vertical", "scroll-y": "", "scroll-into-view": $setup.scrollToView, onScrolltoupper: $setup.loadMoreMessages, "upper-threshold": 0, "scroll-with-animation": true, onScroll: $setup.onScroll }, [ $setup.ChatType === 0 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 0 }, vue.renderList($setup.currentMessages, (message, index) => { var _a; return vue.openBlock(), vue.createElementBlock("view", { class: vue.normalizeClass(["chat-message", { "message-user": message.role === "user" }]), key: index, id: "msg-" + index }, [ message.role === "user" ? (vue.openBlock(), vue.createElementBlock( "view", { key: 0, class: vue.normalizeClass(["chat-avatar", { "chat-avatar-user": message.role === "user" }]) }, [ message.role === "user" && ((_a = $setup.UserData) == null ? void 0 : _a.avatar) ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: $setup.UserData.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "iconfont icon-yonghuziliao" })) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true), message.content && String(message.content).trim() !== "" ? (vue.openBlock(), vue.createElementBlock( "view", { key: 1, class: vue.normalizeClass(["chat-content", { "chat-content-user": message.role === "user" }]) }, [ vue.createElementVNode("view", { innerHTML: $setup.pareseMarkdown(message.content) }, null, 8, ["innerHTML"]) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true) ], 10, ["id"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true), $setup.ChatType === 1 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 1 }, vue.renderList($setup.currentMessages, (message, index) => { var _a; return vue.openBlock(), vue.createElementBlock("view", { class: vue.normalizeClass(["chat-message", { "message-user": message.sender === $setup.UserId }]), key: index, id: "msg-" + index }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["chat-avatar", { "chat-avatar-user": message.sender === $setup.UserId }]) }, [ message.sender === $setup.UserId && ((_a = $setup.UserData) == null ? void 0 : _a.avatar) ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: $setup.UserData.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : $setup.takeTalkUserAvatar(message.sender) ? (vue.openBlock(), vue.createElementBlock("image", { key: 1, src: $setup.takeTalkUserAvatar(message.sender), class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 2, class: "iconfont icon-yonghuziliao" })) ], 2 /* CLASS */ ), vue.createElementVNode( "view", { class: vue.normalizeClass(["chat-content", { "chat-content-user": message.sender === $setup.UserId }]) }, [ message.content && String(message.content).trim() !== "" ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, innerHTML: $setup.pareseMarkdown(message.content) }, null, 8, ["innerHTML"])) : vue.createCommentVNode("v-if", true), message.contentJson ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "message-file-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(JSON.parse(message.contentJson), (file, idx) => { return vue.openBlock(), vue.createElementBlock("view", { key: idx, class: "file-item" }, [ ["jpg", "jpeg", "png", "gif", "webp", "bmp"].includes(file.extendName.toLowerCase()) ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: file.url, mode: "widthFix", class: "message-image", onClick: ($event) => $setup.previewImage(file.url) }, null, 8, ["src", "onClick"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "message-file", onClick: ($event) => $setup.openFile(file.url) }, [ vue.createElementVNode("view", { class: "file-icon" }, "📄"), vue.createElementVNode( "view", { class: "file-name" }, vue.toDisplayString(file.name), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "file-size" }, vue.toDisplayString($setup.formatFileSize(file.fileSize)), 1 /* TEXT */ ) ], 8, ["onClick"])) ]); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ ) ], 10, ["id"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true), $setup.ChatType === 2 ? (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 2 }, vue.renderList($setup.currentMessages, (message, index) => { var _a; return vue.openBlock(), vue.createElementBlock("view", { class: vue.normalizeClass(["chat-message", { "message-user": message.sender === $setup.UserId }]), key: index, id: "msg-" + index }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["chat-avatar", { "chat-avatar-user": message.sender === $setup.UserId }]) }, [ message.sender === $setup.UserId && ((_a = $setup.UserData) == null ? void 0 : _a.avatar) ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: $setup.UserData.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : $setup.groupMemberList.length > 0 && $setup.getGroupMemberAvatarById(message.sender) ? (vue.openBlock(), vue.createElementBlock("image", { key: 1, src: $setup.getGroupMemberAvatarById(message.sender), class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 2, class: "iconfont icon-yonghuziliao" })) ], 2 /* CLASS */ ), vue.createElementVNode( "view", { class: vue.normalizeClass(["chat-content", { "chat-content-user": message.sender === $setup.UserId }]) }, [ message.message && String(message.message).trim() !== "" ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, innerHTML: $setup.pareseMarkdown(message.message) }, null, 8, ["innerHTML"])) : vue.createCommentVNode("v-if", true), message.contentJson ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "message-file-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(JSON.parse(message.contentJson), (file, idx) => { return vue.openBlock(), vue.createElementBlock("view", { key: idx, class: "file-item" }, [ ["jpg", "jpeg", "png", "gif", "webp", "bmp"].includes(file.extendName.toLowerCase()) ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: file.url, mode: "widthFix", class: "message-image", onClick: ($event) => $setup.previewImage(file.url) }, null, 8, ["src", "onClick"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "message-file", onClick: ($event) => $setup.openFile(file.url) }, [ vue.createElementVNode("view", { class: "file-icon" }, "📄"), vue.createElementVNode( "view", { class: "file-name" }, vue.toDisplayString(file.name), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "file-size" }, vue.toDisplayString($setup.formatFileSize(file.fileSize)), 1 /* TEXT */ ) ], 8, ["onClick"])) ]); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ ) ], 10, ["id"]); }), 128 /* KEYED_FRAGMENT */ )) : vue.createCommentVNode("v-if", true) ], 40, ["scroll-into-view"]), vue.createElementVNode("view", { class: "chat-interactive-container" }, [ vue.createElementVNode("view", { class: "chat-interactive-group" }, [ vue.createElementVNode("view", { class: "chat-interactive-btn", onClick: $setup.uploadPhoto }, "拍照上传"), vue.createElementVNode("view", { class: "chat-interactive-btn", onClick: _cache[5] || (_cache[5] = ($event) => $setup.uploadFile()) }, "上传文件") ]), $setup.previewFileArray.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "image-list" }, [ vue.createElementVNode( "view", { class: "image-title" }, "已选择: (" + vue.toDisplayString($setup.previewFileArray.length) + ")", 1 /* TEXT */ ), vue.createElementVNode("view", { class: "image-grid" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.previewFileArray, (item, index) => { return vue.openBlock(), vue.createElementBlock("view", { class: "image-item", key: index }, [ vue.createElementVNode("view", { class: "image-info" }, [ vue.createElementVNode( "text", { class: "image-name" }, vue.toDisplayString(item.name), 1 /* TEXT */ ), vue.createElementVNode("text", { class: "delete-btn", onClick: vue.withModifiers(($event) => $setup.deleteImage(index), ["stop"]) }, "删除", 8, ["onClick"]) ]) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "chat-input-container" }, [ vue.withDirectives(vue.createElementVNode( "textarea", { class: "message-input", placeholder: "输入消息...", onConfirm: $setup.sendMessage, "confirm-type": "send", "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => $setup.textMessage = $event), "auto-height": "" }, null, 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.textMessage] ]), vue.createElementVNode("view", { class: "input-btn-group" }, [ vue.createElementVNode("view", { class: "iconfont icon-tingzhi icon-btn" }) ]) ]) ]) ]) ]) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesChatChat = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$6], ["__scopeId", "data-v-5eb7b895"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/Chat/Chat.vue"]]); const _sfc_main$6 = { __name: "WorkSpace", setup(__props, { expose: __expose }) { __expose(); const UserToken = vue.ref(""); const workspaceId = vue.ref(""); const navbarBeforeTitle = vue.ref(""); const navbarTitle = vue.ref("工作区"); const isSelectFolder = vue.ref(false); const selectFileList = vue.ref([]); const handleSelectFolder = () => { if (isSelectFolder.value) { selectFileList.value = []; } isSelectFolder.value = !isSelectFolder.value; }; const selectFolder = (id) => { const index = selectFileList.value.indexOf(id); if (index !== -1) { selectFileList.value.splice(index, 1); } else { selectFileList.value.push(id); } }; const showNewFolder = vue.ref(false); const isNFNFocused = vue.ref(false); const newFolderName = vue.ref(""); const closeNewFolderModal = () => { showNewFolder.value = false; newFolderName.value = ""; }; const newWorkspaceFolder = () => { showNewFolder.value = true; }; const currentFolderPath = vue.computed(() => { if (folderStack.value.length === 0) return "根目录"; return "/" + folderStack.value.map((f) => f.name).join("/"); }); const folderPathPreview = vue.computed(() => { const folderPath = folderStack.value.map((f) => f.name).join("/"); const name2 = newFolderName.value.trim(); if (name2) { return folderPath ? `./${folderPath}/${name2}` : `./${name2}`; } return folderPath ? `./${folderPath}/` : "./"; }); const confirmCreateFolder = async () => { const name2 = newFolderName.value.trim(); if (!name2) { uni.showToast({ title: "请输入目录名称", icon: "none" }); return; } try { const folderPath = folderStack.value.map((f) => f.name).join("/"); const dirPath = folderPath ? `./${folderPath}/${name2}` : `./${name2}`; await createWorkspaceFolder(UserToken.value, workspaceId.value, dirPath); uni.showToast({ title: "创建成功", icon: "success" }); closeNewFolderModal(); initCurrentFolderList(); } catch (error) { formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:183", "创建文件夹失败:", error); uni.showToast({ title: "创建失败,请重试", icon: "error" }); } }; const handleLongPress = (folder) => { if (isSelectFolder.value) return; uni.showActionSheet({ itemList: ["重命名", "删除", "下载", "压缩"], success: (res) => { switch (res.tapIndex) { case 0: handleRename(folder); break; case 1: handleDelete(folder); break; case 2: handleDownload(folder); break; case 3: handleDownload(folder); break; } } }); }; const handleRename = (folder) => { uni.showModal({ title: "重命名", content: "请输入新名称", editable: true, placeholderText: folder.name, success: (res) => { if (res.confirm && res.content) { updateFolderName(folder.id, res.content); } } }); }; const handleDownload = async (folder) => { if (folder.type === "directory") { uni.showToast({ title: "暂不支持下载目录", icon: "none" }); return; } try { uni.showLoading({ title: "获取下载链接..." }); const filePath = folder.path.startsWith("./") ? folder.path.slice(2) : folder.path; const result = await getWorkspaceFileURL(UserToken.value, workspaceId.value, filePath); uni.hideLoading(); const fileInfo = Array.isArray(result) ? result[0] : result; if (!fileInfo || !fileInfo.url) { uni.showToast({ title: "获取下载链接失败", icon: "error" }); return; } const downloadUrl = fileInfo.url; const fileName = folder.name; uni.showLoading({ title: "下载中..." }); uni.downloadFile({ url: downloadUrl, name: fileName, // 重要:指定文件名,保证打开正常 success: (downloadRes) => { uni.hideLoading(); if (downloadRes.statusCode === 200) { uni.openDocument({ filePath: downloadRes.tempFilePath, showMenu: true, // 右上角显示 分享/保存 按钮 success: () => { uni.showToast({ title: "打开成功", icon: "success" }); }, fail: (err) => { formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:335", "打开失败:", err); uni.showToast({ title: "无法打开此文件", icon: "error" }); } }); } else { uni.showToast({ title: "下载失败", icon: "error" }); } }, fail: (err) => { uni.hideLoading(); formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:348", "下载文件失败:", err); uni.showToast({ title: "下载失败,请重试", icon: "error" }); } }); } catch (error) { uni.hideLoading(); formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:354", "获取下载链接失败:", error); uni.showToast({ title: "获取下载链接失败,请重试", icon: "error" }); } }; const handleDelete = (folder) => { uni.showModal({ title: "提示", content: `确定要删除"${folder.name}"吗?`, success: async (res) => { if (res.confirm) { try { const filePath = `./${folder.path}`; formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:369", "删除的是:", filePath); await daleteWorkspace(UserToken.value, workspaceId.value, filePath); uni.showToast({ title: "删除成功", icon: "success" }); initCurrentFolderList(); } catch (error) { formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:374", "删除失败:", error); uni.showToast({ title: "删除失败,请重试", icon: "error" }); } } } }); }; const isMenuOpen = vue.ref(false); const handleMenu = () => { isMenuOpen.value = !isMenuOpen.value; }; const searchKeyword = vue.ref(""); const isSearchFocus = vue.ref(false); const handleSearchFocus = () => { isSearchFocus.value = !isSearchFocus.value; }; const getFileIcon = (ext) => { const iconMap = { ".png": "icon-wenjiantupian", ".jpg": "icon-wenjiantupian", ".jpeg": "icon-wenjiantupian", ".gif": "icon-wenjiantupian", ".svg": "icon-SVG", ".bmp": "icon-wenjiantupian", ".webp": "icon-wenjiantupian", ".mp4": "icon-wenjianshipin", ".avi": "icon-wenjianshipin", ".mov": "icon-wenjianshipin", ".wmv": "icon-wenjianshipin", ".flv": "icon-wenjianshipin", ".mkv": "icon-wenjianshipin", ".mp3": "icon-wenjianyinpin", ".wav": "icon-wenjianyinpin", ".flac": "icon-wenjianyinpin", ".aac": "icon-wenjianyinpin", ".pdf": "icon-PDF", ".doc": "icon-DOC", ".docx": "icon-DOC", ".xls": "icon-XLS", ".xlsx": "icon-XLS", ".ppt": "icon-PPT", ".pptx": "icon-PPT", ".txt": "icon-TXT", ".md": "icon-file-markdown-fill", ".zip": "icon-wenjianyasuo", ".rar": "icon-wenjianyasuo", ".7z": "icon-wenjianyasuo", ".tar": "icon-wenjianyasuo", ".gz": "icon-wenjianyasuo", ".js": "icon-JS", ".ts": "icon-daimawenjia", ".vue": "icon-daimawenjia", ".html": "icon-HTML", ".css": "icon-CSS", ".py": "icon-daimawenjian", ".java": "icon-daimawenjian", ".json": "icon-JSON" }; return iconMap[ext == null ? void 0 : ext.toLowerCase()] || "icon-qitawenjian"; }; const allFoldersData = vue.ref({}); const folderStack = vue.ref([]); const currentFolderList = vue.ref([]); const getCurrentFolderList = () => { var _a, _b; formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:452", "当前路径为:", JSON.stringify(folderStack.value)); const currentPath = folderStack.value.length > 0 ? folderStack.value[folderStack.value.length - 1].path : "."; if (currentPath === ".") { return ((_a = allFoldersData.value) == null ? void 0 : _a.children) || []; } const findFolderByPath = (list, targetPath) => { var _a2; for (const item of list) { if (item.path === targetPath) return item; if (item.type === "directory" && ((_a2 = item.children) == null ? void 0 : _a2.length)) { const res = findFolderByPath(item.children, targetPath); if (res) return res; } } return null; }; const currentFolder = findFolderByPath(((_b = allFoldersData.value) == null ? void 0 : _b.children) || [], currentPath); return currentFolder ? currentFolder.children : []; }; const initCurrentFolderList = async () => { workspaceId.value = getWorkspaceId(); UserToken.value = getToken(); formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:479", "getWorkspaceId:", workspaceId.value); allFoldersData.value = await getWorkspaceList(UserToken.value, workspaceId.value); currentFolderList.value = getCurrentFolderList(); }; const handleFolderClick = (folder) => { if (folder.type !== "directory") return; folderStack.value.push({ path: folder.path, name: folder.name }); navbarTitle.value = folder.name; navbarBeforeTitle.value = folderStack.value.length > 1 ? folderStack.value[folderStack.value.length - 2].name : "工作区"; currentFolderList.value = getCurrentFolderList(); searchKeyword.value = ""; isSearchFocus.value = false; }; const handleSelectAll = () => { if (selectFileList.value.length === currentFolderList.value.length) { selectFileList.value = []; } else { selectFileList.value = currentFolderList.value.map((f) => f.path); } }; const handleBackOrCheck = () => { if (isSelectFolder.value) { handleSelectAll(); return; } if (folderStack.value.length > 0) { folderStack.value.pop(); if (folderStack.value.length === 0) { navbarTitle.value = "工作区"; navbarBeforeTitle.value = null; } else { navbarTitle.value = folderStack.value[folderStack.value.length - 1].name; navbarBeforeTitle.value = folderStack.value.length > 1 ? folderStack.value[folderStack.value.length - 2].name : "工作区"; } initCurrentFolderList(); searchKeyword.value = ""; isSearchFocus.value = false; } else { uni.navigateBack({ delta: 1, fail() { formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:536", "返回失败,进入兜底跳转"); uni.reLaunch({ url: "/pages/Chat/Chat" }); } }); } }; vue.onMounted(() => { initCurrentFolderList(); }); const __returned__ = { UserToken, workspaceId, navbarBeforeTitle, navbarTitle, isSelectFolder, selectFileList, handleSelectFolder, selectFolder, showNewFolder, isNFNFocused, newFolderName, closeNewFolderModal, newWorkspaceFolder, currentFolderPath, folderPathPreview, confirmCreateFolder, handleLongPress, handleRename, handleDownload, handleDelete, isMenuOpen, handleMenu, searchKeyword, isSearchFocus, handleSearchFocus, getFileIcon, allFoldersData, folderStack, currentFolderList, getCurrentFolderList, initCurrentFolderList, handleFolderClick, handleSelectAll, handleBackOrCheck, onMounted: vue.onMounted, ref: vue.ref, computed: vue.computed, get getWorkspaceId() { return getWorkspaceId; }, get getToken() { return getToken; }, get getWorkspaceList() { return getWorkspaceList; }, get createWorkspaceFolder() { return createWorkspaceFolder; }, get daleteWorkspace() { return daleteWorkspace; }, get getWorkspaceFileURL() { return getWorkspaceFileURL; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), $setup.showNewFolder ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "popup-overlay", onClick: $setup.closeNewFolderModal }, [ vue.createElementVNode("view", { class: "popup-card", onClick: _cache[3] || (_cache[3] = vue.withModifiers(() => { }, ["stop"])) }, [ vue.createElementVNode("view", { class: "close-popup-card", onClick: $setup.closeNewFolderModal }, [ vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) ]), vue.createElementVNode("view", { class: "popup-title" }, "新建工作区目录"), vue.createElementVNode("view", { class: "new-folder-name" }, "目录名称"), vue.createElementVNode( "view", { class: vue.normalizeClass(["create-folder-name", { "has-value": $setup.isNFNFocused || $setup.newFolderName }]) }, [ vue.withDirectives(vue.createElementVNode( "input", { "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.newFolderName = $event), onFocus: _cache[1] || (_cache[1] = ($event) => $setup.isNFNFocused = true), onBlur: _cache[2] || (_cache[2] = ($event) => $setup.isNFNFocused = false), type: "text", placeholder: "输入目录名称,如:项目资料/设计图" }, null, 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.newFolderName] ]) ], 2 /* CLASS */ ), vue.createElementVNode("view", { class: "nf-path-label" }, "当前路径"), vue.createElementVNode( "view", { class: "nf-path-display" }, vue.toDisplayString($setup.currentFolderPath), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "nf-path-label" }, "路径预览"), vue.createElementVNode( "view", { class: "nf-path-preview" }, vue.toDisplayString($setup.folderPathPreview), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "option-wrapper" }, [ vue.createElementVNode("view", { class: "opt-btn opt-cancel", onClick: $setup.closeNewFolderModal }, "取消"), vue.createElementVNode("view", { class: "opt-btn opt-confirm", onClick: $setup.confirmCreateFolder }, "确认") ]) ]) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "workspace-container page-container" }, [ vue.createElementVNode("view", { class: "workspace-header" }, [ vue.createElementVNode("view", { class: "custom-navbar" }, [ vue.createElementVNode("view", { class: "navbar-left", onClick: _cache[4] || (_cache[4] = (...args) => $setup.handleBackOrCheck && $setup.handleBackOrCheck(...args)) }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui custom-navbar-icon" }), vue.createElementVNode( "view", { class: "navbar-before-title workspace-text" }, vue.toDisplayString($setup.isSelectFolder ? "全选" : $setup.navbarBeforeTitle), 1 /* TEXT */ ) ]), vue.createElementVNode( "view", { class: "navbar-title workspace-text" }, vue.toDisplayString($setup.navbarTitle), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "navbar-right" }, [ $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "navbar-right-text workspace-text", onClick: _cache[5] || (_cache[5] = ($event) => $setup.handleSelectFolder()) }, " 完成")) : (vue.openBlock(), vue.createElementBlock( "view", { key: 1, class: vue.normalizeClass(["iconfont icon-gengduo", $setup.isMenuOpen ? "menu-open" : "custom-navbar-icon"]), onClick: $setup.handleMenu }, null, 2 /* CLASS */ )) ]), $setup.isMenuOpen ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "menu-card" }, [ vue.createElementVNode("view", { class: "menu-card-item", onClick: _cache[6] || (_cache[6] = ($event) => { $setup.handleSelectFolder(); $setup.handleMenu(); }) }, "选择"), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("view", { class: "menu-card-item", onClick: _cache[7] || (_cache[7] = ($event) => { $setup.newWorkspaceFolder(); $setup.handleMenu(); }) }, "新建文件夹") ])) : vue.createCommentVNode("v-if", true) ]), vue.createElementVNode("view", { class: "search-file-warpper" }, [ vue.createElementVNode("view", { class: "search-file" }, [ vue.createElementVNode("view", { class: "iconfont icon-sousuo" }), vue.withDirectives(vue.createElementVNode( "input", { class: "search-file-input", placeholder: "搜索", onFocus: $setup.handleSearchFocus, "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => $setup.searchKeyword = $event) }, null, 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.searchKeyword] ]) ]), $setup.isSearchFocus ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "cancel-search", onClick: $setup.handleSearchFocus }, "取消")) : vue.createCommentVNode("v-if", true) ]) ]), vue.createElementVNode("view", { class: "workspace-content" }, [ $setup.currentFolderList.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "folder-null" }, [ vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), vue.createTextVNode(" 文件夹为空 ") ])) : vue.createCommentVNode("v-if", true), $setup.currentFolderList.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "folder-grid" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.currentFolderList, (folder) => { return vue.openBlock(), vue.createElementBlock("view", { class: vue.normalizeClass(["folder-item", { "select-folder": $setup.selectFileList.includes(folder.path) }]), key: folder.path, onClick: ($event) => $setup.isSelectFolder ? $setup.selectFolder(folder.path) : $setup.handleFolderClick(folder), onLongpress: ($event) => $setup.handleLongPress(folder) }, [ folder.type === "directory" ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "iconfont icon-a-wenjianjiawenjian folder-item-style" })) : (vue.openBlock(), vue.createElementBlock( "view", { key: 1, class: vue.normalizeClass(["iconfont folder-item-style", $setup.getFileIcon(folder.extension)]) }, null, 2 /* CLASS */ )), vue.createElementVNode( "view", { class: "folder-name" }, vue.toDisplayString(folder.name), 1 /* TEXT */ ), $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock( "view", { key: 2, class: vue.normalizeClass(["folder-checkbox", { "select-folder": $setup.selectFileList.includes(folder.path) }]) }, [ $setup.selectFileList.includes(folder.path) ? (vue.openBlock(), vue.createBlock(_component_uni_icons, { key: 0, type: "checkmarkempty", color: "#fff" })) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true) ], 42, ["onClick", "onLongpress"]); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ]), $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock( "view", { key: 0, class: vue.normalizeClass(["workspace-footer", { "folder-actions": $setup.selectFileList.length > 0 }]) }, [ vue.createElementVNode("view", { class: "iconfont icon-shangchuan" }), vue.createElementVNode("view", { class: "iconfont icon-fuzhi" }), vue.createElementVNode("view", { class: "iconfont icon-wenjian" }), vue.createElementVNode("view", { class: "iconfont icon-del" }), vue.createElementVNode("view", { class: "iconfont icon-gengduo" }) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesWorkSpaceWorkSpace = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$5], ["__scopeId", "data-v-c1a60359"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/WorkSpace.vue"]]); const _sfc_main$5 = { __name: "UserProfileModal", setup(__props, { expose: __expose }) { __expose(); const closeUserCard = () => { formatAppLog("log", "at pages/UserProfileModal/UserProfileModal.vue:55", "点击了返回"); uni.navigateBack({ delta: 1, fail() { uni.reLaunch({ url: "/pages/Chat/Chat" }); } }); }; const saveUpdate = () => { uni.navigateBack({ url: "/pages/Chat/Chat" }); }; const editUserAvatar = vue.ref(""); const editUsername = vue.ref(""); const editEmail = vue.ref(""); const isNameFocus = vue.ref(false); const isEmailFocus = vue.ref(false); const triggerAvatarUpload = () => { uni.chooseImage({ count: 1, sizeType: ["compressed"], sourceType: ["album", "camera"], success: (res) => { const tempFilePath = res.tempFilePaths[0]; handlrImageSelected(tempFilePath); }, fail: (err) => { formatAppLog("log", "at pages/UserProfileModal/UserProfileModal.vue:90", "选择图片失败", err); } }); }; const handlrImageSelected = (filePath) => { editUserAvatar.value = filePath; }; vue.onMounted(async () => { const token = getToken(); const UserInfo = await getUserInfo(token); editUserAvatar.value = UserInfo.avatar || ""; editUsername.value = UserInfo.username || ""; editEmail.value = UserInfo.email || ""; }); const __returned__ = { closeUserCard, saveUpdate, editUserAvatar, editUsername, editEmail, isNameFocus, isEmailFocus, triggerAvatarUpload, handlrImageSelected, onMounted: vue.onMounted, ref: vue.ref, get getUserInfo() { return getUserInfo; }, get getToken() { return getToken; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), vue.createElementVNode("view", { class: "user-profile page-container" }, [ vue.createElementVNode("view", { class: "modal-header" }, [ vue.createElementVNode("view", { class: "modal-left", onClick: $setup.closeUserCard }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui custom-navbar-icon" }) ]), vue.createElementVNode("view", { class: "modal-title" }, [ vue.createElementVNode("view", { class: "title-text" }, "编辑资料") ]), vue.createElementVNode("view", { class: "modal-right", onClick: $setup.saveUpdate }, [ vue.createElementVNode("view", { class: "save-btn" }, "保存") ]) ]), vue.createElementVNode("view", { class: "modal-body" }, [ vue.createElementVNode("view", { class: "avatar-upload-section", onClick: $setup.triggerAvatarUpload }, [ vue.createElementVNode("view", { class: "avatar-upload-container" }, [ $setup.editUserAvatar ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "avatar-preview" }, [ vue.createElementVNode("image", { src: $setup.editUserAvatar, mode: "aspectFill" }, null, 8, ["src"]) ])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "avatar-placeholder" }, [ vue.createVNode(_component_uni_icons, { type: "person-filled", size: "100rpx", color: "#ffffff" }) ])) ]) ]), vue.createElementVNode("view", { class: "form-card" }, [ vue.createElementVNode("view", { class: "form-field" }, [ vue.createElementVNode("view", { class: "form-text" }, "用户名"), vue.withDirectives(vue.createElementVNode( "input", { "adjust-position": "false", class: vue.normalizeClass(["form-field-input form-field-username", { "edit-input-focus": $setup.isNameFocus }]), "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.editUsername = $event), onFocus: _cache[1] || (_cache[1] = ($event) => $setup.isNameFocus = true), onBlur: _cache[2] || (_cache[2] = ($event) => $setup.isNameFocus = false) }, null, 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vModelText, $setup.editUsername] ]) ]), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("view", { class: "form-field" }, [ vue.createElementVNode("view", { class: "form-text" }, "邮箱"), vue.withDirectives(vue.createElementVNode( "input", { "adjust-position": "false", class: vue.normalizeClass(["form-field-input form-field-emile", { "edit-input-focus": $setup.isEmailFocus }]), "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $setup.editEmail = $event), onFocus: _cache[4] || (_cache[4] = ($event) => $setup.isEmailFocus = true), onBlur: _cache[5] || (_cache[5] = ($event) => $setup.isEmailFocus = false) }, null, 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vModelText, $setup.editEmail] ]) ]) ]), vue.createElementVNode("view", { class: "prompt-content" }, "*保存后再返回哟") ]) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesUserProfileModalUserProfileModal = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4], ["__scopeId", "data-v-d2908b51"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/UserProfileModal/UserProfileModal.vue"]]); const _sfc_main$4 = { __name: "ContactPages", setup(__props, { expose: __expose }) { __expose(); const friendSocketStore = useFriendSocketStore(); const handleFriendConnect = () => { if (friendSocketStore.isConnected) return; if (!userToken.value || !UserId.value) { formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:325", "Token或UserId未准备好"); return; } friendSocketStore.connect({ token: userToken.value, UserId: UserId.value }); }; const handleBack = () => { uni.navigateBack({ delta: 1, fail() { uni.reLaunch({ url: "/pages/Chat/Chat" }); } }); }; const changeChatType = (type, sessionId = "") => { uni.setStorageSync("chatType", type); if (sessionId) { uni.setStorageSync("currentSessionId", sessionId); } uni.reLaunch({ url: "/pages/Chat/Chat" }); }; const currentTab = vue.ref(0); const tabList = vue.reactive([ { name: "contacts", label: "通讯录", icon: "📞" }, { name: "createGroup", label: "新建群聊", icon: "👥" }, { name: "addFriend", label: "添加好友", icon: "➕" }, { name: "videoCall", label: "视频会议", icon: "📹" }, { name: "friendRequest", label: "好友申请", icon: "📨" } ]); const onSwiperChange = (e2) => { currentTab.value = e2.detail.current; }; const switchTab = (index) => { currentTab.value = index; }; const userToken = vue.ref(""); const UserId = vue.ref(""); const FriendAI = { id: "ai_robot", name: "宇恒一号", avatar: "", type: "ai", description: "AI智能助手", lastMessage: null }; const FriendInfoList = vue.ref([]); const takeFriendList = async () => { try { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:426", "开始获取好友列表"); userToken.value = getToken(); const userInfo = await getUserInfo(userToken.value); UserId.value = userInfo._id; formatAppLog("log", "at pages/ContactPages/ContactPages.vue:430", "UserId.value:", UserId.value); const friendList = await getChatFriend(UserId.value); formatAppLog("log", "at pages/ContactPages/ContactPages.vue:432", "friendList:", friendList); if (friendList && friendList.length) { FriendInfoList.value = await takeUserAvatar(friendList); } else { FriendInfoList.value = []; formatAppLog("log", "at pages/ContactPages/ContactPages.vue:437", "好友列表为空"); } } catch (error) { formatAppLog("error", "at pages/ContactPages/ContactPages.vue:440", "获取好友列表失败:", error); FriendInfoList.value = []; } }; const takeUserAvatar = async (friendList) => { if (!(friendList == null ? void 0 : friendList.length)) return []; try { const friendIds = friendList.map((item) => item.receiver); const friendAvatarList = await getUserAvatar(userToken.value, friendIds); const userMap = new Map(friendAvatarList.map((user) => [user.user_id, user]) || []); return friendList.map((friend) => { const userInfo = userMap.get(friend.receiver); return { ...friend, avatar: (userInfo == null ? void 0 : userInfo.avatar) || null }; }); } catch (err) { formatAppLog("error", "at pages/ContactPages/ContactPages.vue:461", "获取好友头像失败", err); return friendList; } }; vue.onMounted(async () => { await takeFriendList(); await takeGroupList(); handleFriendConnect(); }); const GroupList = vue.ref([]); const takeGroupList = async () => { try { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:477", "开始获取群聊列表"); userToken.value = getToken(); const userInfo = await getUserInfo(userToken.value); UserId.value = userInfo._id; formatAppLog("log", "at pages/ContactPages/ContactPages.vue:481", "UserId.value:", UserId.value); GroupList.value = await getGroup(UserId.value); } catch (error) { formatAppLog("error", "at pages/ContactPages/ContactPages.vue:484", "获取群聊列表失败:", error); GroupList.value = []; } }; const createGroupName = vue.ref(""); const createGroupData = vue.ref(); const ensureFriendSocketConnected = () => { return new Promise((resolve, reject) => { if (friendSocketStore.isConnected) { resolve(); return; } if (!userToken.value || !UserId.value) { reject(new Error("Token或UserId未准备好")); return; } formatAppLog("log", "at pages/ContactPages/ContactPages.vue:505", "friendSocket 未连接,正在建立连接..."); friendSocketStore.connect({ token: userToken.value, UserId: UserId.value }); const checkInterval = setInterval(() => { if (friendSocketStore.isConnected) { clearInterval(checkInterval); formatAppLog("log", "at pages/ContactPages/ContactPages.vue:514", "friendSocket 连接已建立"); resolve(); } }, 100); setTimeout(() => { clearInterval(checkInterval); if (!friendSocketStore.isConnected) { reject(new Error("连接超时")); } }, 1e4); }); }; const createGroup = async () => { try { if (!createGroupName.value) { uni.showToast({ title: "群名称不能为空", icon: "none" }); return; } if (selectGroupMember.value.length === 0) { uni.showToast({ title: "请选择群成员", icon: "none" }); return; } await ensureFriendSocketConnected(); const memberIds = selectGroupMember.value.map((member) => member.id); createGroupData.value = { "version": "1.1", "body": { "command": 3, "userIds": memberIds, "message": "我来邀请你们了", "sender": UserId.value, "callBackMessage": true, "groupName": createGroupName.value, "teamCreateReq": { "access_token": userToken.value } } }; const isSend = await friendSocketStore.send(createGroupData.value); if (isSend) { await sendCreateGroup(); } else { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:570", "发送新建群聊消息失败"); } } catch (err) { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:573", err); uni.showToast({ title: `新建群聊失败${err}`, icon: "none" }); } }; const sendCreateGroup = () => { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error("超时未返回群聊创建结果")); }, 18e4); const unwatch = vue.watch(() => friendSocketStore.command, async (newVal) => { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:592", "创建一个一次性监听器"); if (newVal && friendSocketStore.command === 3) { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:594", "监听到command的值是3,检查群聊是否创建成功", friendSocketStore.command); try { await takeGroupList(); const newGroup = GroupList.value.find((g) => g.id === friendSocketStore.groupId); if (newGroup) { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:601", "✅ 新建群聊成功", newGroup); selectGroupMember.value = []; currentTab.value = 0; } else { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:606", "❌ 新建群聊失败 / 群组不存在"); } } catch (error) { formatAppLog("error", "at pages/ContactPages/ContactPages.vue:610", "保存AI回复失败:", error); reject(error); } finally { friendSocketStore.command = null; friendSocketStore.groupId = null; unwatch(); clearTimeout(timeout); } } }); }); }; const selectGroupMember = vue.ref([]); const handlCreateEmember = (id) => { formatAppLog("log", "at pages/ContactPages/ContactPages.vue:631", "选择的好友id:", id); formatAppLog("log", "at pages/ContactPages/ContactPages.vue:632", "selectGroupMember.value=", JSON.stringify(selectGroupMember.value)); const index = selectGroupMember.value.findIndex((item) => item.id === id); if (index === -1) { const friendItem = FriendInfoList.value.find((item) => item.receiver === id); if (friendItem) { selectGroupMember.value.push({ id: friendItem.receiver, friendNickName: friendItem.friendNickName }); } } else { selectGroupMember.value.splice(index, 1); } }; const isSearchFriend = vue.ref(false); const searchFriendName = vue.ref(""); const searchResultList = vue.ref([]); const searchFriend = async () => { if (!searchFriendName.value.trim()) { searchResultList.value = []; return; } const keyword = searchFriendName.value.toLowerCase().trim(); searchResultList.value = await searchUsers(userToken.value, keyword); formatAppLog("log", "at pages/ContactPages/ContactPages.vue:659", "searchResultList.value:", searchResultList.value); }; const handleFriendSearchFocus = () => { isSearchFriend.value = !isSearchFriend.value; }; const currentAddFriend = vue.ref(null); const addNewFriend = (id) => { const friend = mockFriendDB.value.find((friend2) => friend2.id === id); if (friend) { currentAddFriend.value = { ...friend }; } else { formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:680", "未找到该好友"); currentAddFriend.value = null; } }; const closeAddFriendCard = () => { currentAddFriend.value = null; isAgreeBeFriend.value = false; }; const isVoice = vue.ref(false); const isCamera = vue.ref(false); const togglesVoice = () => { isVoice.value = !isVoice.value; }; const togglesCamera = () => { isCamera.value = !isCamera.value; }; const isAgreeBeFriend = vue.ref(false); const refuseBeFriend = (friend) => { }; const agreeBeFriend = (friend) => { isAgreeBeFriend.value = true; currentAddFriend.value = { ...friend }; }; const mockFriendDB = vue.ref([ { id: 1, nickname: "张三", username: "zhangsan", email: "zhangsan@example.com", avatar: "👤" }, { id: 2, nickname: "李四", username: "lisi", email: "lisi@example.com", avatar: "👥" }, { id: 3, nickname: "王小明", username: "wangxm", email: "wang@example.com", avatar: "👪" }, { id: 4, nickname: "赵磊", username: "zhaolei", email: "zhao@example.com", avatar: "🗣️" }, { id: 5, nickname: "张三2", username: "zhangsan", email: "zhangsan@example.com", avatar: "👤" }, { id: 6, nickname: "李四2", username: "lisi", email: "lisi@example.com", avatar: "👥" }, { id: 7, nickname: "王小明2", username: "wangxm", email: "wang@example.com", avatar: "👪" }, { id: 8, nickname: "赵磊2", username: "zhaolei", email: "zhao@example.com", avatar: "🗣️" } ]); const __returned__ = { friendSocketStore, handleFriendConnect, handleBack, changeChatType, currentTab, tabList, onSwiperChange, switchTab, userToken, UserId, FriendAI, FriendInfoList, takeFriendList, takeUserAvatar, GroupList, takeGroupList, createGroupName, createGroupData, ensureFriendSocketConnected, createGroup, sendCreateGroup, selectGroupMember, handlCreateEmember, isSearchFriend, searchFriendName, searchResultList, searchFriend, handleFriendSearchFocus, currentAddFriend, addNewFriend, closeAddFriendCard, isVoice, isCamera, togglesVoice, togglesCamera, isAgreeBeFriend, refuseBeFriend, agreeBeFriend, mockFriendDB, onMounted: vue.onMounted, reactive: vue.reactive, ref: vue.ref, watch: vue.watch, get getToken() { return getToken; }, get getChatFriend() { return getChatFriend; }, get getGroup() { return getGroup; }, get getUserInfo() { return getUserInfo; }, get getUserAvatar() { return getUserAvatar; }, get searchUsers() { return searchUsers; }, get useFriendSocketStore() { return useFriendSocketStore; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), $setup.currentAddFriend ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "popup-overlay" }, [ vue.createElementVNode("view", { class: "popup-card" }, [ vue.createElementVNode("view", { class: "close-popup-card", onClick: $setup.closeAddFriendCard }, [ vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) ]), vue.createElementVNode( "view", { class: "popup-title" }, vue.toDisplayString($setup.isAgreeBeFriend ? "通过好友申请" : "申请添加朋友"), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "friend-card" }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode( "view", { class: "friend-avatar" }, vue.toDisplayString($setup.currentAddFriend.avatar), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString($setup.currentAddFriend.username), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString($setup.currentAddFriend.sessionId), 1 /* TEXT */ ) ]) ]), vue.createElementVNode("view", { class: "nickname-wrapper" }, [ vue.createElementVNode("view", null, "好友备注"), vue.createElementVNode("input", { class: "input-nickname", placeholder: "请输入好友名称" }) ]), vue.createElementVNode( "view", { class: "text-btn confirm-btn" }, vue.toDisplayString($setup.isAgreeBeFriend ? "确认通过" : "发送申请"), 1 /* TEXT */ ) ]) ])) : vue.createCommentVNode("v-if", true), vue.createElementVNode("view", { class: "tabbar-page page-container" }, [ vue.createElementVNode("swiper", { class: "content-swiper", current: $setup.currentTab, duration: 300, onChange: $setup.onSwiperChange }, [ vue.createElementVNode("swiper-item", { class: "content-swiper-item" }, [ vue.createElementVNode("view", { class: "tabpage-containner" }, [ vue.createElementVNode("view", { class: "tabpage-header" }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui", onClick: $setup.handleBack }), vue.createElementVNode("view", { class: "tabpage-title" }, "通讯录") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ vue.createElementVNode("scroll-view", { class: "group-member", direction: "vertical", "scroll-y": "true" }, [ vue.createElementVNode("view", { class: "friend-list" }, [ vue.createElementVNode("view", { class: "friend-card", onClick: _cache[0] || (_cache[0] = ($event) => $setup.changeChatType(0)) }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode("view", { class: "friend-avatar", style: { "background-color": "#38bdf8" } }, [ vue.createElementVNode("view", { class: "iconfont icon-Robot", style: { "font-size": "80rpx", "color": "#fff" } }) ]) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString($setup.FriendAI.name), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "friend-label" }) ]), vue.createElementVNode("view", { class: "friend-card-right" }, [ vue.createVNode(_component_uni_icons, { type: "right" }) ]) ]), (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.FriendInfoList, (friend) => { return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", key: friend.sessionId, onClick: ($event) => $setup.changeChatType(friend.type, friend.sessionId) }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ friend.avatar ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: friend.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "friend-avatar" }, [ vue.createVNode(_component_uni_icons, { type: "person-filled", size: "100rpx", color: "#ffffff" }) ])) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString(friend.friendNickName), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString(friend.sessionId), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right" }, [ vue.createVNode(_component_uni_icons, { type: "right" }) ]) ], 8, ["onClick"]); }), 128 /* KEYED_FRAGMENT */ )), vue.createElementVNode("view", null, "群聊"), vue.createElementVNode("view", { class: "solid-line" }), (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.GroupList, (group) => { return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", key: group.id, onClick: ($event) => $setup.changeChatType(group.type, group.id) }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode("view", { class: "friend-avatar", style: { "background-color": "#ffaaff" } }, [ vue.createElementVNode("view", { class: "iconfont icon-qunliao", style: { "font-size": "80rpx", "color": "#fff" } }) ]) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString(group.name), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString(group.createTime), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right" }, [ vue.createVNode(_component_uni_icons, { type: "right" }) ]) ], 8, ["onClick"]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ]) ]) ]), vue.createElementVNode("swiper-item", { class: "content-swiper-item" }, [ vue.createElementVNode("view", { class: "tabpage-containner" }, [ vue.createElementVNode("view", { class: "tabpage-header" }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui", onClick: $setup.handleBack }), vue.createElementVNode("view", { class: "tabpage-title" }, "新建群聊") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ vue.createElementVNode("view", { class: "group-info" }, [ vue.createElementVNode("view", { class: "group-name" }, [ vue.createElementVNode("view", null, "群名称"), vue.withDirectives(vue.createElementVNode( "input", { class: "input", placeholder: "请输入群名称", "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $setup.createGroupName = $event) }, null, 512 /* NEED_PATCH */ ), [ [vue.vModelText, $setup.createGroupName] ]) ]), vue.createElementVNode("view", { class: "group-member-wrapper" }, [ vue.createElementVNode("view", { class: "member-title" }, "群成员"), vue.createElementVNode("view", { class: "group-ismember-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.selectGroupMember, (item, index) => { return vue.openBlock(), vue.createElementBlock("view", { class: "group-ismember-info", key: index }, [ vue.createElementVNode( "view", { class: "group-ismember-name" }, vue.toDisplayString(item.friendNickName), 1 /* TEXT */ ) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]), vue.createElementVNode("view", { class: "create-group-btn", onClick: $setup.createGroup }, "创建群聊") ]), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("scroll-view", { class: "group-member", direction: "vertical", "scroll-y": "true" }, [ vue.createElementVNode("view", { class: "friend-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.FriendInfoList, (friend) => { var _a; return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", key: friend.receiver }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ friend.avatar ? (vue.openBlock(), vue.createElementBlock("image", { key: 0, src: friend.avatar, class: "friend-avatar", mode: "aspectFill" }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "friend-avatar" }, [ vue.createVNode(_component_uni_icons, { type: "person-filled", size: "100rpx", color: "#ffffff" }) ])) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString(friend.friendNickName), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString(friend.email), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right", onClick: ($event) => $setup.handlCreateEmember(friend.receiver) }, [ vue.createElementVNode("view", { class: "friend-checkbox" }, [ ((_a = $setup.selectGroupMember) == null ? void 0 : _a.find((item) => item.id === friend.receiver)) ? (vue.openBlock(), vue.createBlock(_component_uni_icons, { key: 0, type: "checkmarkempty" })) : vue.createCommentVNode("v-if", true) ]) ], 8, ["onClick"]) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ]) ]) ]), vue.createElementVNode("swiper-item", { class: "content-swiper-item" }, [ vue.createElementVNode("view", { class: "tabpage-containner" }, [ vue.createElementVNode("view", { class: "tabpage-header" }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui", onClick: $setup.handleBack }), vue.createElementVNode("view", { class: "tabpage-title" }, "添加好友") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ vue.createElementVNode("view", { class: "search-warpper" }, [ vue.withDirectives(vue.createElementVNode( "input", { class: vue.normalizeClass(["search-file-input", { active: $setup.isSearchFriend }]), onFocus: $setup.handleFriendSearchFocus, onBlur: $setup.handleFriendSearchFocus, "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.searchFriendName = $event) }, null, 34 /* CLASS, NEED_HYDRATION */ ), [ [vue.vModelText, $setup.searchFriendName] ]), vue.createElementVNode("view", { class: "iconfont icon-sousuo", onClick: $setup.searchFriend }) ]), !$setup.searchFriendName ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "search-tip" }, "请输入用户名或邮箱进行搜索")) : $setup.searchResultList.length ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "search-result" }, [ vue.createElementVNode("scroll-view", { class: "group-member", direction: "vertical", "scroll-y": "true" }, [ vue.createElementVNode("view", { class: "friend-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.searchResultList, (friend) => { return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", key: friend.id }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode( "view", { class: "friend-avatar" }, vue.toDisplayString(friend.avatar), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString(friend.nickname), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString(friend.email), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right", onClick: ($event) => $setup.addNewFriend(friend.id) }, [ vue.createElementVNode("view", { class: "add-btn text-btn" }, "添加") ], 8, ["onClick"]) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ])) : (vue.openBlock(), vue.createElementBlock("view", { key: 2, class: "no-result" }, "未找到相关用户,请尝试其他关键词")) ]) ]) ]), vue.createElementVNode("swiper-item", { class: "content-swiper-item" }, [ vue.createElementVNode("view", { class: "tabpage-containner" }, [ vue.createElementVNode("view", { class: "tabpage-header" }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui", onClick: $setup.handleBack }), vue.createElementVNode("view", { class: "tabpage-title" }, "视频会议") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ vue.createElementVNode("view", { class: "join-meeting-wrapper" }, [ vue.createElementVNode("view", null, "加入会议"), vue.createElementVNode("input", { class: "input-meeting", placeholder: "请输入会议号" }), vue.createElementVNode("view", { class: "meeting-btn text-btn" }, "加入会议") ]), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("view", { class: "create-meeting-wrapper" }, [ vue.createElementVNode("view", null, "创建会议"), vue.createElementVNode("view", { class: "meeting-field" }, [ vue.createElementVNode("view", { class: "meeting-label" }, "会议主题"), vue.createElementVNode("input", { class: "input-meeting", placeholder: "例如:XXX" }) ]), vue.createElementVNode("view", { class: "meeting-field" }, [ vue.createElementVNode("view", { class: "meeting-label" }, "会议密码"), vue.createElementVNode("input", { class: "input-meeting", placeholder: "留空则无密码" }) ]), vue.createElementVNode("view", { class: "meeting-field" }, [ vue.createElementVNode("view", { class: "meeting-label" }, "邀请好友"), vue.createElementVNode("view", { class: "friend-card" }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode("view", { class: "friend-avatar" }, "avatar") ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode("view", { class: "friend-name" }, "friend.nickname"), vue.createElementVNode("view", { class: "friend-label" }, "friend.email") ]), vue.createElementVNode("view", { class: "friend-card-right", onClick: _cache[3] || (_cache[3] = ($event) => $setup.addNewFriend(_ctx.friend.id)) }, [ vue.createElementVNode("view", { class: "add-btn text-btn" }, "添加") ]) ]) ]), vue.createElementVNode("view", { class: "meeting-toggles" }, [ vue.createElementVNode("view", { class: "meeting-toggles-item" }, [ vue.createElementVNode("view", { class: "meeting-toggles-icon icon-btn" }, [ vue.createVNode(_component_uni_icons, { type: "mic-filled" }), vue.createTextVNode("开启麦克风入会 ") ]), vue.createElementVNode("view", { class: "meeting-toggles-switch", onClick: $setup.togglesVoice }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["switch-box", { active: $setup.isVoice }]) }, [ vue.createElementVNode("view", { class: "switch-track" }) ], 2 /* CLASS */ ) ]) ]), vue.createElementVNode("view", { class: "meeting-toggles-item" }, [ vue.createElementVNode("view", { class: "meeting-toggles-icon icon-btn" }, [ vue.createVNode(_component_uni_icons, { type: "eye-filled" }), vue.createTextVNode("开启摄像头入会 ") ]), vue.createElementVNode("view", { class: "meeting-toggles-switch", onClick: $setup.togglesCamera }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["switch-box", { active: $setup.isCamera }]) }, [ vue.createElementVNode("view", { class: "switch-track" }) ], 2 /* CLASS */ ) ]) ]) ]), vue.createElementVNode("view", { class: "meeting-btn text-btn" }, "加入会议") ]) ]) ]) ]), vue.createElementVNode("swiper-item", { class: "content-swiper-item" }, [ vue.createElementVNode("view", { class: "tabpage-containner" }, [ vue.createElementVNode("view", { class: "tabpage-header" }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui", onClick: $setup.handleBack }), vue.createElementVNode("view", { class: "tabpage-title" }, "好友申请") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ vue.createElementVNode("scroll-view", { class: "group-member", direction: "vertical", "scroll-y": "true" }, [ vue.createElementVNode("view", { class: "friend-list" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.mockFriendDB, (friend) => { return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", key: friend.id }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode( "view", { class: "friend-avatar" }, vue.toDisplayString(friend.avatar), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, vue.toDisplayString(friend.nickname), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, vue.toDisplayString(friend.email), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right" }, [ vue.createElementVNode("view", { class: "friend-option" }, [ vue.createElementVNode("view", { class: "refuse-btn text-btn", onClick: ($event) => $setup.refuseBeFriend(friend) }, "拒绝", 8, ["onClick"]), vue.createElementVNode("view", { class: "agree-btn text-btn", onClick: ($event) => $setup.agreeBeFriend(friend) }, "同意", 8, ["onClick"]) ]) ]) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ]) ]) ]) ], 40, ["current"]), vue.createElementVNode("view", { class: "bottom-tabbar" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.tabList, (tab, index) => { return vue.openBlock(), vue.createElementBlock("view", { key: tab.name, onClick: ($event) => $setup.switchTab(index), class: "tab-item" }, [ vue.createElementVNode( "view", { class: "tab-icon" }, vue.toDisplayString(tab.icon), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "tab-label" }, vue.toDisplayString(tab.label), 1 /* TEXT */ ) ], 8, ["onClick"]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesContactPagesContactPages = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__scopeId", "data-v-976117c3"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/ContactPages/ContactPages.vue"]]); const _sfc_main$3 = { __name: "TemplateSpace", setup(__props, { expose: __expose }) { __expose(); const formatTime = (timestamp) => { if (!timestamp) return ""; const seconds = Math.floor(timestamp); const date = new Date(seconds * 1e3); const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, "0"); const day = date.getDate().toString().padStart(2, "0"); const hours = date.getHours().toString().padStart(2, "0"); const minutes = date.getMinutes().toString().padStart(2, "0"); const seconds_part = date.getSeconds().toString().padStart(2, "0"); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds_part}`; }; const formatSize = (bytes) => { if (!bytes || bytes === 0) return "0 B"; const units = ["B", "KB", "MB", "GB", "TB"]; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return `${size.toFixed(1)} ${units[unitIndex]}`; }; const handleLikeTemplate = (index) => { let targetItem; if (checkTemplate.value === "all") { targetItem = allTemplate.value[index]; } else if (checkTemplate.value === "like") { const favoriteList = allTemplate.value.filter((item) => item.is_favorite); targetItem = favoriteList[index]; } if (targetItem) { targetItem.is_favorite = !targetItem.is_favorite; } if (checkTemplate.value === "all") { currentTemplateList.value = [...allTemplate.value]; } else { currentTemplateList.value = allTemplate.value.filter((item) => item.is_favorite); } }; const templateName = vue.ref("aaa"); const editTemplate = () => { formatAppLog("log", "at pages/WorkSpace/TemplateSpace/TemplateSpace.vue:188", "点击了编辑模板"); }; const checkTemplate = vue.ref(""); const currentTemplateList = vue.ref([]); const checkShowTemplate = (type) => { checkTemplate.value = type; if (type === "all") { navbarTitle.value = "全部模板"; currentTemplateList.value = allTemplate.value; } if (type === "like") { navbarTitle.value = "收藏模板"; currentTemplateList.value = allTemplate.value.filter((item) => item.is_favorite === true); } }; const navbarBeforeTitle = vue.ref(""); const navbarTitle = vue.ref("模板区"); const isSelectFolder = vue.ref(false); const selectFileList = vue.ref([]); const handleSelectFolder = () => { if (isSelectFolder.value) { selectFileList.value = []; } isSelectFolder.value = !isSelectFolder.value; }; const selectFolder = (id) => { const index = selectFileList.value.indexOf(id); if (index !== -1) { selectFileList.value.splice(index, 1); } else { selectFileList.value.push(id); } }; const handleLongPress = (folder) => { if (isSelectFolder.value) return; uni.showActionSheet({ itemList: ["重命名", "删除", "下载", "压缩"], success: (res) => { switch (res.tapIndex) { case 0: handleRename(folder); break; case 1: handleDelete(folder); break; case 2: handleDownload(); break; case 3: handleDownload(); break; } } }); }; const handleRename = (folder) => { uni.showModal({ title: "重命名", content: "请输入新名称", editable: true, placeholderText: folder.name, success: (res) => { if (res.confirm && res.content) { updateFolderName(folder.id, res.content); } } }); }; const handleDownload = (folder) => { uni.showToast({ title: "移动功能开发中", icon: "none" }); }; const handleDelete = (folder) => { uni.showModal({ title: "提示", content: `确定要删除文件夹"${folder.name}"吗?`, success: (res) => { if (res.confirm) { formatAppLog("log", "at pages/WorkSpace/TemplateSpace/TemplateSpace.vue:283", "确认删除文件夹"); } } }); }; const isMenuOpen = vue.ref(false); const handleMenu = () => { isMenuOpen.value = !isMenuOpen.value; }; const searchKeyword = vue.ref(""); const isSearchFocus = vue.ref(false); const handleSearchFocus = () => { isSearchFocus.value = !isSearchFocus.value; }; const allTemplate = vue.ref([ { "name": "SKILL.md", "type": "file", "path": "SKILL.md", "children": [], "file_count": 0, "directory_count": 0, "size": 4768, "modified_time": 17768273619123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhrviifdhiuhrviuehrviuawhiuvrhy" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhiuvrhy" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "该回家看了的法国红酒看来法帝国海军快来尝尝v吧给v复仇计划曝光vi计划日方提供与i哦的风格和健康" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "的法国红酒看来法帝国海军快来尝尝v吧给" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhrviifdhiuhrviuehrviuawhiuvrhy" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhrviifdhiuhrviuehrviuawhiuvrhy" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhrviifdhiuhrviuehrviuawhiuvrhy" }, { "name": "222.md", "type": "file", "path": "222.md", "children": [], "file_count": 0, "directory_count": 0, "size": 5558, "modified_time": 17768276669123552e-7, "extension": ".md", "is_favorite": false, "usage_count": 0, "sort": 0, "content": "khgvshbbthvgbihepiubjhrviifdhiuhrviuehrviuawhiuvrhy" } ]); const handleSelectAll = () => { if (selectFileList.value.length === currentTemplateList.value.length) { selectFileList.value = []; } else { selectFileList.value = currentTemplateList.value.map((f) => f.id); } }; const handleBackOrCheck = () => { if (isSelectFolder.value) { handleSelectAll(); return; } if (!isSelectFolder.value && currentTemplateList.value) { currentTemplateList.value = []; checkTemplate.value = ""; navbarTitle.value = "模板区"; } if (!isSelectFolder.value && !currentTemplateList.value) { uni.navigateBack({ delta: 1, fail() { formatAppLog("log", "at pages/WorkSpace/TemplateSpace/TemplateSpace.vue:468", "返回失败,进入兜底跳转"); uni.reLaunch({ url: "/pages/Chat/Chat" }); } }); } }; const __returned__ = { formatTime, formatSize, handleLikeTemplate, templateName, editTemplate, checkTemplate, currentTemplateList, checkShowTemplate, navbarBeforeTitle, navbarTitle, isSelectFolder, selectFileList, handleSelectFolder, selectFolder, handleLongPress, handleRename, handleDownload, handleDelete, isMenuOpen, handleMenu, searchKeyword, isSearchFocus, handleSearchFocus, allTemplate, handleSelectAll, handleBackOrCheck, onMounted: vue.onMounted, ref: vue.ref }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, [ vue.createElementVNode("view", { class: "status-bar" }), vue.createElementVNode("view", { class: "popup-overlay" }, [ vue.createElementVNode("view", { class: "popup-card" }, [ vue.createElementVNode("view", { class: "close-popup-card" }, [ vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) ]), vue.createElementVNode("view", { class: "popup-title" }, "编辑模板"), vue.createElementVNode("view", { class: "edit-template-wrapper" }, [ vue.createElementVNode("view", { class: "edit-template-name" }, [ vue.createElementVNode("view", null, "模板名称"), vue.withDirectives(vue.createElementVNode( "input", { "placeholder-style": "请输入模板名称", "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.templateName = $event) }, null, 512 /* NEED_PATCH */ ), [ [vue.vModelText, $setup.templateName] ]) ]), vue.createElementVNode("view", { class: "edit-template-name" }, [ vue.createElementVNode("view", null, "模板内容"), vue.createElementVNode("view", { class: "markdown-editor-pane" }, [ vue.createElementVNode("view", { class: "markdown-pane-header" }, " 编辑 "), vue.createElementVNode("textarea") ]), vue.createElementVNode("view", { class: "markdown-preview-pane" }, [ vue.createElementVNode("view", { class: "markdown-pane-header" }, " 预览 "), vue.createElementVNode("view") ]) ]) ]) ]) ]), vue.createElementVNode("view", { class: "workspace-container page-container" }, [ vue.createElementVNode("view", { class: "workspace-header" }, [ vue.createElementVNode("view", { class: "custom-navbar" }, [ vue.createElementVNode("view", { class: "navbar-left", onClick: _cache[1] || (_cache[1] = (...args) => $setup.handleBackOrCheck && $setup.handleBackOrCheck(...args)) }, [ vue.createElementVNode("view", { class: "iconfont icon-fanhui custom-navbar-icon" }), vue.createElementVNode( "view", { class: "navbar-before-title workspace-text" }, vue.toDisplayString($setup.isSelectFolder ? "全选" : $setup.navbarBeforeTitle), 1 /* TEXT */ ) ]), vue.createElementVNode( "view", { class: "navbar-title workspace-text" }, vue.toDisplayString($setup.navbarTitle), 1 /* TEXT */ ), $setup.checkTemplate ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "navbar-right" }, [ $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "navbar-right-text workspace-text", onClick: _cache[2] || (_cache[2] = ($event) => $setup.handleSelectFolder()) }, " 完成")) : (vue.openBlock(), vue.createElementBlock( "view", { key: 1, class: vue.normalizeClass(["iconfont icon-gengduo", $setup.isMenuOpen ? "menu-open" : "custom-navbar-icon"]), onClick: $setup.handleMenu }, null, 2 /* CLASS */ )) ])) : vue.createCommentVNode("v-if", true), $setup.isMenuOpen ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "menu-card" }, [ vue.createElementVNode("view", { class: "menu-card-item", onClick: _cache[3] || (_cache[3] = ($event) => { $setup.handleSelectFolder(); $setup.handleMenu(); }) }, "选择"), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("view", { class: "menu-card-item" }, "新建模板"), vue.createElementVNode("view", { class: "solid-line" }), vue.createElementVNode("view", { class: "menu-card-item" }, "上传模板") ])) : vue.createCommentVNode("v-if", true) ]), vue.createElementVNode("view", { class: "search-file-warpper" }, [ vue.createElementVNode("view", { class: "search-file" }, [ vue.createElementVNode("view", { class: "iconfont icon-sousuo" }), vue.withDirectives(vue.createElementVNode( "input", { class: "search-file-input", placeholder: "搜索", onFocus: $setup.handleSearchFocus, "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $setup.searchKeyword = $event) }, null, 544 /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.searchKeyword] ]) ]), $setup.isSearchFocus ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "cancel-search", onClick: $setup.handleSearchFocus }, "取消")) : vue.createCommentVNode("v-if", true) ]) ]), !$setup.checkTemplate ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "folder-grid" }, [ vue.createElementVNode("view", { class: "folder-item", onClick: _cache[5] || (_cache[5] = ($event) => $setup.checkShowTemplate("all")) }, [ vue.createElementVNode("view", { class: "iconfont icon-a-wenjianjiawenjian folder-item-style" }), vue.createElementVNode("view", { class: "folder-name" }, "全部模板") ]), vue.createElementVNode("view", { class: "folder-item", onClick: _cache[6] || (_cache[6] = ($event) => $setup.checkShowTemplate("like")) }, [ vue.createElementVNode("view", { class: "iconfont icon-a-wenjianjiawenjian folder-item-style" }), vue.createElementVNode("view", { class: "folder-name" }, "收藏模板") ]) ])) : vue.createCommentVNode("v-if", true), $setup.checkTemplate ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "workspace-content" }, [ $setup.currentTemplateList.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "folder-null" }, [ vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), vue.createTextVNode(" 暂无模板 ") ])) : vue.createCommentVNode("v-if", true), $setup.currentTemplateList.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, class: "template-grid" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.currentTemplateList, (item, index) => { return vue.openBlock(), vue.createElementBlock("view", { class: "template-card", key: index }, [ vue.createElementVNode( "view", { class: "template-name" }, vue.toDisplayString(item.name), 1 /* TEXT */ ), vue.createElementVNode("view", { class: "template-content" }, [ vue.createElementVNode( "view", { class: "template-content-text" }, vue.toDisplayString(item.content), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "template-info-wrapper" }, [ vue.createElementVNode("view", { class: "template-item" }, [ vue.createElementVNode( "view", { class: "template-time background-style" }, vue.toDisplayString($setup.formatTime(item.modified_time)), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "template-cache background-style" }, vue.toDisplayString($setup.formatSize(item.size)), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "template-option" }, [ vue.createElementVNode("view", { class: vue.normalizeClass(["iconfont", item.is_favorite ? "icon-favorite-fill" : "icon-favorite"]), onClick: ($event) => $setup.handleLikeTemplate(index) }, null, 10, ["onClick"]), vue.createElementVNode("view", { class: "iconfont icon-edit-fill", onClick: $setup.editTemplate }), vue.createElementVNode("view", { class: "iconfont icon-choose-fill" }) ]) ]) ]); }), 128 /* KEYED_FRAGMENT */ )) ])) : vue.createCommentVNode("v-if", true) ])) : vue.createCommentVNode("v-if", true), $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock( "view", { key: 2, class: vue.normalizeClass(["workspace-footer", { "folder-actions": $setup.selectFileList.length > 0 }]) }, [ vue.createElementVNode("view", { class: "iconfont icon-shangchuan" }), vue.createElementVNode("view", { class: "iconfont icon-fuzhi" }), vue.createElementVNode("view", { class: "iconfont icon-wenjian" }), vue.createElementVNode("view", { class: "iconfont icon-del" }), vue.createElementVNode("view", { class: "iconfont icon-gengduo" }) ], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true) ]) ], 64 /* STABLE_FRAGMENT */ ); } const PagesWorkSpaceTemplateSpaceTemplateSpace = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__scopeId", "data-v-769edd25"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/TemplateSpace/TemplateSpace.vue"]]); const _sfc_main$2 = { __name: "text", setup(__props, { expose: __expose }) { __expose(); const formHtml = vue.ref(""); const sanitizeContent = (str) => { return str.replace(/<\/?script>/gi, (match) => { let result = ""; for (let i = 0; i < match.length; i++) { result += "\\u" + match.charCodeAt(i).toString(16).padStart(4, "0"); } return result; }); }; vue.onMounted(() => { formHtml.value = ` 明白了!您希望在我的回复中直接嵌入可编辑的表单卡片。让我试试: ---

    ✏️ 直接在下方编辑任务

    --- **✅ 您现在可以直接在上方的卡片中填写任务信息,点击"添加任务"即可!** 填写完成后告诉我"已填好"或"添加",我会帮您确认是否成功! `; }); const initForm = () => { setTimeout(() => { const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0]; const startInput = document.getElementById("inlineStart"); const endInput = document.getElementById("inlineEnd"); if (startInput) startInput.value = today; if (endInput) endInput.value = today; const clearBtn = document.getElementById("clearBtn"); const submitBtn = document.getElementById("submitBtn"); if (clearBtn) { clearBtn.onclick = () => { const titleInput = document.getElementById("inlineTitle"); const descInput = document.getElementById("inlineDesc"); if (titleInput) titleInput.value = ""; if (descInput) descInput.value = ""; }; } if (submitBtn) { submitBtn.onclick = () => { const titleInput = document.getElementById("inlineTitle"); const title = titleInput == null ? void 0 : titleInput.value.trim(); if (!title) { alert("请输入任务名称"); return; } alert(`任务已添加:${title}`); if (titleInput) titleInput.value = ""; if (document.getElementById("inlineDesc")) document.getElementById("inlineDesc").value = ""; }; } }, 100); }; const __returned__ = { formHtml, sanitizeContent, initForm, ref: vue.ref, onMounted: vue.onMounted }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("view", null, [ vue.createElementVNode("view", { innerHTML: $setup.sanitizeContent($setup.formHtml) }, null, 8, ["innerHTML"]) ]); } const PagesTextText = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text.vue"]]); const _sfc_main$1 = { __name: "text2", setup(__props, { expose: __expose }) { __expose(); const socketStore = useSocketStore(); const config = vue.ref({ token: getToken(), conversationId: getCurrentSessionId() }); const sendMessage = vue.ref(""); const quickMessages = vue.ref([ { label: "Ping", data: { ws_event: "ping" } }, { label: "认证", data: { ws_event: "auth", data: { token: "", conversation_id: "" } } }, { label: "测试消息", data: { ws_event: "message", data: { task_call_id: getTaskCallId(), token: getToken(), conversation_id: getCurrentSessionId() } } } ]); const connectionStatusClass = vue.computed(() => { const status = socketStore.connectionStatus; return { "status-connected": status === "connected", "status-connecting": status === "connecting", "status-error": status === "error", "status-disconnected": status === "disconnected" }; }); const handleConnect = () => { if (!config.value.token) { uni.showToast({ title: "请输入Token", icon: "none" }); return; } socketStore.connect({ token: config.value.token, conversationId: getCurrentSessionId() }); }; const handleDisconnect = () => { socketStore.disconnect(); }; const handleSendPing = async () => { try { await socketStore.sendPing(); } catch (e2) { uni.showToast({ title: "发送失败", icon: "none" }); } }; const handleSend = async () => { if (!sendMessage.value.trim()) return; try { const messageData = { ws_event: "message", data: { task_call_id: getTaskCallId(), result: { tools: [] } } }; await socketStore.send(messageData); sendMessage.value = ""; } catch (e2) { uni.showToast({ title: "发送失败", icon: "none" }); } }; const sendQuickMessage = async (template) => { const messageData = { ws_event: "message", data: { task_call_id: getTaskCallId(), token: getToken(), conversation_id: getCurrentSessionId() } }; try { await socketStore.send(messageData); } catch (e2) { uni.showToast({ title: "发送失败", icon: "none" }); } }; const formatJson = () => { if (!sendMessage.value.trim()) return; try { const obj = JSON.parse(sendMessage.value); sendMessage.value = JSON.stringify(obj, null, 2); } catch { uni.showToast({ title: "不是有效的JSON", icon: "none" }); } }; const loadMoreLogs = () => { }; vue.watch(() => socketStore.isDisconnected, (newVal) => { if (newVal && socketStore.messageString) { formatAppLog("log", "at pages/text/text2.vue:253", socketStore.messageString); } }); vue.onMounted(() => { socketStore.addLog("info", "=== Socket测试页面 ==="); socketStore.addLog("info", "页面已加载"); if (socketStore.isConnected) { socketStore.addLog("info", "当前已处于连接状态"); } }); vue.onUnmounted(() => { socketStore.addLog("info", "页面卸载"); }); const __returned__ = { socketStore, config, sendMessage, quickMessages, connectionStatusClass, handleConnect, handleDisconnect, handleSendPing, handleSend, sendQuickMessage, formatJson, loadMoreLogs, ref: vue.ref, computed: vue.computed, onMounted: vue.onMounted, onUnmounted: vue.onUnmounted, watch: vue.watch, get useSocketStore() { return useSocketStore; }, get getToken() { return getToken; }, get getTaskCallId() { return getTaskCallId; }, get getCurrentSessionId() { return getCurrentSessionId; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [ vue.createElementVNode("view", { class: "status-card" }, [ vue.createElementVNode("text", { class: "status-label" }, "连接状态"), vue.createElementVNode( "view", { class: vue.normalizeClass(["status-value", $setup.connectionStatusClass]) }, [ vue.createElementVNode( "text", null, vue.toDisplayString($setup.socketStore.getStatusText()), 1 /* TEXT */ ) ], 2 /* CLASS */ ), $setup.socketStore.reconnectAttempts > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 0, class: "status-info" }, [ vue.createElementVNode( "text", { class: "reconnect-info" }, "重连次数: " + vue.toDisplayString($setup.socketStore.reconnectAttempts), 1 /* TEXT */ ) ])) : vue.createCommentVNode("v-if", true) ]), vue.createElementVNode("view", { class: "config-card" }, [ vue.createElementVNode("text", { class: "section-title" }, "连接配置"), vue.createElementVNode("view", { class: "input-group" }, [ vue.createElementVNode("text", { class: "input-label" }, "Token"), vue.withDirectives(vue.createElementVNode( "input", { class: "input-field", "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.config.token = $event), placeholder: "请输入Token" }, null, 512 /* NEED_PATCH */ ), [ [vue.vModelText, $setup.config.token] ]) ]), vue.createElementVNode("view", { class: "input-group" }, [ vue.createElementVNode("text", { class: "input-label" }, "Conversation ID"), vue.withDirectives(vue.createElementVNode( "input", { class: "input-field", "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $setup.config.conversationId = $event), placeholder: "请输入会话ID(可选)" }, null, 512 /* NEED_PATCH */ ), [ [vue.vModelText, $setup.config.conversationId] ]) ]) ]), vue.createElementVNode("view", { class: "control-card" }, [ vue.createElementVNode("button", { class: "btn btn-primary", disabled: $setup.socketStore.isConnected || $setup.socketStore.isConnecting, onClick: $setup.handleConnect }, vue.toDisplayString($setup.socketStore.isConnecting ? "连接中..." : "连接"), 9, ["disabled"]), vue.createElementVNode("button", { class: "btn btn-danger", disabled: !$setup.socketStore.isConnected, onClick: $setup.handleDisconnect }, " 断开 ", 8, ["disabled"]), vue.createElementVNode("button", { class: "btn btn-secondary", onClick: $setup.handleSendPing, disabled: !$setup.socketStore.isConnected }, " Ping ", 8, ["disabled"]) ]), vue.createElementVNode("view", { class: "send-card" }, [ vue.createElementVNode("text", { class: "section-title" }, "发送消息"), vue.createElementVNode("view", { class: "send-input-wrapper" }, [ vue.withDirectives(vue.createElementVNode("textarea", { class: "send-input", "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.sendMessage = $event), placeholder: "输入要发送的消息(JSON格式)", disabled: !$setup.socketStore.isConnected }, null, 8, ["disabled"]), [ [vue.vModelText, $setup.sendMessage] ]), vue.createElementVNode("view", { class: "send-buttons" }, [ vue.createElementVNode("button", { class: "btn btn-primary btn-small", disabled: !$setup.socketStore.isConnected || !$setup.sendMessage.trim(), onClick: $setup.handleSend }, " 发送 ", 8, ["disabled"]), vue.createElementVNode("button", { class: "btn btn-outline btn-small", disabled: !$setup.sendMessage.trim(), onClick: $setup.formatJson }, " 格式化 ", 8, ["disabled"]) ]) ]), vue.createElementVNode("view", { class: "quick-messages" }, [ vue.createElementVNode("text", { class: "quick-label" }, "快捷消息:"), vue.createElementVNode("view", { class: "quick-btns" }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.quickMessages, (item) => { return vue.openBlock(), vue.createElementBlock("button", { key: item.label, class: "quick-btn", disabled: !$setup.socketStore.isConnected, onClick: ($event) => $setup.sendQuickMessage(item.data) }, vue.toDisplayString(item.label), 9, ["disabled", "onClick"]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]) ]), vue.createElementVNode("view", { class: "log-card" }, [ vue.createElementVNode("view", { class: "log-header" }, [ vue.createElementVNode("view", { class: "log-title-wrapper" }, [ vue.createElementVNode("text", { class: "section-title" }, "日志"), vue.createElementVNode( "text", { class: "log-count" }, "(" + vue.toDisplayString($setup.socketStore.logs.length) + ")", 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "log-actions" }, [ vue.createElementVNode("button", { class: "btn btn-small btn-secondary", onClick: _cache[3] || (_cache[3] = (...args) => $setup.socketStore.clearLogs && $setup.socketStore.clearLogs(...args)) }, "清空") ]) ]), vue.createElementVNode( "scroll-view", { class: "log-list", "scroll-y": "", onScrolltoupper: $setup.loadMoreLogs }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList($setup.socketStore.logs, (log, index) => { return vue.openBlock(), vue.createElementBlock( "view", { key: index, class: vue.normalizeClass(["log-item", "log-" + log.type]) }, [ vue.createElementVNode( "text", { class: "log-time" }, vue.toDisplayString(log.time), 1 /* TEXT */ ), vue.createElementVNode( "text", { class: "log-content" }, vue.toDisplayString(log.content), 1 /* TEXT */ ) ], 2 /* CLASS */ ); }), 128 /* KEYED_FRAGMENT */ )) ], 32 /* NEED_HYDRATION */ ) ]) ]); } const PagesTextText2 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-cd5869b7"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text2.vue"]]); __definePage("pages/Login/Login", PagesLoginLogin); __definePage("pages/Chat/Chat", PagesChatChat); __definePage("pages/WorkSpace/WorkSpace", PagesWorkSpaceWorkSpace); __definePage("pages/UserProfileModal/UserProfileModal", PagesUserProfileModalUserProfileModal); __definePage("pages/ContactPages/ContactPages", PagesContactPagesContactPages); __definePage("pages/WorkSpace/TemplateSpace/TemplateSpace", PagesWorkSpaceTemplateSpaceTemplateSpace); __definePage("pages/text/text", PagesTextText); __definePage("pages/text/text2", PagesTextText2); const _sfc_main = { onLaunch: function() { formatAppLog("log", "at App.vue:4", "App Launch"); }, onShow: function() { formatAppLog("log", "at App.vue:7", "App Show"); }, onHide: function() { formatAppLog("log", "at App.vue:10", "App Hide"); } }; const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "D:/Projects/uniapp/app-test/test1/App.vue"]]); function createApp() { const app = vue.createVueApp(App); const pinia = createPinia(); app.use(pinia); return { app, pinia // 暴露pinia,避免后续调用时丢失上下文 }; } const { app: __app__, Vuex: __Vuex__, Pinia: __Pinia__ } = createApp(); uni.Vuex = __Vuex__; uni.Pinia = __Pinia__; __app__.provide("__globalStyles", __uniConfig.styles); __app__._component.mpType = "app"; __app__._component.render = () => { }; __app__.mount("#app"); })(Vue);