zhuhao_dev #104
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* 工具类-窗口-状态管理
|
||||||
|
*/
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useToolState = defineStore('tool', {
|
||||||
|
state: () => ({
|
||||||
|
model: 'select', // 悬浮球-当前模式
|
||||||
|
showBoardAll: false, // 全屏画板-是否显示
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
}
|
||||||
|
})
|
|
@ -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: '请输入您的账号' }],
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<canvas ref="canvasRef" />
|
<div>
|
||||||
<slot></slot>
|
<canvas ref="canvasRef" />
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
// 功能说明:画板
|
// 功能说明:画板
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue