zhuhao_dev #104

Merged
zhuhao merged 6 commits from zhuhao_dev into main 2024-08-07 15:51:13 +08:00
10 changed files with 144 additions and 36 deletions
Showing only changes of commit 3bcb0a2ef3 - Show all commits

View File

@ -205,14 +205,8 @@ app.on('ready', () => {
ipcMain.on('openWindow', (e, data) => { ipcMain.on('openWindow', (e, data) => {
createLinkWin(data) createLinkWin(data)
}) })
// 新窗口创建-监听 // zdg: 消息监听
ipcMain.on('new-window', (e, data) => { handleAll()
const { id, type } = data
const win = BrowserWindow.fromId(id)
win.type = type // 绑定独立标识
remote.enable(win.webContents) // 开启远程服务
})
// 打开-登录窗口 // 打开-登录窗口
createLoginWindow() createLoginWindow()
@ -229,3 +223,24 @@ app.on('window-all-closed', () => {
app.quit() app.quit()
} }
}) })
// 监听全局事件
function handleAll() {
// 新窗口创建-监听
ipcMain.on('new-window', (e, data) => {
const { id, type } = data
const win = BrowserWindow.fromId(id)
win.type = type // 绑定独立标识
remote.enable(win.webContents) // 开启远程服务
})
// 用于监听-状态管理变化-同步所有窗口
ipcMain.handle('pinia-state-change', (e, 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)
}
}
})
}

View File

@ -30,7 +30,10 @@
<el-scrollbar height="450px"> <el-scrollbar height="450px">
<div class="textbook-item flex" v-for="item in subjectList" :class="curBookId == item.id ? 'active-item' : ''" <div class="textbook-item flex" v-for="item in subjectList" :class="curBookId == item.id ? 'active-item' : ''"
:key="item.id" @click="changeBook(item)"> :key="item.id" @click="changeBook(item)">
<img :src="BaseUrl + item.avartar" class="textbook-img" alt=""> <img v-if="item.avartar" :src="BaseUrl + item.avartar" class="textbook-img" alt="">
<div v-else class="textbook-img">
<i class="iconfont icon-jiaocaixuanze" style="font-size: 40px;"></i>
</div>
<span class="book-name">{{ item.itemtitle }}</span> <span class="book-name">{{ item.itemtitle }}</span>
</div> </div>
</el-scrollbar> </el-scrollbar>
@ -398,6 +401,9 @@ onMounted(() => {
.textbook-img { .textbook-img {
width: 55px; width: 55px;
height: 70px; height: 70px;
display: flex;
align-items: center;
justify-content: center;
} }
} }

View File

@ -23,7 +23,7 @@
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button type="primary" @click="editUserInfo"> <el-button type="primary" @click="editUserInfo" :loading="subjectLoading">
确定 确定
</el-button> </el-button>
</div> </div>
@ -33,7 +33,7 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, watch } from 'vue' import { ref, watch } from 'vue'
import { listEvaluation } from '@/api/subject' import { listEvaluation } from '@/api/subject'
import { updateUserInfo } from '@/api/system/user' import { updateUserInfo } from '@/api/system/user'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
@ -42,12 +42,20 @@ const userStore = useUserStore()
const { userId, userName } = userStore.user const { userId, userName } = userStore.user
const props = defineProps({ const props = defineProps({
loginData: {
type: Object,
default(){
return {}
}
},
modelValue: { modelValue: {
type: Boolean, type: Boolean,
default: false default: false
}, },
}) })
const subjectLoading = ref(false)
// emit // emit
const emit = defineEmits(['update:modelValue', 'onSuccess']) const emit = defineEmits(['update:modelValue', 'onSuccess'])
@ -111,8 +119,18 @@ const editUserInfo = async () =>{
edustage: gradeVal.value, edustage: gradeVal.value,
edusubject: subjectVal.value edusubject: subjectVal.value
} }
await updateUserInfo(data)
await userStore.getInfo() //
//
subjectLoading.value = true
try {
//
await updateUserInfo(data)
await userStore.login(props.loginData)
await userStore.getInfo()
} finally {
subjectLoading.value = false
}
emit('onSuccess') emit('onSuccess')
} }
@ -148,5 +166,7 @@ watch(() => props.modelValue, (newVal) => {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
} }
.el-select-dropdown__item{
-webkit-app-region: no-drag;
}
</style> </style>

