godoos/frontend/src/stores/localchat.ts
2024-07-23 19:02:10 +08:00

464 lines
13 KiB
TypeScript

import { defineStore } from 'pinia'
import emojiList from "@/assets/emoji.json"
import { ref, toRaw, inject } from "vue";
import { db } from './db'
import { System,dirname } from "@/system";
import { getSystemConfig } from "@/system/config";
import { isBase64, base64ToBuffer } from "@/util/file";
import { notifyError, notifySuccess } from "@/util/msg";
export const useLocalChatStore = defineStore('localChatStore', () => {
const config = getSystemConfig();
const sys = inject<System>("system");
const userList:any = ref([])
const msgList:any = ref([])
const contentList:any = ref([])
const hostInfo:any = ref({})
const showChooseFile = ref(false)
const currentPage = ref(1)
const pageSize = ref(50)
const navList = ref([
{ index: 1, lable: "消息列表", icon: "ChatDotRound", type:"success" },
{ index: 2, lable: "用户列表", icon: "UserFilled", type: "info" },
])
const navId = ref(1)
const sendInfo = ref("")
const chatTargetId = ref(0)
const chatTargetIp = ref("")
const handleSelect = (key: number) => {
navId.value = key;
};
const setChatId = async(ip : string) => {
//console.log(ip)
//chatTargetId.value = id
chatTargetIp.value = ip
const data = await db.get("chatuser", {ip : ip})
if(!data)return;
chatTargetId.value = data.id
clearContentList(data.id)
currentPage.value = 1
await getMsgList()
}
const initContentList = async () => {
const list:any = {}
const msgAll = await db.getAll('chatmsg')
msgAll.forEach((d : any) => {
if(!d.isMe){
if (!list[d.targetIp]){
list[d.targetIp] = []
}
list[d.targetIp].push(d)
}
})
const res = []
for(const p in list){
const chatArr = list[p]
let readNum = 0
chatArr.forEach((d:any) => {
if(!d.isRead){
readNum++
}
})
const last = chatArr.pop()
last.readNum = readNum
res.push(last)
}
contentList.value = res.sort((a, b) => b.createdAt - a.createdAt);
}
const clearContentList = (targetId:number) => {
contentList.value.forEach((d : any) => {
if(d.targetId === targetId) {
d.readNum = 0
}
})
}
const clearMsg = async () => {
if (chatTargetIp.value === '') return
await db.deleteByField('chatmsg','targetIp', chatTargetIp.value)
msgList.value = []
}
const updateContentList = async (msg:any) => {
if(msg.isMe)return;
const has = contentList.value.find((d:any) => d.targetIp === msg.targetIp)
if(has){
contentList.value.forEach((d: any, index: number) => {
if (d.targetIp === msg.targetIp) {
if (!msg.isRead) {
msg.readNum = d.readNum + 1;
} else {
msg.readNum = 0;
}
// 直接替换数组中的元素以触发更新
contentList.value.splice(index, 1, msg);
}
});
//console.log(contentList.value)
}else{
if(msg.isRead){
msg.readNum = 0
}else{
msg.readNum = 1
}
contentList.value.unshift(msg)
//console.log(contentList.value)
}
contentList.value = contentList.value.sort((a: any, b: any) => b.createdAt - a.createdAt)
}
const init = async() => {
await getUserList()
await initUserList()
await initContentList()
}
const initUserList = async() => {
if(userList.value.length > 0) {
const updates : any = []
userList.value.forEach((d: any) => {
if (d.isOnline) {
updates.push({
key: d.id,
changes: {
isOnline: false
}
})
}
});
await db.table('chatuser').bulkUpdate(updates)
}
}
const refreshUserList = async () => {
await db.clear('chatuser')
userList.value = []
}
const getMsgList = async () => {
if (chatTargetId.value < 1)return;
//msgList.value = await db.getByField('chatmsg', 'targetId', chatTargetId.value)
//msgList.value = await db.pageSearch('chatmsg', currentPage.value, pageSize.value, { targetId: chatTargetId.value })
const offset = (currentPage.value - 1) * pageSize.value
const list = await db.table('chatmsg')
.where({ targetIp: chatTargetIp.value })
.desc()
.offset(offset)
.limit(pageSize.value)
.toArray();
list.sort((a:any,b:any) => a.id > b.id)
msgList.value = list;
}
const moreMsgList = async() => {
if (chatTargetId.value < 1) return;
//const list = await db.pageSearch('chatmsg', currentPage.value + 1, pageSize.value, { targetId: chatTargetId.value })
const offset = currentPage.value * pageSize.value
const list = await db.table('chatmsg')
.where({ targetIp: chatTargetIp.value })
.desc()
.offset(offset)
.limit(pageSize.value)
.toArray();
if(list && list.length > 0) {
list.sort((a: any, b: any) => a.id > b.id)
currentPage.value = currentPage.value + 1
msgList.value = [...list, ...msgList.value];
}
}
const getUserList = async () => {
const list = await db.getAll('chatuser')
list.sort((a: any, b: any) => a.updatedAt > b.updatedAt)
userList.value = list
}
const setUserList = async (data:any) => {
//console.log(data)
if(data.length < 1){
return
}
hostInfo.value = data[0]
data.shift()
const ips:any = []
userList.value.forEach((d : any) => {
ips.push(d.ip)
});
const has:any = []
const nothas:any = []
data.forEach((d:any) => {
if(ips.includes(d.ip)){
has.push(d.ip)
}else{
nothas.push(d)
}
})
if(has.length > 0) {
const updates:any = []
userList.value.forEach((d: any) => {
if(has.includes(d.ip)){
updates.push({
key : d.id,
changes : {
isOnline : true,
updatedAt:Date.now()
}
})
}
});
await db.table('chatuser').bulkUpdate(updates)
}
if(nothas.length > 0) {
nothas.forEach((d:any) => {
d.isOnline = true
d.username = data.hostname
d.createdAt = Date.now()
d.updatedAt = Date.now()
})
await db.table('chatuser').bulkAdd(nothas)
}
await getUserList()
}
const addFile = async (data:any) => {
const targetUser:any = await getTargetUser(data)
const files:any = []
data.fileList.forEach((d:any) => {
d.save_path = d.save_path.replace(/\\/g, "/");
files.push({
name : d.name,
path : d.save_path,
ext : d.save_path.split('.').pop(),
content: d.content
})
})
const saveMsg: any = {
type: 'file',
targetId: targetUser.id,
targetIp: targetUser.ip,
content: files,
reciperInfo: data.senderInfo,
createdAt: Date.now(),
isMe: false,
isRead: false,
status: 'reciped'
}
if (targetUser.id === chatTargetId.value) {
saveMsg.readAt = Date.now()
saveMsg.isRead = true
msgList.value.push(saveMsg)
}
console.log(saveMsg)
await db.addOne('chatmsg', saveMsg)
//await getMsgList()
await updateContentList(saveMsg)
if (config.storeType === 'browser') {
await storeFile(files)
}
handleSelect(1)
}
const storeFile = async(fileList : any) => {
if (fileList.length < 1) return;
console.log(fileList)
for (let i = 0; i < fileList.length; i++) {
let content = fileList[i].content
if(typeof content === 'string') {
if(isBase64(content)){
content = base64ToBuffer(content);
}
const path = dirname(fileList[i].path)
//console.log(path)
await sys?.fs.mkdir(path);
await sys?.fs.writeFile(fileList[i].path, content);
}
}
}
const getTargetUser = async (data:any) => {
let targetUser:any = userList.value.find((d: any) => d.ip === data.senderInfo.ip)
if (!targetUser){
targetUser = {
isOnline : true,
ip:data.senderInfo.ip,
hostname: data.senderInfo.hostname,
username : data.senderInfo.hostname,
createdAt : Date.now(),
updatedAt : Date.now()
}
targetUser.id = await db.addOne("chatuser",targetUser)
userList.value.unshift(targetUser)
}
return targetUser
}
const addText = async (data:any) => {
const targetUser:any = await getTargetUser(data)
const saveMsg:any = {
type: 'text',
targetId: targetUser.id,
targetIp: targetUser.ip,
content: data.content,
reciperInfo: data.senderInfo,
createdAt: Date.now(),
isMe: false,
isRead: false,
status: 'reciped'
}
if (targetUser.id === chatTargetId.value){
saveMsg.readAt = Date.now()
saveMsg.isRead = true
msgList.value.push(saveMsg)
}
//console.log(saveMsg)
await db.addOne('chatmsg', saveMsg)
//await getMsgList()
await updateContentList(saveMsg)
handleSelect(1)
}
const sendMsg = async () => {
if(chatTargetId.value < 1) {
return
}
const saveMsg:any = {
type : 'text',
targetId : chatTargetId.value,
targetIp: chatTargetIp.value,
content: sendInfo.value.trim(),
senderInfo: toRaw(hostInfo.value),
createdAt:Date.now(),
isMe:true,
isRead:false,
status:'sending'
}
//console.log(saveMsg)
const msgId = await db.addOne('chatmsg', saveMsg)
//await getMsgList()
msgList.value.push(saveMsg)
const targetUser = userList.value.find((d: any) => d.id === chatTargetId.value)
//console.log(targetUser)
if(targetUser.isOnline) {
const postUrl = `http://${targetUser.ip}:56780/message`
const completion = await fetch(postUrl, {
method: "POST",
body: JSON.stringify(saveMsg),
})
if (!completion.ok) {
console.log(completion)
}else{
saveMsg.isRead = true
saveMsg.status = 'sended'
saveMsg.readAt = Date.now()
await db.update('chatmsg', msgId, saveMsg)
}
}
sendInfo.value = ""
await updateContentList(saveMsg)
}
//上传文件资源
async function uploadFile(paths:any) {
if (chatTargetId.value < 1) {
return
}
const targetUser = userList.value.find((d: any) => d.id === chatTargetId.value)
if (!targetUser.isOnline) {
notifyError("The user is not online!");
return;
}
if (!hostInfo.value || !hostInfo.value.ip) {
notifyError("Please wait for a moment");
return;
}
//console.log(paths)
const formData = new FormData();
const errstr:any = []
const files:any = []
for (let i = 0; i < paths.length; i++) {
const content = await sys?.fs.readFile(paths[i]);
let blobContent;
if(!content || content == ''){
errstr.push(paths[i] + " is empty")
continue
}
if (content instanceof ArrayBuffer) {
blobContent = new Blob([content]);
}
else if (typeof content === 'string') {
if (isBase64(content)) {
const base64 = base64ToBuffer(content);
blobContent = new Blob([base64]);
} else {
blobContent = new Blob([content], { type: "text/plain;charset=utf-8" });
}
}
else {
errstr.push(paths[i] + " type is error")
continue
}
const fileName = paths[i].split("/").pop()
files.push({
name: fileName,
path: paths[i],
ext : fileName.split(".").pop(),
})
//files.push(blobContent);
formData.append(`files`, blobContent, fileName);
}
if(errstr.length > 0) {
errstr.forEach((d:any) => {
notifyError(d);
})
return
}
//formData.append("files", files);
formData.append("ip", hostInfo.value.ip);
formData.append("hostname", hostInfo.value.hostname);
//console.log(formData)
const postUrl = `http://${targetUser.ip}:56780/upload`
const res = await fetch(postUrl, {
method: "POST",
body: formData,
});
if (!res.ok) {
console.log(res);
notifyError("Upload error!");
return;
}
const saveMsg: any = {
type: 'file',
targetId: targetUser.id,
targetIp: targetUser.ip,
content: files,
reciperInfo: toRaw(targetUser),
createdAt: Date.now(),
isMe: false,
isRead: true,
status: 'reciped'
}
console.log(saveMsg)
await db.addOne('chatmsg', saveMsg)
msgList.value.push(saveMsg)
notifySuccess("upload success!");
}
return {
userList,
navList,
sendInfo,
navId,
chatTargetId,
chatTargetIp,
msgList,
hostInfo,
contentList,
emojiList,
showChooseFile,
pageSize,
init,
setUserList,
getUserList,
handleSelect,
setChatId,
sendMsg,
addText,
addFile,
uploadFile,
moreMsgList,
refreshUserList,
clearMsg
}
})