优化-数据状态共享

im-chat
This commit is contained in:
zdg 2024-08-13 09:07:28 +08:00
parent f9de8514ed
commit 0ffa45313b
9 changed files with 113 additions and 32 deletions

View File

@ -243,4 +243,18 @@ function handleAll() {
}
}
})
// 用于监听-状态管理变化-初始同步
ipcMain.handle('pinia-state-init', (e, wid, storeName, jsonStr) => {
// for(const curWin of BrowserWindow.getAllWindows()){
// const id = curWin.webContents.id
// const bool = id !== e.sender.id && !curWin.isDestroyed()
// if (bool) { // 除了消息发送窗口和销毁的窗口 其他都发送
// curWin.webContents.send('pinia-state-set', storeName, jsonStr)
// }
// }
console.log('pinia-state-init', jsonStr)
const win = BrowserWindow.fromId(wid)
console.log(win)
win.webContents.send('pinia-state-set', storeName, jsonStr)
})
}

View File

@ -393,7 +393,7 @@ defineExpose({
savaDataStore
})
watchEffect(() => {
console.log(toolState.model,'监听')
console.log(toolState, '监听')
watchToolState() //
})
</script>

View File

@ -3,41 +3,79 @@
*/
const isNode = typeof require !== 'undefined' // 是否支持node函数
const { ipcRenderer } = isNode?require('electron'):{} // app使用
// const Remote = isNode?require('@electron/remote'):{} // 远程模块
export function shareStorePlugin({store}) {
store.$subscribe(() => { // 自动同步
store.$subscribe((mutation, state) => { // 自动同步
// mutation 变量包含了变化前后的状态
// mutation.events: key newValue target oldValue oldTarget
// state 是变化后的状态
console.log('store.$subscribe', mutation)
// 在存储变化的时候执行
const storeName = store.$id
// const storeName = store.$id
// const storeName = mutation.storeId
const { storeId: storeName, payload, events, type } = mutation // direct
// if (!Object.keys(payload).length) return
if (type != 'direct') return
// 用于多窗口共享(需要共享的状态名称)
const names = ['tool']
if (names.includes(storeName)) stateSync(store) // 需要同步
if (names.includes(storeName)) stateSync(storeName, events.key, events.newValue) // 需要同步
})
// 暴露方法-手动同步
store.stateSync = () => stateSync(store)
store.stateSync = (storeName, key, value) => {
if (!storeName && !!key && !!value) stateSync(storeName, key, value)
else stateSyncAll(store)
}
// 暴露方法-发送当前状态-新窗口
store.stateSyncInit = wid => stateSyncInit(wid, store)
// 监听主线程消息-同步数据
stateChange(store)
}
// 同步数据-发送给主线程
function stateSync(store) {
// 同步数据-发送给主线程-单独
function stateSync(storeName, key, value) {
console.log('state-change', storeName, key, value)
let jsonStr = ''
if (typeof key === 'string') jsonStr = JSON.stringify({[key]:value})
else if (typeof value === 'object') jsonStr = JSON.stringify(key)
// 通知主线程更新
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
}
// 同步数据-发送给主线程-全量更新
function stateSyncAll(store) {
const storeName = store.$id
const jsonStr = JSON.stringify(store.$state)
// console.log('state-change', jsonStr, storeName)
// 通知主线程更新
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
}
// 发送当前数据状态
function stateSyncInit(wid, store) {
const storeName = store.$id
const curJson = JSON.stringify(store.$state) // 当前数据
// 发送同步数据给新窗口-更新状态
ipcRenderer.invoke('pinia-state-init', wid, storeName, curJson)
}
// 同步数据-接收主线程消息
function stateChange(store) {
const storeName = store.$id
// 设置更新 store-state 数据状态
const setStateData = (jsonStr) => {
const curJson = JSON.stringify(store.$state) // 当前数据
const isUp = curJson != jsonStr // 不同的时候才写入,不然会导致触发数据变化监听,导致死循环
if (!isUp) return
const stateJson = JSON.parse(jsonStr) // 新数据
// console.log('setStateData', stateJson)
// 更新状态
store.$patch(stateJson)
// 您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态
// store.$state = stateJson
}
// 消息监听
ipcRenderer?.on('pinia-state-set', (e, sName, jsonStr) => {
if (sName == storeName) { // 更新对应数据
// console.log('state-set', jsonStr, sName)
const curJson = JSON.stringify(store.$state) // 当前数据
const isUp = curJson != jsonStr // 不同的时候才写入,不然会导致触发数据变化监听,导致死循环
if (!isUp) return
const stateJson = JSON.parse(jsonStr) // 新数据
// 更新状态
store.$patch(stateJson)
// 您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态
// store.$state = stateJson
}
// console.log('pinia-state-set', sName, jsonStr)
sName == storeName && setStateData(jsonStr) // 更新对应数据
})
}

View File

@ -10,10 +10,12 @@ const isNode = typeof require !== 'undefined' // 是否支持node函数
const path = isNode?require('path'):{}
const Remote = isNode?require('@electron/remote'):{}
const { ipcRenderer } = isNode?require('electron'):window.electron || {}
import { useToolState } from '@/store/modules/tool' // 获取store状态
// 常用变量
const BaseUrl = isNode?process.env['ELECTRON_RENDERER_URL']+'/#':''
const isDev = isNode?process.env.NODE_ENV !== 'production':''
const toolState = useToolState() // 获取store状态
// 暴露Remote中的属性
export const ipcMain = Remote?.ipcMain || {}
@ -163,13 +165,19 @@ export function toolWindow({url, isConsole, option={}}) {
}
// 创建-新窗口
let win = new Remote.BrowserWindow(config)
if (!isDev) win.loadFile(urlAll,{hash: url}) // 加载文件
else win.loadURL(urlAll) // 加载url
win.once('ready-to-show', () => {resolve(win)})
if (!isDev) win.loadFile(urlAll,{hash: url}) // 加载文件
else win.loadURL(urlAll) // 加载url
win.once('ready-to-show', () => { // 窗口加载完成
resolve(win)
})
// 主窗口关闭事件
mainWin.once('closed', () => { win.destroy()})
// 内部监听器
win.webContents.on('did-finish-load', () => {})
win.webContents.on('did-finish-load', () => {
setTimeout(() => {
toolState.stateSyncInit(win.id) // 同步状态
}, 200);
})
// 内部监听器-是否打印
if (!!isConsole) {
win.webContents.on('console-message', (e,leve,m,lin,s) => {
@ -194,6 +202,7 @@ const eventHandles = (type, win) => {
if(onClosed) onClosed() // 自定义关闭事件
win = null
})
// 新窗口-创建事件(如:主进程加载远程服务)
ipcRenderer.send('new-window', {id:win.id, type})
}

View File

@ -107,7 +107,7 @@ const switchPageMode = () => {
}
}
onMounted(async () => {
toolState.isPdfWin=true
// toolState.isPdfWin=true
pdfObj.pdfUrl = getStaticUrl(route.query.path, 'user', 'selfFile', true)
textbookId.value = route.query.textbookId
pdfObj.bookId=textbookId.value

View File

@ -0,0 +1,14 @@
<script setup>
// im-chat im chat
</script>
<template>
<div class="im-chat">
<slot></slot>
</div>
</template>
<style lang="scss" scoped>
</style>

View File

@ -17,8 +17,11 @@
<!-- 内容部分 -->
<transition name="el-fade-in">
<div class="c-popover" :style="`--top: ${topPos}px;--height:${hPost}px;`" v-show="isVisible">
<div class="content">
<homework/>
<div class="content" v-if="isVisible">
<slot name="content">
<homework v-if="activeObj?.prop === 'resource'" />
<span v-else style="color:red;">{{activeObj}}</span>
</slot>
</div>
</div>
</transition>
@ -135,8 +138,4 @@ const clickHandel = (o, e) => {
transform: rotate(45deg);
}
}
.content{
color: red;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<button v-if="props.test" @click="trigger">测试</button>
<el-button v-if="props.test" type="primary" @click="trigger">测试</el-button>
<div ref="warpRef" class="c-warp">
<template v-for="i in sum">
<slot><el-icon><Star /></el-icon></slot>

View File

@ -9,7 +9,10 @@
<!-- 点赞组件 -->
<upvote-vue></upvote-vue>
<!-- 底部工具栏 :style="dataPos.style"-->
<!-- im-chat 聊天组件 -->
<im-chat />
<!-- 底部工具栏 -->
<div class="tool-bottom-all" @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
<div v-drag="{handle:'.tool-bottom-all', dragtime}"
@v-drag-start="dragtime = Date.now()">
@ -40,6 +43,7 @@ import logo from '@root/resources/icon.png' // logo
import boardVue from './components/board.vue' // -
import sideVue from './components/side.vue' // -
import upvoteVue from './components/upvote.vue' // -
import imChat from './components/imChat.vue' // im-chat-
import vDrag from './directive/drag' // -
import vIgnore from './directive/ignore' // -穿
import { useToolState } from '@/store/modules/tool' // -
@ -62,7 +66,9 @@ const btnList = [ // 工具栏按钮列表
]
// === ===
onMounted(async() => {
resetStatus() // -
setTimeout(() => {
resetStatus() // -
}, 200);
})
@ -125,6 +131,7 @@ const sideChange = o => {
// === ===
watchEffect(() => {
console.log('工具:', toolStore)
// , : -
const show = !toolStore.isPdfWin && toolStore.showBoardAll
if (show != isShow.value) isShow.value = show