View File

@ -0,0 +1,41 @@
/**
* 共享数据状态-多窗口
*/
const { ipcRenderer } = require('electron') // app使用
export function shareStorePlugin({store}) {
store.$subscribe(() => { // 自动同步
// 在存储变化的时候执行
const storeName = store.$id
// 用于多窗口共享(需要共享的状态名称)
const names = ['tool']
if (names.includes(storeName)) stateSync(store) // 需要同步
})
// 暴露方法-手动同步
store.stateSync = () => stateSync(store)
// 监听主线程消息-同步数据
stateChange(store)
}
// 同步数据-发送给主线程
function stateSync(store) {
const storeName = store.$id
const jsonStr = JSON.stringify(store.$state)
// 通知主线程更新
ipcRenderer.invoke('pinia-state-change', storeName, jsonStr)
}
// 同步数据-接收主线程消息
function stateChange(store) {
const storeName = store.$id
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
}
})
}

View File

@ -1,7 +1,9 @@
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import { shareStorePlugin } from '@/plugins/shareStore'
const pinia = createPinia() //创建pinia实例 const pinia = createPinia() //创建pinia实例
pinia.use(piniaPluginPersistedstate) //将插件添加到 pinia 实例上 pinia.use(piniaPluginPersistedstate) //将插件添加到 pinia 实例上
pinia.use(shareStorePlugin) // 多窗口数据状态共享
export const store = pinia export const store = pinia

View File

@ -0,0 +1,13 @@
/**
* 工具类-窗口-状态管理
*/
import { defineStore } from 'pinia'
export const useToolState = defineStore('tool', {
state: () => ({
model: 'select', // 悬浮球-当前模式
showBoardAll: false, // 全屏画板-是否显示
}),
actions: {
}
})

View File

