From 5cbb35f659665615efe555d668d92c4d72b417bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E7=94=B0=E5=BC=98?= <1240092443@qq.com> Date: Tue, 29 Oct 2024 09:21:52 +0800 Subject: [PATCH] =?UTF-8?q?add:=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/auto-imports.d.ts | 3 +- frontend/components.d.ts | 1 + frontend/src/components/chat/Chat.vue | 231 ++++++---- frontend/src/components/chat/ChatBox.vue | 341 +++++++------- frontend/src/components/chat/ChatMenu.vue | 8 +- frontend/src/components/chat/ChatMessage.vue | 26 +- frontend/src/components/chat/ChatMsgList.vue | 199 +++++--- frontend/src/components/chat/ChatUserList.vue | 268 ++++++++--- .../src/components/chat/ChatUserSetting.vue | 1 - frontend/src/components/chat/chatUserInfo.vue | 79 ++++ frontend/src/stores/chat.ts | 435 ++++++++++++++---- frontend/src/stores/db.ts | 39 +- 12 files changed, 1150 insertions(+), 481 deletions(-) create mode 100644 frontend/src/components/chat/chatUserInfo.vue diff --git a/frontend/auto-imports.d.ts b/frontend/auto-imports.d.ts index eab6be6..d0c217f 100644 --- a/frontend/auto-imports.d.ts +++ b/frontend/auto-imports.d.ts @@ -3,6 +3,7 @@ // @ts-nocheck // noinspection JSUnusedGlobalSymbols // Generated by unplugin-auto-import +// biome-ignore lint: disable export {} declare global { const EffectScope: typeof import('vue')['EffectScope'] @@ -70,6 +71,6 @@ declare global { // for type re-export declare global { // @ts-ignore - export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' import('vue') } diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 35ff343..819d793 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -26,6 +26,7 @@ declare module 'vue' { ChatMessage: typeof import('./src/components/chat/ChatMessage.vue')['default'] ChatMsgList: typeof import('./src/components/chat/ChatMsgList.vue')['default'] ChatNav: typeof import('./src/components/localchat/ChatNav.vue')['default'] + ChatUserInfo: typeof import('./src/components/chat/chatUserInfo.vue')['default'] ChatUserList: typeof import('./src/components/chat/ChatUserList.vue')['default'] ChatUserSetting: typeof import('./src/components/chat/ChatUserSetting.vue')['default'] ChatWorkList: typeof import('./src/components/chat/ChatWorkList.vue')['default'] diff --git a/frontend/src/components/chat/Chat.vue b/frontend/src/components/chat/Chat.vue index 4f8eab5..058407d 100644 --- a/frontend/src/components/chat/Chat.vue +++ b/frontend/src/components/chat/Chat.vue @@ -1,115 +1,144 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file + diff --git a/frontend/src/components/chat/ChatBox.vue b/frontend/src/components/chat/ChatBox.vue index 4d9fc64..318e13c 100644 --- a/frontend/src/components/chat/ChatBox.vue +++ b/frontend/src/components/chat/ChatBox.vue @@ -1,173 +1,204 @@ - - - - {{ store.targetUserInfo.username }} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 暂无内容 - + + + + {{ store.targetUserInfo.username }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 欢迎使用GodoOS + \ No newline at end of file + .no-message-container { + height: 100%; + margin: 120px auto; + text-align: center; + justify-content: center; + } + diff --git a/frontend/src/components/chat/ChatMenu.vue b/frontend/src/components/chat/ChatMenu.vue index aa86def..2439900 100644 --- a/frontend/src/components/chat/ChatMenu.vue +++ b/frontend/src/components/chat/ChatMenu.vue @@ -3,6 +3,10 @@ import {ref} from "vue"; import { useChatStore } from "@/stores/chat"; import {Setting as SettingIcon} from "@element-plus/icons-vue"; const store = useChatStore() +const getOnline = () => { + store.getOnlineUsers() + store.setCurrentNavId(1) +} @@ -17,7 +21,7 @@ const store = useChatStore() - + @@ -59,7 +63,7 @@ const store = useChatStore() .menu-icon-on { margin: 20px auto; font-size: 25px; - color: #07C160; + color: #0078d4; cursor: pointer; } diff --git a/frontend/src/components/chat/ChatMessage.vue b/frontend/src/components/chat/ChatMessage.vue index 12db80e..264ada4 100644 --- a/frontend/src/components/chat/ChatMessage.vue +++ b/frontend/src/components/chat/ChatMessage.vue @@ -1,13 +1,11 @@ - - - - + + @@ -30,10 +28,7 @@ const store = useChatStore() - - - - + @@ -56,19 +51,16 @@ const store = useChatStore() - - - + {{ item.userInfo.id === store.targetUserId ? "你" : item.userInfo.username }}撤回了一条消息 - - - - {{ item.label }} + + + {{ contextItem.label }} @@ -163,4 +155,4 @@ const store = useChatStore() font-family: Arial, sans-serif; line-height: 2.2; } - + \ No newline at end of file diff --git a/frontend/src/components/chat/ChatMsgList.vue b/frontend/src/components/chat/ChatMsgList.vue index 41693d7..00c6ed9 100644 --- a/frontend/src/components/chat/ChatMsgList.vue +++ b/frontend/src/components/chat/ChatMsgList.vue @@ -1,71 +1,158 @@ - - - - + + - + - - - - {{ item.name }} + + + + {{ item.nickname }} + + {{ item.previewMessage }} + + {{ + item.targetUserId === id + ? "你" + : '"' + item.nickname + '"' + }}撤回了一条消息 + + - - {{ item.previewTimeFormat }} + + + {{ item.previewTimeFormat }} + - - {{ item.previewMessage }} - {{ item.userId === id ? "你" : "\"" + item.name + - "\""}}撤回了一条消息 - + + + + + 暂无数据 + + + diff --git a/frontend/src/components/chat/ChatUserList.vue b/frontend/src/components/chat/ChatUserList.vue index 30629a8..9b4fa52 100644 --- a/frontend/src/components/chat/ChatUserList.vue +++ b/frontend/src/components/chat/ChatUserList.vue @@ -1,71 +1,221 @@ - - - - - - - - - - {{ item.name }} - - - {{ item.previewTimeFormat }} - - - - {{ item.previewMessage }} - {{ item.userId === id ? "你" : "\"" + item.name + - "\""}}撤回了一条消息 - - - - - + + + + 同事({{store.userList.length}}) + 同事 + + + + + + + + + + + + + {{ item.nickname }} + + + + + + + + + + + + {{ item.ip }} + + + + + + + + + 暂无数据 + + + + + 部门({{store.groupList.length}}) + 部门 + + + + + + + + + + + + + {{ group.name }} + + + + + {{ group.previewTimeFormat }} + + + + + + {{ group.previewMessage }} + + + {{ + group.userId === id + ? "你" + : '"' + group.name + '"' + }}撤回了一条消息 + + + + + + + + + 暂无数据 + + + + .no-data { + text-align: center; + color: #999999; + } + \ No newline at end of file diff --git a/frontend/src/components/chat/ChatUserSetting.vue b/frontend/src/components/chat/ChatUserSetting.vue index ff34fc6..24018fc 100644 --- a/frontend/src/components/chat/ChatUserSetting.vue +++ b/frontend/src/components/chat/ChatUserSetting.vue @@ -13,7 +13,6 @@ const onSubmit = () => { - diff --git a/frontend/src/components/chat/chatUserInfo.vue b/frontend/src/components/chat/chatUserInfo.vue new file mode 100644 index 0000000..c6beb3e --- /dev/null +++ b/frontend/src/components/chat/chatUserInfo.vue @@ -0,0 +1,79 @@ + + + + + + 欢迎使用GodoOS + + + + 昵称: {{ store.targetUserInfo.nickname }} + 邮箱: {{ store.targetUserInfo.email }} + 电话: {{ store.targetUserInfo.phone }} + 描述: {{ store.targetUserInfo.desc }} + 工号: {{ store.targetUserInfo.jobNumber }} + 工作地点: {{ store.targetUserInfo.workPlace }} + 入职日期: {{ store.targetUserInfo.hiredDate }} + + 发送消息 + + + + + + diff --git a/frontend/src/stores/chat.ts b/frontend/src/stores/chat.ts index 2d4a8d4..f1fe69e 100644 --- a/frontend/src/stores/chat.ts +++ b/frontend/src/stores/chat.ts @@ -1,86 +1,367 @@ -import { defineStore } from 'pinia' -import emojiList from "@/assets/emoji.json" -import { getSystemConfig } from '@/system/config' +import emojiList from "@/assets/emoji.json"; +import { fetchGet, fetchPost, getSystemConfig } from '@/system/config'; +import { notifyError } from "@/util/msg"; +import { defineStore } from 'pinia'; +import { db } from "./db"; +import { useMessageStore } from "./message"; + export const useChatStore = defineStore('chatStore', () => { - const userList: any = ref([]) // 用户列表 - const chatList: any = ref([]) // 消息列表 - const msgList: any = ref([]) //聊天消息列表 - const userInfo: any = ref({}) - const showChooseFile = ref(false) - const currentPage = ref(1) - const pageSize = ref(50) - const scrollbarRef = ref() - const innerRef = ref() - const config = getSystemConfig() - const currentNavId = ref(0) - const message: any = ref() - const targetUserInfo:any = ref({}) - const targetUserId = ref(0) - const search = ref('') - const contextMenu = ref({ - visible: false, - chatMessageId: 0, - list: [ - { - id: 2, - label: '撤回', - } - ], - x: 0, - y: 0 - }) - const initChat = () => { - if(config.userInfo.avatar == ''){ - config.userInfo.avatar = '/logo.png' - } - userInfo.value = config.userInfo + // 用户列表 + const userList: any = ref([]); + + // 定义聊天列表项的接口 + interface ChatListItem { + id: number; + nickname: string; + avatar: string; + previewTimeFormat: string; + previewType: 0 | 1; // 消息类型,0表示正常消息,1表示撤回消息 + previewMessage: string; + } + + // 模拟数据 - 聊天列表 + const chatList = ref([ + { + id: 2, + nickname: '朋友2', + avatar: '/logo.png', + previewTimeFormat: "昨天", + previewType: 1, + previewMessage: "测试消息", + }, + ]); + + // 模拟数据 - 聊天消息列表 + const chatHistory = ref([]); + + // 群组数据 + const groupList = ref([ + { + id: 1, + name: '群组1', + avatar: '/logo.png', + previewTimeFormat: "今天", + previewType: 0, + previewMessage: "这是一个示例消息。", + }, + { + id: 2, + name: '群组2', + avatar: '/logo.png', + previewTimeFormat: "今天", + previewType: 0, + previewMessage: "这是一个示例消息。", + }, + { + id: 3, + name: '群组3', + avatar: '/logo.png', + previewTimeFormat: "今天", + previewType: 0, + previewMessage: "这是一个示例消息。", } - const setCurrentNavId = (id: number) => { - currentNavId.value = id + ]); + + const activeNames = ref([]); + const userInfo: any = ref({}); + const showChooseFile = ref(false); + const currentPage = ref(1); + const pageSize = ref(50); + const innerRef = ref(null); + const scrollbarRef = ref(null); + const config = getSystemConfig(); + const currentNavId = ref(0); + const message: any = ref(''); + const targetUserInfo: any = ref({}); + const targetUserId = ref(); + const search = ref(''); + const messageStore = useMessageStore(); + const apiUrl = "http://192.168.1.10:8816"; + + const contextMenu = ref({ + visible: false, + chatMessageId: 0, + list: [ + { + id: 2, + label: '撤回', + } + ], + x: 0, + y: 0 + }); + + const initChat = () => { + if (config.userInfo.avatar == '') { + config.userInfo.avatar = '/logo.png'; } - const sendMessage = async () => { - await setScrollToBottom() + userInfo.value = config.userInfo; + }; + + const setCurrentNavId = (id: number) => { + currentNavId.value = id; + }; + + const sendMessage = async () => { + const chatSendUrl = apiUrl + '/chat/send'; + const messageHistory = { + type: 'text', + createdAt: Date.now(), + content: message.value, + targetUserId: targetUserId.value, + previewType: 0, // 消息类型,0表示正常消息,1表示撤回消息 + previewMessage: message.value, + isMe: true, + isRead: false, + userInfo: { + id: config.userInfo.id, + username: config.userInfo.username, + avatar: config.userInfo.avatar, + }, + }; + + const res = await fetchPost(chatSendUrl, messageHistory); + + if (res.ok) { + // 本地存储一份聊天记录 + await db.addOne('chatRecord', messageHistory); + + // 更新聊天历史 + chatHistory.value.push(messageHistory); + + // 更新 chatList 和 conversationList + await updateConversationList(targetUserId.value); + + // 清空输入框 + clearMessage(); + + // 聊天框滚动到底部 + await setScrollToBottom(); + return; } - const setScrollToBottom = async () => { - await nextTick() - const max = innerRef.value.clientHeight - scrollbarRef.value.setScrollTop(max) + notifyError("消息发送失败"); + }; + + const updateConversationList = async (id: number) => { + // 先判断是否已经存在该会话 + const res = await db.getRow('conversationList', 'id', id); + + if (res) { + // 更新现有会话 + const updatedConversation = { + ...res, + previewMessage: message.value, + previewTimeFormat: formatTime(Date.now()), + previewType: 0, + }; + await db.update('conversationList', id, updatedConversation); + + // 更新 chatList + const existingConversationIndex = chatList.value.findIndex(conversation => conversation.id === id); + if (existingConversationIndex !== -1) { + chatList.value[existingConversationIndex] = updatedConversation; + } else { + chatList.value.push(updatedConversation); + } + } else { + const targetUser = await db.getOne('workbenchusers', id); + const lastMessage = messageHistory; + + const targetUserInfo = { + id: targetUser.id, + nickname: targetUser.nickname, + avatar: targetUser.avatar, + }; + + // 计算时间差 + const now = new Date(); + const createdAt = new Date(lastMessage.createdAt); + const diffTime = Math.abs(now.getTime() - createdAt.getTime()); + + // 根据时间差格式化时间 + const previewTimeFormat = formatTime(Date.now()); + + const newConversation = { + ...targetUserInfo, + previewTimeFormat, + previewMessage: lastMessage.content, + previewType: lastMessage.type, + }; + + // 添加到 conversationList + await db.addOne('conversationList', newConversation); + + // 添加到 chatList + chatList.value.push(newConversation); } - const changeChatList = async () => { - // const res = await getChatList(id) - // chatList.value = res.data + }; + + const formatTime = (timestamp: number): string => { + const now = new Date(); + const createdAt = new Date(timestamp); + const diffTime = Math.abs(now.getTime() - createdAt.getTime()); + + const minutes = Math.floor(diffTime / (1000 * 60)); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + if (minutes < 1) { + return '刚刚'; + } else if (minutes < 60) { + return `${minutes}分钟前`; + } else if (hours < 24) { + return `${hours}小时前`; + } else { + return `${days}天前`; } - const handleContextMenu = async () => { - contextMenu.value.visible = false; + }; + + const clearMessage = () => { + message.value = ''; + }; + + const initSSE = async () => { + console.log('initSSE'); + const source = new EventSource(`${apiUrl}/chat/message`); + + console.log(source); + source.onmessage = function (event) { + const data = JSON.parse(event.data); + console.log(data); + messageStore.handleMessage(data); + }; + + source.onerror = function (event) { + console.error('EventSource error:', event); + }; + }; + + const setScrollToBottom = async () => { + await nextTick(); // 确保 DOM 已经更新完毕 + + // 检查 innerRef 是否存在 + if (!innerRef.value) { + console.warn('innerRef is not defined.'); + return; } - const showContextMenu = (event: any, id: number) => { - contextMenu.value.visible = true; - contextMenu.value.chatMessageId = id; - contextMenu.value.x = event.x; - contextMenu.value.y = event.y; + + // 设置滚动条到底部 + const max = innerRef.value.clientHeight; + if (scrollbarRef.value) { + scrollbarRef.value.setScrollTop(max); + } else { + console.warn('scrollbarRef is not defined.'); } - return { - emojiList, - userList, - chatList, - msgList, - userInfo, - search, - showChooseFile, - currentPage, - pageSize, - scrollbarRef, - innerRef, - currentNavId, - targetUserInfo, - targetUserId, - message, - contextMenu, - initChat, - setCurrentNavId, - sendMessage, - changeChatList, - handleContextMenu, - showContextMenu + }; + + const changeChatList = async (id: number) => { + // 设置 targetUserId + targetUserId.value = id; + + // 获取当前用户和目标用户的聊天记录 + const messagesList = await db.getByField('chatRecord', 'targetUserId', id); + chatHistory.value = messagesList; + + // 设置目标用户的信息 + setTargetUserInfo(id); + }; + + const setTargetUserInfo = async (id: number) => { + targetUserInfo.value = await db.getOne('workbenchusers', id); + }; + + const handleContextMenu = async () => { + contextMenu.value.visible = false; + }; + + const getOnlineUsers = async () => { + const res = await fetchGet(apiUrl + '/chat/online?page=1'); + + if (!res.ok) { + notifyError("获取在线用户失败"); + return; } -}) \ No newline at end of file + + const data = await res.json(); + console.log(data); + + const onlineUsers = data.data.list.map((item: any) => ({ + id: item.id, + username: item.username, + nickname: item.nickname, + email: item.email, + phone: item.phone, + desc: item.desc, + jobNumber: item.job_number, + workPlace: item.work_place, + hiredDate: item.hired_date, + avatar: item.avatar || '/logo.png', + isOnline: true, + ip: item.login_ip, + updatedAt: item.updated_at, + createdAt: item.add_time, + })); + + // 更新或添加用户 + const existingUserIds = await db.getAll('workbenchusers').then(users => users.map(user => user.id)); + const newUserIds = onlineUsers.filter(user => !existingUserIds.includes(user.id)).map(user => user.id); + + // 更新现有用户的状态 + const updatePromises = onlineUsers.filter(user => existingUserIds.includes(user.id)).map(user => { + return db.update('workbenchusers', user.id, { + isOnline: true, + updatedAt: user.updatedAt, + ip: user.ip, + }); + }); + + // 添加新用户 + const addPromises = onlineUsers.filter((user: { id: any }) => newUserIds.includes(user.id)).map((user: any) => { + return db.addOne('workbenchusers', user); + }); + + await Promise.all([...updatePromises, ...addPromises]); + + // 更新 userList + userList.value = await db.getAll('workbenchusers'); + + console.log(userList.value); + }; + + const showContextMenu = (event: any, id: number) => { + contextMenu.value.visible = true; + contextMenu.value.chatMessageId = id; + contextMenu.value.x = event.x; + contextMenu.value.y = event.y; + }; + + return { + emojiList, + userList, + chatList, + groupList, + chatHistory, + userInfo, + search, + showChooseFile, + currentPage, + pageSize, + scrollbarRef, + innerRef, + currentNavId, + targetUserInfo, + targetUserId, + message, + contextMenu, + activeNames, + initChat, + initSSE, + setCurrentNavId, + sendMessage, + changeChatList, + handleContextMenu, + showContextMenu, + getOnlineUsers, + updateConversationList + }; +}); \ No newline at end of file diff --git a/frontend/src/stores/db.ts b/frontend/src/stores/db.ts index aa9dc14..57779dd 100644 --- a/frontend/src/stores/db.ts +++ b/frontend/src/stores/db.ts @@ -1,13 +1,22 @@ -import Dexie from 'dexie' +import Dexie from 'dexie'; -export type ChatTable = 'chatuser' | 'chatmsg' | 'chatmessage' | 'groupmessage' +export type ChatTable = 'chatuser' | 'chatmsg' | 'chatmessage' | 'groupmessage' | 'chatRecord' | 'workbenchusers' | 'conversationList'; -export const dbInit:any = new Dexie('GodoOSDatabase'); +export const dbInit: any = new Dexie('GodoOSDatabase'); dbInit.version(1).stores({ - chatuser:'++id,ip,hostname,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt', - chatmsg:'++id,targetId,targetIp,senderInfo,reciperInfo,content,type,status,isRead,isMe,readAt,createdAt', - chatmessage:'++id,userId,toUserId,senderInfo,isMe,isRead,content,type,readAt,createdAt', - groupmessage:'++id,userId,groupId,senderInfo,isMe,isRead,content,type,readAt,createdAt' + // 用户列表 + workbenchusers: '++id,ip,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt', + // 聊天记录 + chatRecord: '++id,userId,targetUserId,senderInfo,previewType,previewMessage,isMe,isRead,content,type,readAt,createdAt', + // 会话列表 + conversationList: '++id,userId,targetUserId,targetIp,senderInfo,previewMessage,previewType,isMe,isRead,content,type,createdAt', + chatuser: '++id,ip,hostname,userName,avatar,mobile,nickName,isOnline,updatedAt,createdAt', + // chatmsg: '++id,targetUserId,targetIp,senderInfo,reciperInfo,previewMessage,previewType,content,type,status,isRead,isMe,readAt,createdAt', + chatmessage: '++id,userId,targetUserId,senderInfo,isMe,isRead,content,type,readAt,createdAt', + groupmessage: '++id,userId,groupId,senderInfo,isMe,isRead,content,type,readAt,createdAt', +}).upgrade((tx: { chatRecord: { addIndex: (arg0: string, arg1: (obj: { targetUserId: any; }) => any) => void; }; }) => { + // 手动添加索引 + tx.chatRecord.addIndex('targetUserId', (obj: { targetUserId: any; }) => obj.targetUserId); }); export const db = { @@ -55,7 +64,7 @@ export const db = { .limit(size) .toArray(); }, - async filter(tableName: ChatTable, filterFunc : any) { + async filter(tableName: ChatTable, filterFunc: any) { return dbInit[tableName].filter(filterFunc).toArray() }, table(tableName: ChatTable) { @@ -64,26 +73,28 @@ export const db = { async getOne(tableName: ChatTable, Id: number) { return dbInit[tableName].get(Id) }, - async getRow(tableName: ChatTable, fieldName: string, val: any){ + async getRow(tableName: ChatTable, fieldName: string, val: any) { return dbInit[tableName].where(fieldName).equals(val).first() }, - async get(tableName: ChatTable, whereObj : any) { + async get(tableName: ChatTable, whereObj: any) { //console.log(whereObj) const data = await dbInit[tableName].where(whereObj).first() //console.log(data) - return data? data : false + return data ? data : false }, async rows(tableName: ChatTable, whereObj: any) { return dbInit[tableName].where(whereObj).toArray() }, + async field(tableName: ChatTable, whereObj: any, field: string) { const data = await this.get(tableName, whereObj) return data ? data[field] : false }, - async getValue(tableName: ChatTable, fieldName: string, val: any, fName : string) { + async getValue(tableName: ChatTable, fieldName: string, val: any, fName: string) { const row = await this.getRow(tableName, fieldName, val); return row[fName] }, + async getByField(tableName: ChatTable, fieldName: string, val: any) { return dbInit[tableName].where(fieldName).equals(val).toArray() }, @@ -105,6 +116,10 @@ export const db = { async deleteByField(tableName: ChatTable, fieldName: string, val: any) { return dbInit[tableName].where(fieldName).equals(val).delete() }, + // 获取创建时间最近的记录 + async getLatest(tableName: ChatTable, fieldName: string, val: any) { + return dbInit[tableName].where(fieldName).equals(val).reverse().first() + }, async clear(tableName: ChatTable) { return dbInit[tableName].clear() },
暂无内容
欢迎使用GodoOS
暂无数据
昵称: {{ store.targetUserInfo.nickname }}
邮箱: {{ store.targetUserInfo.email }}
电话: {{ store.targetUserInfo.phone }}
描述: {{ store.targetUserInfo.desc }}
工号: {{ store.targetUserInfo.jobNumber }}
工作地点: {{ store.targetUserInfo.workPlace }}
入职日期: {{ store.targetUserInfo.hiredDate }}