Compare commits

..

No commits in common. "4596ce491136936b5c7ed0f8aa296a1b25213f3e" and "87a50c397f4255b095b45f341214fac894368154" have entirely different histories.

10 changed files with 64 additions and 109 deletions

View File

@ -115,7 +115,7 @@ const outerAi = [
title: '生成图片', title: '生成图片',
secondTit: '文生图大模型', secondTit: '文生图大模型',
img: new URL('../../../src/assets/images/ai-01.png', import.meta.url).href, img: new URL('../../../src/assets/images/ai-01.png', import.meta.url).href,
path: '/ais/aiwenxinyige' path: '/ais/aisd3'
}, },
{ {
id: 2, id: 2,

View File

@ -114,7 +114,6 @@ const emitChangeBook = async () => {
*/ */
let levelFirstId = null let levelFirstId = null
let levelSecondId = null let levelSecondId = null
let bookeId = curBook.data.id
if (curData.parentNode) { if (curData.parentNode) {
levelFirstId = curData.parentNode.id levelFirstId = curData.parentNode.id
levelSecondId = curData.id levelSecondId = curData.id
@ -122,7 +121,7 @@ const emitChangeBook = async () => {
levelFirstId = curData.id levelFirstId = curData.id
levelSecondId = '' levelSecondId = ''
} }
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId})) localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId}))
emit('changeBook', data) emit('changeBook', data)
} }
@ -207,7 +206,6 @@ const handleNodeClick = (data, node) => {
*/ */
let levelFirstId = null let levelFirstId = null
let levelSecondId = null let levelSecondId = null
let bookeId = curBook.data.id
if (nodeData.parentNode) { if (nodeData.parentNode) {
levelFirstId = nodeData.parentNode.id levelFirstId = nodeData.parentNode.id
levelSecondId = nodeData.id levelSecondId = nodeData.id
@ -215,7 +213,7 @@ const handleNodeClick = (data, node) => {
levelFirstId = nodeData.id levelFirstId = nodeData.id
levelSecondId = '' levelSecondId = ''
} }
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId})) localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId}))
emit('nodeClick', curData) emit('nodeClick', curData)
@ -235,7 +233,6 @@ onMounted( async () => {
} }
else{ else{
curBook.data = useSubject.subjectList[0] curBook.data = useSubject.subjectList[0]
localStorage.setItem('curBook', JSON.stringify(curBook.data))
treeData.value = useSubject.treeData treeData.value = useSubject.treeData
} }
// //

View File

@ -102,9 +102,8 @@ const getTreeData = () => {
levelFirstId = curNode.id levelFirstId = curNode.id
levelSecondId = '' levelSecondId = ''
} }
let bookeId = curBookId
// 头部 教材分析、作业设计打开外部链接需要当前章节ID // 头部 教材分析、作业设计打开外部链接需要当前章节ID
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId})) localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId}))
// const data = { // const data = {
// textBook: { // textBook: {

View File