@ -24,7 +24,7 @@
</div> </div>
</div> </div>
<!--选择学科--> <!--选择学科-->
<SelectSubject v-model="isSubject" @onSuccess="successEditSubject" /> <SelectSubject v-model="isSubject" :loginData="loginForm" @onSuccess="successEditSubject"/>
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
@ -35,7 +35,7 @@ import leftBg2 from '@/assets/images/login/left-bg2.png'
import WindowTools from '@/components/window-tools/index.vue' import WindowTools from '@/components/window-tools/index.vue'
import SelectSubject from '@/components/select-subject/index.vue' import SelectSubject from '@/components/select-subject/index.vue'
const { BrowserWindow, session } = require('@electron/remote') const { session } = require('@electron/remote')
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
const formRef = ref() const formRef = ref()
@ -48,6 +48,7 @@ const loginForm = reactive({
password: '', password: '',
rememberMe: false rememberMe: false
}) })
// //
const rules = reactive({ const rules = reactive({
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }], username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],

View File

@ -23,7 +23,6 @@
</div> </div>
<!-- 上传弹窗 --> <!-- 上传弹窗 -->
<uploadDialog v-model="isDialogOpen" @submit-file="submitFile" /> <uploadDialog v-model="isDialogOpen" @submit-file="submitFile" />
<!-- <el-button @click="testClick">测试</el-button> -->
</template> </template>
<script setup> <script setup>
@ -35,22 +34,17 @@ import ResoureList from './container/resoure-list.vue'
import uploadDialog from '@/components/upload-dialog/index.vue' import uploadDialog from '@/components/upload-dialog/index.vue'
import uploaderState from '@/store/modules/uploader' import uploaderState from '@/store/modules/uploader'
import { createWindow } from '@/utils/tool' import { createWindow } from '@/utils/tool'
// import { useToolState } from '@/store/modules/tool'
const sourceStore = useResoureStore() const sourceStore = useResoureStore()
const isDialogOpen = ref(false) const isDialogOpen = ref(false)
const toolStore = useToolState()
const openDialog = () => { const openDialog = () => {
isDialogOpen.value = true isDialogOpen.value = true
} }
onMounted(async () => { // onMounted(async () => {
// const params = { url: '/tool/sphere' } // console.log('toolStore: ', toolStore.windowState)
// const res = await ipcMsgSend('tool-sphere:create', params) // })
// console.log('', res)
})
const testClick = async () => {
const win = await createWindow('tool-sphere', { url: '/tool/sphere' })
console.log('消息返回:', win)
}
// //
const getData = (data) => { const getData = (data) => {
const { textBook, node } = data const { textBook, node } = data

View File

@ -1,6 +1,8 @@
<template> <template>
<canvas ref="canvasRef" /> <div>
<slot></slot> <canvas ref="canvasRef" />
<slot></slot>
</div>
</template> </template>
<script setup> <script setup>
// //

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="warp-all"> <div class="warp-all">
<board-vue v-model="tabActive"></board-vue> <board-vue v-model="tabActive" v-show="isShow"></board-vue>
<!-- 底部工具栏 :style="dataPos.style"--> <!-- 底部工具栏 :style="dataPos.style"-->
<div class="tool-bottom-all" <div class="tool-bottom-all"
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)"> @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
@ -27,18 +27,20 @@
<script setup> <script setup>
// electron // electron
import { onMounted, ref, reactive } from 'vue' import { onMounted, ref, reactive, watchEffect } from 'vue'
import logo from '@root/resources/icon.png' // logo import logo from '@root/resources/icon.png' // logo
import boardVue from './components/board.vue' // import boardVue from './components/board.vue' //
import vDrag from './directive/drag' import vDrag from './directive/drag' // -
// const Remote = require('@electron/remote') // remote import { useToolState } from '@/store/modules/tool'
const { ipcRenderer } = require('electron') // app使 const { ipcRenderer } = require('electron') // app使
// const ipcRenderer = { send: () => {} } // 使 // const ipcRenderer = { send: () => {} } // 使
const tabActive = ref('select') // const tabActive = ref('select') //
const isFold = ref(false) // const isFold = ref(false) //
const isDrag = ref(false) // const isDrag = ref(false) //
const dragtime = ref(0) const dragtime = ref(0) // -
const isShow = ref(false)
const toolStore = useToolState()
const btnList = [ // const btnList = [ //
{ label: '选择', value: 'select', icon: 'icon-mouse' }, { label: '选择', value: 'select', icon: 'icon-mouse' },
{ label: '画笔', value: 'brush', icon: 'icon-huabi' }, { label: '画笔', value: 'brush', icon: 'icon-huabi' },
@ -48,9 +50,17 @@ const btnList = [ // 工具栏按钮列表
// { label: '', value: 'focus', icon: 'icon-jujiao' }, // { label: '', value: 'focus', icon: 'icon-jujiao' },
// { label: '', value: 'more', icon: 'icon-xiazai9' }, // { label: '', value: 'more', icon: 'icon-xiazai9' },
] ]
onMounted(() => {
// isShow.value = toolStore.showBoardAll // -
// console.log('xxx: ', toolStore.model)
// setTimeout(() => {
// toolStore.windowState.test = ''
// }, 2000);
})
// ==== === // ==== ===
const tabChange = (val) => { // tab-change const tabChange = (val) => { // tab-change
console.log(val) // console.log('xxxx:', val)
toolStore.showBoardAll = true
switch (val) { switch (val) {
case 'brush': // case 'brush': //
break break
@ -68,6 +78,7 @@ const tabChange = (val) => { // 切换tab-change
default: default:
break break
} }
toolStore.model = val // tab
} }
const logoHandle = (e,t) => { // logo - | const logoHandle = (e,t) => { // logo - |
if (Date.now() - dragtime.value < 200) { if (Date.now() - dragtime.value < 200) {
@ -80,6 +91,9 @@ const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
if (tabActive.value == 'select') resBool = !!bool if (tabActive.value == 'select') resBool = !!bool
ipcRenderer.send('tool-sphere:set:ignore', resBool) ipcRenderer.send('tool-sphere:set:ignore', resBool)
} }
watchEffect(() => { //
isShow.value = toolStore.showBoardAll // -
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>