Compare commits

...

13 Commits

12 changed files with 155 additions and 82 deletions

View File

@ -28,6 +28,7 @@
"element-plus": "^2.7.6", "element-plus": "^2.7.6",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"lodash": "^4.17.21",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1", "pinia-plugin-persistedstate": "^3.2.1",
"spark-md5": "^3.0.2", "spark-md5": "^3.0.2",

View File

@ -5,7 +5,7 @@ import icon from '../../resources/icon.png?asset'
import File from './file' import File from './file'
File({ app, shell, BrowserWindow, ipcMain }) File({ app, shell, BrowserWindow, ipcMain })
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
let mainWindow, loginWindow let mainWindow, loginWindow
//登录窗口 //登录窗口
@ -24,9 +24,16 @@ function createLoginWindow() {
nodeIntegration: true nodeIntegration: true
} }
}) })
const loginURL = is.dev ? `http://localhost:5173/#/login` : `file://${__dirname}/index.html/login` // handleUpdate(loginWindow,ipcMain)
loginWindow.loadURL(loginURL) // const loginURL = is.dev ? `http://localhost:5173/#/login` : `file://${__dirname}/index.html/#/login`
// loginWindow.loadURL(loginURL)
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
loginWindow.loadURL('http://localhost:5173/#/login')
} else {
loginWindow.loadFile(join(__dirname, '../renderer/index.html'), {hash: 'login'})
}
loginWindow.webContents.openDevTools()
loginWindow.once('ready-to-show', () => { loginWindow.once('ready-to-show', () => {
loginWindow.show() loginWindow.show()
}) })
@ -41,7 +48,7 @@ function createMainWindow() {
width: 1200, width: 1200,
height: 700, height: 700,
show: false, show: false,
frame: false,// 无边框 frame: false, // 无边框
autoHideMenuBar: true, autoHideMenuBar: true,
...(process.platform === 'linux' ? { icon } : {}), ...(process.platform === 'linux' ? { icon } : {}),
webPreferences: { webPreferences: {
@ -61,17 +68,18 @@ function createMainWindow() {
mainWindow.webContents.openDevTools() mainWindow.webContents.openDevTools()
if (is.dev && process.env['ELECTRON_RENDERER_URL']) { if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] )
} else { } else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html')) mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
} }
} }
// 作业窗口相关-开发中 // 作业窗口相关-开发中
let openWindow let linkWindow
function createOpenWin(data) { async function createLinkWin(data) {
if (openWindow) return if (linkWindow) return
openWindow = new BrowserWindow({ linkWindow = new BrowserWindow({
width: 650, width: 650,
height: 500, height: 500,
show: false, show: false,
@ -81,28 +89,32 @@ function createOpenWin(data) {
...(process.platform === 'linux' ? { icon } : {}), ...(process.platform === 'linux' ? { icon } : {}),
webPreferences: { webPreferences: {
sandbox: false, sandbox: false,
nodeIntegration: true nodeIntegration: true,
worldSafeExecuteJavaScript: true,
contextIsolation: true
} }
}) })
let cookieDetails = {...data.cookieData} let cookieDetails = { ...data.cookieData }
openWindow.webContents.session.cookies.set(cookieDetails).then(()=>{ await linkWindow.webContents.session.cookies.set(cookieDetails).then(()=>{
console.log('Cookie set successfully.') console.log('Cookie is successful');
}).catch(err =>{ }).catch( error =>{
console.error('Set cookie failed:', error) console.error('Cookie is error', error);
}) })
openWindow.loadURL(data.fullPath)
openWindow.once('ready-to-show', () => { linkWindow.loadURL(data.fullPath)
openWindow.show()
linkWindow.once('ready-to-show', () => {
linkWindow.show()
linkWindow.maximize()
}) })
openWindow.on('closed', () => { linkWindow.on('closed', () => {
openWindow = null linkWindow = null
}) })
} }
// 初始化完成 // 初始化完成
app.on('ready', () => { app.on('ready', () => {
// 设置应用程序用户模型标识符 // 设置应用程序用户模型标识符
electronApp.setAppUserModelId('com.electron') electronApp.setAppUserModelId('com.electron')
@ -149,16 +161,18 @@ app.on('ready', () => {
createLoginWindow() createLoginWindow()
} }
mainWindow.destroy() mainWindow.destroy()
mainWindow = null
loginWindow.show() loginWindow.show()
loginWindow.focus() loginWindow.focus()
}) })
//打开作业窗口 //打开作业窗口
ipcMain.on('openWork', (e, data) => { ipcMain.on('openWindow', (e, data) => {
createOpenWin(data) createLinkWin(data)
}) })
createLoginWindow() createLoginWindow()
app.on('activate', function () { app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createLoginWindow() if (BrowserWindow.getAllWindows().length === 0) createLoginWindow()
}) })