@ -65,7 +65,7 @@
<script setup> <script setup>
import { ref, watch, onMounted } from 'vue' import { ref, watch, onMounted } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { ArrowDown } from '@element-plus/icons-vue' import { ArrowDown } from '@element-plus/icons-vue'
import WindowTools from '@/components/window-tools/index.vue' import WindowTools from '@/components/window-tools/index.vue'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
@ -74,10 +74,6 @@ import outLink from '@/utils/linkConfig'
import logoIco from '@/assets/images/logo.png' import logoIco from '@/assets/images/logo.png'
import { listEvaluation } from '@/api/classManage/index' import { listEvaluation } from '@/api/classManage/index'
import { clearBookInfo } from '@/utils/ruoyi' import { clearBookInfo } from '@/utils/ruoyi'
import { sessionStore } from '@/utils/store'
import { useToolState } from '@/store/modules/tool'
const toolState = useToolState();
let homeTitle = ref(import.meta.env.VITE_APP_TITLE) let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
const userStore = useUserStore() const userStore = useUserStore()
@ -170,8 +166,6 @@ function handleCommand(command) {
} }
function logout() { function logout() {
const hasClass = sessionStore.has('activeClass.id')
if (hasClass || toolState.isToolWin) return ElMessage.warning('当前正在上课,请先结结束上课')
ElMessageBox.confirm('确认退出系统吗?', '提示', { ElMessageBox.confirm('确认退出系统吗?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',

View File

@ -5,8 +5,6 @@ const isNode = typeof require !== 'undefined' // 是否支持node函数
const { ipcRenderer } = isNode?require('electron'):{} // app使用 const { ipcRenderer } = isNode?require('electron'):{} // app使用
import { sessionStore } from '@/utils/store' import { sessionStore } from '@/utils/store'
import CircularJSON from 'circular-json' import CircularJSON from 'circular-json'
import _ from 'lodash'
// import { diff } from 'jsondiffpatch' // import { diff } from 'jsondiffpatch'
// const Remote = isNode?require('@electron/remote'):{} // 远程模块 // const Remote = isNode?require('@electron/remote'):{} // 远程模块
@ -21,14 +19,19 @@ export function shareStorePlugin({store}) {
const storeName = mutation.storeId const storeName = mutation.storeId
// 用于多窗口共享(需要共享的状态名称) // 用于多窗口共享(需要共享的状态名称)
const names = ['tool'] const names = ['tool']
if (names.includes(storeName)) stateSyncWatch(storeName, state) // 需要同步 if (names.includes(storeName)) {
const { storeId: storeName, payload, events, type } = mutation // direct
// if (!Object.keys(payload).length) return
// if (type != 'direct' || !events || Array.isArray(events) || !events.key) return
stateSyncWatch(storeName, state) // 需要同步
}
}) })
// 暴露方法-手动同步 // 暴露方法-手动同步
store.stateSync = (storeName, key, value) => { store.stateSync = (storeName, key, value) => {
const state = store.$state const state = store.$state
if (!storeName && !!key && !!value) stateSync(storeName, key, value, state) if (!storeName && !!key && !!value) stateSync(storeName, key, value, state)
else stateSyncAll(store) else stateSyncAll(store, state)
} }
// 暴露方法-发送当前状态-新窗口 // 暴露方法-发送当前状态-新窗口
store.stateSyncInit = wid => stateSyncInit(wid, store) store.stateSyncInit = wid => stateSyncInit(wid, store)
@ -55,42 +58,21 @@ function stateSync(storeName, key, value, state) {
function stateSyncWatch(storeName, newState) { function stateSyncWatch(storeName, newState) {
const oldState = sessionStore.store // 旧数据 const oldState = sessionStore.store // 旧数据
const diffData = findDifferences(oldState, newState) const diffData = findDifferences(oldState, newState)
if(!_.keys(diffData).length) return // 没有变化就终止执行 // console.log('state-change-diffData', diffData)
// 数据处理: 找出差异
console.log('state-change-diffData', diffData)
try { try {
let pinaValue = {} // store pina状态管理需要的数据格式
// 数据转换处理
for(const key in diffData) { for(const key in diffData) {
const value = diffData[key] || null const value = diffData[key] || null
const newValue = {} // 重新组装pinia需要的数据 {a:{b:1}} 这种 const newValue = {} // 重新组装pinia需要的数据 {a:{b:1}} 这种
const keyArr = key.split('.') || [] const keyArr = key.split('.') || []
keyArr.reduce((o,c,i)=>{o[c] = i === keyArr.length-1 ? value : {};return o[c]}, newValue) keyArr.reduce((o,c,i)=>{o[c] = i === keyArr.length-1 ? value : {};return o[c]}, newValue)
// 合并数据 loadsh _.merge() 函数 const jsonStr = JSON.stringify(newValue) // 从新组装-json数据
_.merge(pinaValue, newValue) // 更新本地数据-session
// console.log('state-change-update:', key, value)
sessionStore.set(key, value)
// 通知主线程更新
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
// console.log('======',key, value, jsonStr )
} }
// 数据处理: electron-store
const [key, value] = _.toPairs(pinaValue)[0] // 对象转换为数组 {a:1} toPairs [['a',1]]
// 无数据就终止执行
if (!key || !value) return
// 更新本地数据-session
// 直接获取当前最新值(整体更新)上面获取到value是差异值并不能知道删除还是新增
const newValAll = _.get(newState, key)
const oldValAll = sessionStore.get(key)
// 没变化也终止执行
if (_.isEqual(oldValAll, newValAll)) return
// 更新本地数据-session
sessionStore.set(key, newValAll)
// 数据处理: pina-store
const jsonStr = JSON.stringify(pinaValue) // 从新组装-json数据
// 通知主线程更新
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
// console.log('======',key, value, jsonStr )
} catch (error) { } catch (error) {
console.log('state-change-error', error) console.log('state-change-error', error)
} }

View File

@ -24,11 +24,10 @@ export const useToolState = defineStore('tool', {
actions: { actions: {
async resetDef() { // 重置数据-下课 async resetDef() { // 重置数据-下课
this.model = 'select' // 悬浮球-当前模式 this.model = 'select' // 悬浮球-当前模式
await sleep(50) // 休眠50ms await sleep(20) // 休眠20ms
this.showBoardAll = false // 全屏画板-是否显示 this.showBoardAll = false // 全屏画板-是否显示
await sleep(50) // 休眠50ms await sleep(20) // 休眠20ms
this.isToolWin = false // 工具窗口是否打开 this.isToolWin = false // 工具窗口是否打开
await sleep(50) // 休眠50ms
} }
} }
}) })

View File

@ -8,7 +8,7 @@
<div class="item-title">{{ item.name }}</div> <div class="item-title">{{ item.name }}</div>
<div class="item-content"> <div class="item-content">
<ul class="flex con-ul"> <ul class="flex con-ul">
<li v-for="menu in item.list" :key="menu.id" @click="clickMenu(menu)" class="flex item-menu" :class="menu.disabled ? 'menu-disabled' : ''"> <li v-for="menu in item.list" @click="clickMenu(menu)" class="flex item-menu" :class="menu.disabled ? 'menu-disabled' : ''">
<i class="iconfont" :class="menu.icon"></i> <i class="iconfont" :class="menu.icon"></i>
<span>{{ menu.name }}</span> <span>{{ menu.name }}</span>
</li> </li>
@ -47,10 +47,13 @@ import outLink from '@/utils/linkConfig'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { useGetClassWork } from '@/hooks/useGetClassWork' import { useGetClassWork } from '@/hooks/useGetClassWork'
const router = useRouter() const router = useRouter()
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
const type = ref(-1)
const chartDom = ref(null); const chartDom = ref(null);
let chartInstance = null let chartInstance = null
const menuList = [{ const menuList = [{
name: '课程教学', name: '课程教学',
span: 24, span: 24,
@ -60,39 +63,38 @@ const menuList = [{
name: '课标分析', name: '课标分析',
icon: 'icon-kecheng', icon: 'icon-kecheng',
isOuter: true, isOuter: true,
path: '/teaching/chatwithstandard', path: '/teaching/chatwithstandard'
id: '1-1'
}, },
{ {
name: '教材分析', name: '教材分析',
icon: 'icon-jiaocaixuanze', icon: 'icon-jiaocaixuanze',
isOuter: true, isOuter: true,
path: '/teaching/chatwithtextbook', path: '/teaching/chatwithtextbook'
id: '1-2'
}, },
{ {
name: '考试分析', name: '考试分析',
icon: 'icon-kaoshi', icon: 'icon-kaoshi',
path: '/examReport', path: '/examReport'
id: '1-3'
}, },
{ {
name: '学情分析', name: '学情分析',
icon: 'icon-xueqingfenxi', icon: 'icon-xueqingfenxi',
disabled: true, disabled: true
id: '1-4'
}, },
// {
// name: '',
// icon: 'icon-jiaoxuesheji',
// path: '/prepare'
// },
{ {
name: '教学实践', name: '教学实践',
icon: 'icon-jiaoxuefenxi', icon: 'icon-jiaoxuefenxi',
path: '/prepare', path: '/prepare'
id: '1-5'
}, },
{ {
name: '教学反思', name: '教学反思',
icon: 'icon-jiaoxuefansi', icon: 'icon-jiaoxuefansi',
disabled: true, disabled: true
id: '1-6'
}, },
] ]
}, },
@ -105,27 +107,27 @@ const menuList = [{
name: '作业设计', name: '作业设计',
icon: 'icon-jiaoxuefansi', icon: 'icon-jiaoxuefansi',
isOuter: true, isOuter: true,
path: '/teaching/classtaskassign?titleName=作业布置&openDialog=newClassTask', path: '/teaching/classtaskassign?titleName=作业布置&openDialog=newClassTask'
id: '2-1' //path: '/newClassTask'
//path: '/classTaskAssign'
//isOuter: true,
//path: '/teaching/classtaskassign?titleName=&&openDialog=newClassTask'
}, },
{ {
name: '作业布置', name: '作业布置',
icon: 'icon-xiezuo1', icon: 'icon-xiezuo1',
isOuter: true, isOuter: true,
path: '/teaching/classtaskassign?titleName=作业布置', path: '/teaching/classtaskassign?titleName=作业布置'
id: '2-2'
}, },
{ {
name: '作业批改', name: '作业批改',
icon: 'icon-pigai', icon: 'icon-pigai',
path: '/classTask', path: '/classTask'
id: '2-3'
}, },
{ {
name: '作业统计', name: '作业统计',
icon: 'icon-tongji', icon: 'icon-tongji',
disabled: true, disabled: true
id: '2-4'
}, },
] ]
}, },
@ -137,47 +139,41 @@ const menuList = [{
{ {
name: '教学计划', name: '教学计划',
icon: 'icon-jiaoxuejihua', icon: 'icon-jiaoxuejihua',
disabled: true, disabled: true
id: '3-1'
}, },
{ {
name: '教学组织', name: '教学组织',
icon: 'icon-organization-framework-line', icon: 'icon-organization-framework-line',
disabled: true, disabled: true
id: '3-2'
}, },
{ {
name: '教学质量', name: '教学质量',
icon: 'icon-jiaoxuezhiliangfenxi', icon: 'icon-jiaoxuezhiliangfenxi',
disabled: true, disabled: true
id: '3-3'
}, },
{ {
name: '教学反馈', name: '教学反馈',
icon: 'icon-fankui', icon: 'icon-fankui',
disabled: true, disabled: true
id: '3-4'
}, },
] ]
} }
] ]
const clickMenu = ({isOuter, path, disabled, id}) =>{ const clickMenu = ({isOuter, path, disabled}) =>{
if(disabled) return if(disabled) return
// //
if(isOuter){ if(isOuter){
let configObj = outLink().getBaseData() let configObj = outLink().getBaseData()
let fullPath = configObj.fullPath + path let fullPath = configObj.fullPath + path
if(id == '1-2' || id == '2-1' || id == '2-2' ){ if(path == '/teaching/classtaskassign?titleName=作业布置&openDialog=newClassTask' || path == '/teaching/classtaskassign?titleName=作业布置'){
// ID // ID
const { levelFirstId, levelSecondId, bookeId } = JSON.parse(localStorage.getItem('unitId')) const { levelFirstId, levelSecondId } = JSON.parse(localStorage.getItem('unitId'))
let unitId = levelSecondId ? levelSecondId : levelFirstId let unitId = levelSecondId ? levelSecondId : levelFirstId
if(fullPath.indexOf('?') == -1){ fullPath = fullPath + `&unitId=${unitId}`
fullPath += `?unitId=${unitId}&bookeId=${bookeId}`
} console.log(fullPath)
else{
fullPath += `&unitId=${unitId}&bookeId=${bookeId}`
}
} }
fullPath = fullPath.replaceAll('//', '/') fullPath = fullPath.replaceAll('//', '/')
// //

View File

@ -208,8 +208,7 @@ export default {
openFileWin(items) { openFileWin(items) {
if (items.fileFlag === 'apt') { if (items.fileFlag === 'apt') {
console.log(this.curNode); console.log(this.curNode);
let curBook = JSON.parse(localStorage.getItem('curBook')) const path="/teaching/aptindex?id="+items.fileId + "&cataId=" + this.curNode.id;
const path="/teaching/aptindex?id="+items.fileId + "&unitId=" + this.curNode.id + "&bookId=" + curBook.id;
let configObj = outLink().getBaseData() let configObj = outLink().getBaseData()
let fullPath = configObj.fullPath + path let fullPath = configObj.fullPath + path
fullPath = fullPath.replaceAll('//', '/') fullPath = fullPath.replaceAll('//', '/')

View File

@ -219,15 +219,15 @@ const sideChange = async o => {
}).then(async() => { }).then(async() => {
await imChatRef.value?.imChatObj?.imChat?.sendMsgClosed() // await imChatRef.value?.imChatObj?.imChat?.sendMsgClosed() //
// const elMsg = ElMessage.warning({duration:0,message:'...'}) // const elMsg = ElMessage.warning({duration:0,message:'...'})
const elMsg = ElLoading.service({lock: true, text: '正在下课...', background: 'rgba(0, 0, 0, 0.7)'}) // const elMsg = ElLoading.service({lock: true, text: '...', background: 'rgba(0, 0, 0, 0.7)'})
// 2 // 2
setTimeout(async() => { setTimeout(async() => {
// elMsg.close()
// toolStore.isToolWin = false // toolStore.isToolWin = false
toolStore.resetDef() // toolStore.resetDef() //
await imChatRef.value?.deleteGroup() // await imChatRef.value?.deleteGroup() //
await imChatRef.value?.logout() // 退im await imChatRef.value?.logout() // 退im
await classManageApi.endClass(route.query.reservId) await classManageApi.endClass(route.query.reservId)
elMsg.close()
ipcMsgSend('tool-sphere:close') // ipcMsgSend('tool-sphere:close') //
}, 500); }, 500);
@ -243,7 +243,6 @@ const sideChange = async o => {
// === === // === ===
watchEffect(() => { watchEffect(() => {
if (isOver.value) return // ,
// , : - // , : -
const show = !toolStore.isPdfWin && toolStore.showBoardAll const show = !toolStore.isPdfWin && toolStore.showBoardAll
if (show != isShow.value) isShow.value = show if (show != isShow.value) isShow.value = show

View File

@ -1,15 +1,9 @@
<template> <template>
<canvas ref="canvasRef" style="pointer-events: none;" /> <canvas ref="canvasRef" />
<div style="position: absolute;top: 0;" @click="test('click')" <button @click="eraseTo">橡皮擦
@mouseenter="test('mouseenter')" @mousemove="test('mousemove')" @mouseleave="test('mouseleave')" <i class="iconfont icon-xiangpica"></i>
@touchstart="test('touchstart')" @touchmove="test('touchmove')" @touchend="test('touchend')" </button>
@touchcancel="test('touchcancel')" @mousedown="test('mousedown')" @mouseup="test('mouseup')" <button @click="close">销毁</button>
@mouseout="test('mouseout')" @mouseover="test('mouseover')" @mousewheel="test('mousewheel')">
<!-- <button @click="eraseTo">橡皮擦</button> -->
<!-- <i class="iconfont icon-xiangpica"></i> -->
<!-- <button @click="close">销毁</button> -->
<div style="width: 100px;height: 100px;background: #ffbcbc;">小星星</div>
</div>
</template> </template>
<script setup> <script setup>
@ -49,10 +43,6 @@ const eraseTo = () => { // 橡皮擦
// canvas.dispose() // canvas.dispose()
} }
const close = () => { FabricVue.removeCanvas() } const close = () => { FabricVue.removeCanvas() }
const test = (key, e) => {
console.log('event: ', key)
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>