8332 lines
302 KiB
JavaScript
8332 lines
302 KiB
JavaScript
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) {
|
||
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 _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 = { "": ["<em>", "</em>"], _: ["<strong>", "</strong>"], "*": ["<strong>", "</strong>"], "~": ["<s>", "</s>"], "\n": ["<br />"], " ": ["<br />"], "-": ["<hr />"] };
|
||
function n(e2) {
|
||
return e2.replace(RegExp("^" + (e2.match(/^(\t| )+/) || "")[0], "gm"), "");
|
||
}
|
||
function r(e2) {
|
||
return (e2 + "").replace(/"/g, """).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 = '<pre class="code ' + (g[4] ? "poetry" : g[2].toLowerCase()) + '"><code' + (g[2] ? ' class="language-' + g[2].toLowerCase() + '"' : "") + ">" + n(r(p).replace(/^\n+|\n+$/g, "")) + "</code></pre>" : (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, "<li>$1</li>")), o = "<" + p + ">" + s + "</" + p + ">") : g[8] ? o = '<img src="' + r(g[8]) + '" alt="' + r(g[7]) + '">' : g[10] ? (h = h.replace("<a>", '<a href="' + r(g[11] || i[l.toLowerCase()]) + '">'), o = $() + "</a>") : g[9] ? o = "<a>" : g[12] || g[14] ? o = "<" + (p = "h" + (g[14] ? g[14].length : g[13] > "=" ? 1 : 2)) + ">" + t(g[12] || g[15], i) + "</" + p + ">" : g[16] ? o = "<code>" + r(g[16]) + "</code>" : (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<Id, S, G, A> 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:194", "[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:284", "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:303", "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 = '<table border="1" style="border-collapse:collapse;width:100%;margin:8px 0">';
|
||
rows.forEach((row, index) => {
|
||
const tag = index === 0 ? "th" : "td";
|
||
const cells = row.split("|").filter((c) => c.trim() !== "");
|
||
html += "<tr>";
|
||
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()}</${tag}>`;
|
||
});
|
||
html += "</tr>";
|
||
});
|
||
html += "</table>";
|
||
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 = /<script\b[^>]*>([\s\S]*?)<\/script>/i.test(str);
|
||
const hasFormTags = /<(form|input|select|textarea|button)\b[^>]*>/i.test(str);
|
||
let cleanedStr = str.replace(/<script\b[^>]*>([\s\S]*?)<\/script>/gi, "");
|
||
cleanedStr = cleanedStr.replace(/<\/?minimax:tool_call>/g, (m) => m.replace(/</g, "<").replace(/>/g, ">")).replace(/<\|[\w]+?\|>/g, (m) => m.replace(/</g, "<").replace(/>/g, ">"));
|
||
if (hasScript || hasFormTags) {
|
||
const warningHtml = '<h2 style="color: red; font-weight: bold;">表单仅预览,不可操作!!!</h2>';
|
||
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 = () => {
|
||
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:491", "点击了拍照上传");
|
||
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:509", "选择图片失败", 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:532", "点击了上传文件");
|
||
limeChooseFile_utsProxy.chooseFile({
|
||
count: 5,
|
||
type: "all",
|
||
success: (res) => {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:537", "成功了");
|
||
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:548", "选择失败:", 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:615", "文件上传失败:", 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);
|
||
};
|
||
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;
|
||
await waitForAIResponse();
|
||
} catch (error) {
|
||
isThinking.value = false;
|
||
uni.showToast({
|
||
title: `用户发送消息失败${error}`,
|
||
icon: "error"
|
||
});
|
||
}
|
||
};
|
||
const waitForAIResponse = () => {
|
||
return new Promise((resolve, reject) => {
|
||
const timeout = setTimeout(() => {
|
||
unwatch();
|
||
reject(new Error("等待AI回复超时"));
|
||
}, 18e4);
|
||
const finish = async () => {
|
||
try {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:774", "ai返回的消息:", socketStore.messageString);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:775", "AI回复结束,刷新消息列表");
|
||
await takeConversationMessages();
|
||
resolve();
|
||
} catch (error) {
|
||
formatAppLog("error", "at pages/Chat/Chat.vue:779", "保存AI回复失败:", error);
|
||
reject(error);
|
||
} finally {
|
||
isThinking.value = false;
|
||
textMessage.value = "";
|
||
uploadedFiles.value = [];
|
||
unwatch();
|
||
clearTimeout(timeout);
|
||
}
|
||
};
|
||
const unwatch = vue.watch(() => socketStore.isThinking, (newVal, oldVal) => {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:792", "isThinking 变化:", oldVal, "→", newVal);
|
||
if (oldVal && !newVal && socketStore.messageString) {
|
||
finish();
|
||
}
|
||
});
|
||
});
|
||
};
|
||
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:819", "用户信息已加载:", UserId.value, UserAvatar.value);
|
||
} catch (error) {
|
||
formatAppLog("error", "at pages/Chat/Chat.vue:821", "获取用户信息失败:", error);
|
||
}
|
||
};
|
||
const takeUserConversations = async () => {
|
||
try {
|
||
userToken.value = getToken();
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:829", "token:", userToken.value);
|
||
UserConversations.value = await getUserConversations(userToken.value) || [];
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:831", "UserConversations:", UserConversations.value);
|
||
if (UserConversations.value.length > 0) {
|
||
currentSessionId.value = UserConversations.value[0]._id;
|
||
} else {
|
||
currentSessionId.value = "";
|
||
}
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:839", "保存会话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:854", "开始获取好友列表");
|
||
const friendList = await getChatFriend(UserId.value);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:857", "friendList:", friendList);
|
||
if (friendList && friendList.length) {
|
||
FriendInfoList.value = await takeUserAvatar(friendList);
|
||
} else {
|
||
FriendInfoList.value = [];
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:862", "好友列表为空");
|
||
}
|
||
} catch (error) {
|
||
formatAppLog("error", "at pages/Chat/Chat.vue:865", "获取好友列表失败:", 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:895", "获取好友头像失败", err);
|
||
return friendList;
|
||
}
|
||
};
|
||
const GroupList = vue.ref([]);
|
||
const takeGroupList = async () => {
|
||
try {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:905", "开始获取群聊列表");
|
||
GroupList.value = await getGroup(UserId.value);
|
||
} catch (error) {
|
||
formatAppLog("error", "at pages/Chat/Chat.vue:910", "获取群聊列表失败:", 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:924", "请求头像的ID列表:", memberIds);
|
||
const memberAvatarList = await getUserAvatar(userToken.value, memberIds);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:926", "头像接口返回数据:", memberAvatarList);
|
||
const userMap = new Map(memberAvatarList.map((user) => [user.user_id, user]) || []);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:929", "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:934", `查找 ${memberId} 的头像:`, userInfo);
|
||
return {
|
||
...member,
|
||
avatar: (userInfo == null ? void 0 : userInfo.avatar) || null
|
||
};
|
||
});
|
||
} catch (err) {
|
||
formatAppLog("error", "at pages/Chat/Chat.vue:941", "获取群成员头像失败", 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:986", "好友消息:", 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:999", "群聊消息:", allmessages.value);
|
||
const memberList = await getGroupMemberList(currentSessionId.value);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:1002", "获取到的群成员列表:", memberList);
|
||
if (memberList && memberList.length) {
|
||
groupMemberList.value = await takeGroupMemberAvatar(memberList);
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:1005", "群成员列表(带头像):", groupMemberList.value);
|
||
} else {
|
||
groupMemberList.value = [];
|
||
}
|
||
scrollToBottom();
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: `获取群聊会话失败${error}`,
|
||
icon: "none"
|
||
});
|
||
}
|
||
};
|
||
const loadMoreMessages = async () => {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:1020", "加载更多信息");
|
||
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:1048", "收到了好友消息");
|
||
if (newId) {
|
||
formatAppLog("log", "at pages/Chat/Chat.vue:1050", "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:1066", "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, sendAIMessage, waitForAIResponse, 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 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 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/WorkSpace.vue:149", "确认删除文件夹");
|
||
}
|
||
}
|
||
});
|
||
};
|
||
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 allFoldersData = vue.ref({
|
||
// 根目录下的文件夹
|
||
"root": [
|
||
{
|
||
id: 1,
|
||
name: "文档资料",
|
||
parentId: "root",
|
||
children: [
|
||
{
|
||
id: 11,
|
||
name: "工作文档",
|
||
parentId: 1,
|
||
children: []
|
||
},
|
||
{
|
||
id: 12,
|
||
name: "学习笔记",
|
||
parentId: 1,
|
||
children: []
|
||
},
|
||
{
|
||
id: 13,
|
||
name: "合同模板",
|
||
parentId: 1,
|
||
children: []
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 2,
|
||
name: "图片素材",
|
||
parentId: "root",
|
||
children: [
|
||
{
|
||
id: 21,
|
||
name: "风景图片",
|
||
parentId: 2,
|
||
children: []
|
||
},
|
||
{
|
||
id: 22,
|
||
name: "人物照片",
|
||
parentId: 2,
|
||
children: []
|
||
},
|
||
{
|
||
id: 23,
|
||
name: "UI图标",
|
||
parentId: 2,
|
||
children: []
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 3,
|
||
name: "视频文件",
|
||
parentId: "root",
|
||
children: [
|
||
{
|
||
id: 31,
|
||
name: "教程视频",
|
||
parentId: 3,
|
||
children: []
|
||
},
|
||
{
|
||
id: 32,
|
||
name: "会议录像",
|
||
parentId: 3,
|
||
children: []
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 4,
|
||
name: "项目代码",
|
||
parentId: "root",
|
||
children: [
|
||
{
|
||
id: 41,
|
||
name: "前端项目",
|
||
parentId: 4,
|
||
children: []
|
||
},
|
||
{
|
||
id: 42,
|
||
name: "后端服务",
|
||
parentId: 4,
|
||
children: []
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 5,
|
||
name: "安装包",
|
||
parentId: "root",
|
||
children: []
|
||
},
|
||
{
|
||
id: 6,
|
||
name: "备份文件",
|
||
parentId: "root",
|
||
children: []
|
||
},
|
||
{
|
||
id: 7,
|
||
name: "临时文件",
|
||
parentId: "root",
|
||
children: []
|
||
},
|
||
{
|
||
id: 8,
|
||
name: "个人收藏",
|
||
parentId: "root",
|
||
children: []
|
||
}
|
||
]
|
||
});
|
||
const folderStack = vue.ref([]);
|
||
const currentFolderList = vue.ref([]);
|
||
const getCurrentFolderList = () => {
|
||
const currentPath = folderStack.value.length > 0 ? folderStack.value[folderStack.value.length - 1].id : "root";
|
||
if (currentPath === "root") {
|
||
return allFoldersData.value["root"] || [];
|
||
}
|
||
const findFolderById = (folders, id) => {
|
||
for (const folder of folders) {
|
||
if (folder.id === id)
|
||
return folder;
|
||
if (folder.children && folder.children.length > 0) {
|
||
const found = findFolderById(folder.children, id);
|
||
if (found)
|
||
return found;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
const currentFolder = findFolderById(allFoldersData.value["root"], currentPath);
|
||
return currentFolder ? currentFolder.children : [];
|
||
};
|
||
const initCurrentFolderList = () => {
|
||
workspaceId.value = getWorkspaceId();
|
||
formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:312", "getWorkspaceId:", workspaceId.value);
|
||
currentFolderList.value = getCurrentFolderList();
|
||
};
|
||
const handleFolderClick = (folder) => {
|
||
folderStack.value.push({
|
||
id: folder.id,
|
||
name: folder.name
|
||
});
|
||
navbarTitle.value = folder.name;
|
||
navbarBeforeTitle.value = folderStack.value.length > 1 ? folderStack.value[folderStack.value.length - 2].name : "工作区";
|
||
initCurrentFolderList();
|
||
searchKeyword.value = "";
|
||
isSearchFocus.value = false;
|
||
};
|
||
const handleSelectAll = () => {
|
||
if (selectFileList.value.length === currentFolderList.value.length) {
|
||
selectFileList.value = [];
|
||
} else {
|
||
selectFileList.value = currentFolderList.value.map((f) => f.id);
|
||
}
|
||
};
|
||
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:367", "返回失败,进入兜底跳转");
|
||
uni.reLaunch({
|
||
url: "/pages/Chat/Chat"
|
||
});
|
||
}
|
||
});
|
||
}
|
||
};
|
||
vue.onMounted(() => {
|
||
initCurrentFolderList();
|
||
});
|
||
const __returned__ = { workspaceId, navbarBeforeTitle, navbarTitle, isSelectFolder, selectFileList, handleSelectFolder, selectFolder, handleLongPress, handleRename, handleDownload, handleDelete, isMenuOpen, handleMenu, searchKeyword, isSearchFocus, handleSearchFocus, allFoldersData, folderStack, currentFolderList, getCurrentFolderList, initCurrentFolderList, handleFolderClick, handleSelectAll, handleBackOrCheck, onMounted: vue.onMounted, ref: vue.ref, get getWorkspaceId() {
|
||
return getWorkspaceId;
|
||
} };
|
||
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" }),
|
||
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[0] || (_cache[0] = (...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[1] || (_cache[1] = ($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[2] || (_cache[2] = ($event) => {
|
||
$setup.handleSelectFolder();
|
||
$setup.handleMenu();
|
||
})
|
||
}, "选择"),
|
||
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[3] || (_cache[3] = ($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.id) }]),
|
||
key: folder.id,
|
||
onClick: ($event) => $setup.isSelectFolder ? $setup.selectFolder(folder.id) : $setup.handleFolderClick(folder),
|
||
onLongpress: ($event) => $setup.handleLongPress(folder)
|
||
}, [
|
||
vue.createElementVNode("view", { class: "iconfont icon-a-wenjianjiawenjian folder-item-style" }),
|
||
vue.createElementVNode(
|
||
"view",
|
||
{ class: "folder-name" },
|
||
vue.toDisplayString(folder.name),
|
||
1
|
||
/* TEXT */
|
||
),
|
||
$setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock(
|
||
"view",
|
||
{
|
||
key: 0,
|
||
class: vue.normalizeClass(["folder-checkbox", { "select-folder": $setup.selectFileList.includes(folder.id) }])
|
||
},
|
||
[
|
||
$setup.selectFileList.includes(folder.id) ? (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 = `
|
||
明白了!您希望在我的回复中直接嵌入可编辑的表单卡片。让我试试:
|
||
|
||
---
|
||
|
||
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 20px; padding: 28px; color: white; font-family: 'Microsoft YaHei', sans-serif; box-shadow: 0 10px 40px rgba(0,0,0,0.25); margin: 20px 0;">
|
||
<h2 style="margin: 0 0 20px 0; font-size: 20px; display: flex; align-items: center; gap: 12px;">
|
||
<span style="font-size: 26px;">✏️</span> 直接在下方编辑任务
|
||
</h2>
|
||
|
||
<form id="inlineTaskForm" style="background: rgba(255,255,255,0.1); border-radius: 16px; padding: 24px;">
|
||
<div style="margin-bottom: 18px;">
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">任务名称</label>
|
||
<input type="text" id="inlineTitle" placeholder="输入任务名称..." style="width: 100%; padding: 14px 16px; background: #1e1e2e; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; color: #fff; font-size: 15px;">
|
||
</div>
|
||
|
||
<div style="margin-bottom: 18px;">
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">任务描述</label>
|
||
<textarea id="inlineDesc" placeholder="输入详细描述..." style="width: 100%; padding: 14px 16px; background: #1e1e2e; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; color: #fff; font-size: 14px; resize: vertical; min-height: 60px;"></textarea>
|
||
</div>
|
||
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 18px;">
|
||
<div>
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">开始日期</label>
|
||
<input type="date" id="inlineStart" style="width: 100%; padding: 14px 16px; background: #1e1e2e; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; color: #fff; font-size: 15px;">
|
||
</div>
|
||
<div>
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">截止日期</label>
|
||
<input type="date" id="inlineEnd" style="width: 100%; padding: 14px 16px; background: #1e1e2e; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; color: #fff; font-size: 15px;">
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-bottom: 18px;">
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">时间</label>
|
||
<input type="time" id="inlineTime" value="09:00" style="width: 100%; padding: 14px 16px; background: #1e1e2e; border: 2px solid rgba(255,255,255,0.2); border-radius: 10px; color: #fff; font-size: 15px;">
|
||
</div>
|
||
|
||
<div style="margin-bottom: 18px;">
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 10px; text-transform: uppercase; letter-spacing: 1px;">优先级</label>
|
||
<div style="display: flex; gap: 10px;">
|
||
<label style="flex: 1; text-align: center; padding: 12px; background: rgba(254, 215, 215, 0.2); border: 2px solid transparent; border-radius: 10px; cursor: pointer; transition: all 0.3s;" onclick="selectPriority(this, 'high')">
|
||
🔴 高
|
||
<input type="radio" name="priority" value="high" checked style="display: none;">
|
||
</label>
|
||
<label style="flex: 1; text-align: center; padding: 12px; background: rgba(254, 235, 200, 0.2); border: 2px solid transparent; border-radius: 10px; cursor: pointer; transition: all 0.3s;" onclick="selectPriority(this, 'medium')">
|
||
🟡 中
|
||
<input type="radio" name="priority" value="medium" style="display: none;">
|
||
</label>
|
||
<label style="flex: 1; text-align: center; padding: 12px; background: rgba(198, 246, 213, 0.2); border: 2px solid transparent; border-radius: 10px; cursor: pointer; transition: all 0.3s;" onclick="selectPriority(this, 'low')">
|
||
🟢 低
|
||
<input type="radio" name="priority" value="low" style="display: none;">
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-bottom: 20px;">
|
||
<label style="display: block; font-size: 12px; opacity: 0.8; margin-bottom: 10px; text-transform: uppercase; letter-spacing: 1px;">分类</label>
|
||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
||
<label style="padding: 10px 16px; background: rgba(233, 216, 253, 0.2); border: 2px solid #667eea; border-radius: 20px; cursor: pointer; font-size: 13px;" onclick="selectCategory(this, 'work')">
|
||
💼 工作
|
||
<input type="radio" name="category" value="work" checked style="display: none;">
|
||
</label>
|
||
<label style="padding: 10px 16px; background: rgba(190, 227, 248, 0.2); border: 2px solid transparent; border-radius: 20px; cursor: pointer; font-size: 13px;" onclick="selectCategory(this, 'life')">
|
||
🏠 生活
|
||
<input type="radio" name="category" value="life" style="display: none;">
|
||
</label>
|
||
<label style="padding: 10px 16px; background: rgba(254, 215, 226, 0.2); border: 2px solid transparent; border-radius: 20px; cursor: pointer; font-size: 13px;" onclick="selectCategory(this, 'study')">
|
||
📚 学习
|
||
<input type="radio" name="category" value="study" style="display: none;">
|
||
</label>
|
||
<label style="padding: 10px 16px; background: rgba(198, 246, 213, 0.2); border: 2px solid transparent; border-radius: 20px; cursor: pointer; font-size: 13px;" onclick="selectCategory(this, 'health')">
|
||
💪 健康
|
||
<input type="radio" name="category" value="health" style="display: none;">
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display: flex; gap: 12px;">
|
||
<button type="button" onclick="clearInlineForm()" style="flex: 1; padding: 14px; background: rgba(255,255,255,0.2); border: none; border-radius: 12px; color: white; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.3s;">
|
||
清空
|
||
</button>
|
||
<button type="button" onclick="submitInlineForm()" style="flex: 2; padding: 14px; background: white; border: none; border-radius: 12px; color: #667eea; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.3s;">
|
||
✅ 添加任务
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
|
||
|
||
---
|
||
|
||
**✅ 您现在可以直接在上方的卡片中填写任务信息,点击"添加任务"即可!**
|
||
|
||
填写完成后告诉我"已填好"或"添加",我会帮您确认是否成功!
|
||
`;
|
||
});
|
||
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);
|