View File

@ -79,10 +79,6 @@ const subjectList = ref([])
const allSubject = ref([]) const allSubject = ref([])
const dialogVisible = ref(false) const dialogVisible = ref(false)
watch(() => props.modelValue, (newVal) => {
dialogVisible.value = newVal
})
// //
const changeGrade = ()=>{ const changeGrade = ()=>{
// //
@ -120,8 +116,13 @@ const editUserInfo = async () =>{
emit('onSuccess') emit('onSuccess')
} }
watch(() => props.modelValue, (newVal) => {
dialogVisible.value = newVal
if(newVal){
getSubject()
}
})
onMounted(getSubject)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -138,6 +139,7 @@ onMounted(getSubject)
.dialog-content { .dialog-content {
padding: 30px 20px 10px 30px; padding: 30px 20px 10px 30px;
-webkit-app-region: no-drag;
} }
.dialog-footer{ .dialog-footer{

View File

@ -24,7 +24,8 @@
<div class="prepare-body-main-item"> <div class="prepare-body-main-item">
<div class="prepare-uploader-progress" :style="{ width: item.percentage + '%' }"></div> <div class="prepare-uploader-progress" :style="{ width: item.percentage + '%' }"></div>
<div class="prepare-body-main-item-icon"> <div class="prepare-body-main-item-icon">
<svg <FileImage :size="50" :file-name="item.raw.name" />
<!-- <svg
class="icon" class="icon"
aria-hidden="true" aria-hidden="true"
font-size="50px" font-size="50px"
@ -32,7 +33,7 @@
style="margin: auto" style="margin: auto"
> >
<use xlink:href="#icon-ppt"></use> <use xlink:href="#icon-ppt"></use>
</svg> </svg>-->
</div> </div>
<div class="prepare-body-main-item-info"> <div class="prepare-body-main-item-info">
<div class="prepare-item-info-title">{{ item.raw.name }}</div> <div class="prepare-item-info-title">{{ item.raw.name }}</div>
@ -62,10 +63,11 @@ import { getToken } from '@/utils/auth'
// import CryptoJS from 'crypto-js/md5' // import CryptoJS from 'crypto-js/md5'
import SparkMD5 from 'spark-md5' import SparkMD5 from 'spark-md5'
import { DeleteFilled } from '@element-plus/icons-vue' import { DeleteFilled } from '@element-plus/icons-vue'
import FileImage from '@/components/file-image/index.vue'
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
export default { export default {
name: 'Uploader', name: 'Uploader',
components: { DeleteFilled }, components: { DeleteFilled, FileImage },
data() { data() {
return { return {
timer: null, timer: null,

View File

@ -1,9 +0,0 @@
// 作业
export const homeWorkConfig = {
// host 设置token 等
host: 'https://file.ysaix.com:7868',
name: 'Admin-Token',
// 完整路径
fullPath: 'https://file.ysaix.com:7868/teaching/classtaskassign?titleName=%E4%BD%9C%E4%B8%9A%E5%B8%83%E7%BD%AE'
}

View File

@ -0,0 +1,18 @@
import useUserStore from '@/store/modules/user'
import array from 'lodash/array'
export const hasPermission = (value, def = true) => {
// 不传值,默认视为有权限,不做鉴权
if (!value) {
return def
}
const allCodeList = useUserStore().roles
// 如果不是数组直接判断pinia里的权限数组有没有相同的元素即可
if (!Array.isArray(value)) {
return allCodeList.includes(value)
}
// intersection是lodash提供的一个方法用于返回一个所有给定数组都存在的元素组成的数组
return array.intersection(value, allCodeList).length > 0
}

View File

@ -0,0 +1,40 @@
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const baseConfig = {
// Electron 设置cookie
url: 'https://file.ysaix.com:7868',
//cookie 名称 这里为 token
name: 'Admin-Token',
//cookie 值
value: userStore.token,
// 域名
domain: 'file.ysaix.com',
}
// 作业
const homeWork = {
data: { ...baseConfig},
// 完整路径
fullPath: `${baseConfig.url}/teaching/classtaskassign?titleName=%E4%BD%9C%E4%B8%9A%E5%B8%83%E7%BD%AE`
}
// 高考研读
const gk = {
data: { ...baseConfig},
fullPath: `${baseConfig.url}/education/colentrance`
}
// 课标研读
const standard = {
data: { ...baseConfig},
fullPath: `${baseConfig.url}/teaching/chatwithstandard`
}
export default {
homeWork,
gk,
standard
}

View File

@ -31,7 +31,7 @@
</div> </div>
</div> </div>
<!--选择学科--> <!--选择学科-->
<SelectSubject v-model="isSubject" v-if="isSubject" class="select-subject" @onSuccess="successEditSubject" /> <SelectSubject v-model="isSubject" @onSuccess="successEditSubject" />
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
@ -202,7 +202,5 @@ onMounted(()=>{
.el-form-item { .el-form-item {
margin-bottom: 40px; margin-bottom: 40px;
} }
.select-subject{
-webkit-app-region: drag;
}
</style> </style>

View File

@ -7,9 +7,9 @@
<el-image style="width: 80px; height: 110px" :src="curBookImg" /> <el-image style="width: 80px; height: 110px" :src="curBookImg" />
</div> </div>
<div class="top-item"> <div class="top-item">
<el-button class="btn">教材研读</el-button> <el-button class="btn" @click="handleOutLink('standard')">课标研读</el-button>
<el-button class="btn">电子课本</el-button> <el-button class="btn" >电子课本</el-button>
<el-button class="btn">高考研读</el-button> <el-button class="btn" @click="handleOutLink('gk')">高考研读</el-button>
<el-button class="btn">教学大模型</el-button> <el-button class="btn">教学大模型</el-button>
</div> </div>
<el-button type="primary" class="to-class-btn"> <el-button type="primary" class="to-class-btn">
@ -37,7 +37,7 @@
</el-popover> </el-popover>
</div> </div>
<div style="display: flex"> <div style="display: flex">
<el-button @click="handleHomeWork">布置作业</el-button> <el-button @click="handleOutLink('homeWork')">布置作业</el-button>
<el-button @click="isDialogOpen = true">上传资料</el-button> <el-button @click="isDialogOpen = true">上传资料</el-button>
<el-button type="primary" style="margin-left: 10px" @click="createFile">新建课件</el-button> <el-button type="primary" style="margin-left: 10px" @click="createFile">新建课件</el-button>
</div> </div>
@ -73,8 +73,8 @@ import { toTimeText } from '@/utils/date'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { parseCataByNode, creatPPT, asyncLocalFile } from '@/utils/talkFile' import { parseCataByNode, creatPPT, asyncLocalFile } from '@/utils/talkFile'
import FileOperBatch from '@/views/prepare/container/file-oper-batch.vue' import FileOperBatch from '@/views/prepare/container/file-oper-batch.vue'
import useUserStore from '@/store/modules/user'
import { homeWorkConfig } from '@/utils/config' import outLink from '@/utils/linkConfig'
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
export default { export default {
@ -102,7 +102,6 @@ export default {
}, },
// //
curBookImg: '', curBookImg: '',
userStore: ''
} }
}, },
computed: { computed: {
@ -118,7 +117,7 @@ export default {
this.callback(param) this.callback(param)
}) })
this.lastAsyncAllTime = localStorage.getItem('lastAsyncAllTime') this.lastAsyncAllTime = localStorage.getItem('lastAsyncAllTime')
this.userStore = useUserStore()
}, },
mounted() { mounted() {
}, },
@ -251,15 +250,14 @@ export default {
this.uploadData.textbookId = data.textBook.curBookId this.uploadData.textbookId = data.textBook.curBookId
this.asyncAllFile() this.asyncAllFile()
}, },
// //
handleHomeWork(){ handleOutLink(key){
ipcRenderer.send('openWork',{ // key linkConfig.js
fullPath: homeWorkConfig.fullPath, let configObj = outLink[key]
cookieData: { //
url: homeWorkConfig.host, ipcRenderer.send('openWindow', {
name: homeWorkConfig.name, fullPath: configObj.fullPath,
value: this.userStore.token cookieData: {...(configObj.data)}
}
}) })
}, },
} }

View File

@ -8,12 +8,13 @@
}}</el-button> }}</el-button>
</el-col> </el-col>
<el-col :span="12" class="search-box flex"> <el-col :span="12" class="search-box flex">
<el-input v-model="sourceStore.query.fileName" @input="sourceStore.changeName" style="width: 240px" placeholder="请输入关键词" /> <el-input v-model="sourceStore.query.fileName" @input="sourceStore.changeName" style="width: 240px"
placeholder="请输入关键词" />
</el-col> </el-col>
</el-row> </el-row>
<el-row class="resoure-btns"> <el-row class="resoure-btns">
<el-col :span="24" class="query-row flex"> <el-col :span="24" class="query-row flex">
<div class="flex row-left"> <el-select v-model="sourceStore.query.fileSuffix" @change="sourceStore.changeSuffix" <div class="flex row-left"> <el-select v-model="sourceStore.query.fileSuffix" @change="sourceStore.changeSuffix"
style="width: 110px"> style="width: 110px">
<el-option v-for="item in sourceStore.resourceFormatList" :key="item.value" :label="item.label" <el-option v-for="item in sourceStore.resourceFormatList" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
@ -22,7 +23,7 @@
<el-button v-for="item in sourceStore.resourceTypeList" :key="item.id" <el-button v-for="item in sourceStore.resourceTypeList" :key="item.id"
:type="sourceStore.query.fileFlag == item.value ? 'primary' : ''" round :type="sourceStore.query.fileFlag == item.value ? 'primary' : ''" round
@click="sourceStore.changeType(item.value)">{{ @click="sourceStore.changeType(item.value)">{{
item.label }}</el-button> item.label }}</el-button>
</div> </div>
<div> <div>
<slot name="add" /> <slot name="add" />
@ -58,7 +59,8 @@ const sourceStore = useResoureStore()
.query-row { .query-row {
justify-content: space-between; justify-content: space-between;
.row-left{
.row-left {
align-items: center; align-items: center;
} }
} }
@ -70,11 +72,12 @@ const sourceStore = useResoureStore()
margin: 0 10px; margin: 0 10px;
} }
} }
} }
.el-button.is-round{
.el-button.is-round {
padding: 3px 15px; padding: 3px 15px;
font-size: 13px; font-size: 13px;
} }

View File

@ -6,7 +6,7 @@
<div class="page-right"> <div class="page-right">
<!-- 搜索 --> <!-- 搜索 -->
<ResoureSearch #add> <ResoureSearch #add>
<el-button type="primary" round @click="openDialog" class="create-btn"> <el-button v-if="hasPermission(['platformmanager'])" type="primary" round @click="openDialog" class="create-btn">
<i class="iconfont icon-jiahao"></i> <i class="iconfont icon-jiahao"></i>
新建资源</el-button> 新建资源</el-button>
</ResoureSearch> </ResoureSearch>
@ -26,6 +26,7 @@ import ResoureSearch from './container/resoure-search.vue'
import ResoureList from './container/resoure-list.vue' 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 { hasPermission } from '@/utils/hasPermission'
const sourceStore = useResoureStore() const sourceStore = useResoureStore()
const isDialogOpen = ref(false) const isDialogOpen = ref(false)
@ -76,7 +77,6 @@ const submitFile = (data) => {
const fileCallBack = (res) => { const fileCallBack = (res) => {
console.log(res)
if (res.code == 200) { if (res.code == 200) {
sourceStore.handleQuery() sourceStore.handleQuery()
} }

View File

@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { getSmarttalkPage } from '@/api/file/index' import { getSmarttalkPage } from '@/api/file/index'
import { tabs, resourceType, resourceFormat } from '@/utils/resourceDict' import { tabs, resourceType, resourceFormat } from '@/utils/resourceDict'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { hasPermission } from '@/utils/hasPermission'
const userStore = useUserStore() const userStore = useUserStore()
@ -21,10 +22,15 @@ const resourceFormatList = [
] ]
// 校本资源为学校ID // 校本资源为学校ID
tabs.forEach(item =>{ tabs.forEach((item) => {
if( item.label == "校本资源"){ if (item.label == '校本资源') {
item.value = userStore.user.deptId item.value = userStore.user.deptId
} }
})
tabs.forEach((item, i) => {
if (item.label == '平台资源' && !hasPermission(['platformmanager'])) {
tabs.splice(i, 1)
}
}) })
const structQuery = { const structQuery = {
@ -39,14 +45,14 @@ export default defineStore('resource', {
resourceFormatList, resourceFormatList,
searchKey: '', searchKey: '',
//节点数据 //节点数据
nodeData:{}, nodeData: {},
loading: false, loading: false,
//查询条件 //查询条件
query: { query: {
textbookId: '', textbookId: '',
fileSource: '平台', fileSource: tabs[0].value,
//资源格式 mp3 ppt ... //资源格式 mp3 ppt ...
fileSuffix: -1, fileSuffix: -1,
// 资源类型 课件 素材 教案 // 资源类型 课件 素材 教案
@ -66,10 +72,11 @@ export default defineStore('resource', {
handleQuery() { handleQuery() {
try { try {
this.loading = true this.loading = true
let data = {...this.query} let data = { ...this.query }
if(data.fileSuffix == -1){ if (data.fileSuffix == -1) {
data.fileSuffix = '' data.fileSuffix = ''
} }
console.log(data, 200)
getSmarttalkPage(data).then((res) => { getSmarttalkPage(data).then((res) => {
this.result.total = res.total this.result.total = res.total
this.result.list = res.rows this.result.list = res.rows
@ -86,14 +93,13 @@ export default defineStore('resource', {
this.query.fileFlag = val this.query.fileFlag = val
this.handleQuery() this.handleQuery()
}, },
changeSuffix(val){ changeSuffix(val) {
this.query.fileSuffix = val this.query.fileSuffix = val
this.handleQuery() this.handleQuery()
}, },
// 关键词搜索 // 关键词搜索
changeName(){ changeName() {
console.log(this.query.fileName)
this.handleQuery() this.handleQuery()
}, }
} }
}) })