Merge pull request 'zhuhao_dev' (#109) from zhuhao_dev into main

Reviewed-on: #109
This commit is contained in:
朱浩 2024-08-08 14:05:48 +08:00
commit c56039270c
5 changed files with 205 additions and 124 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "aix-win", "name": "aix-win",
"version": "1.0.4", "version": "1.0.5",
"description": "An Electron application with Vue", "description": "An Electron application with Vue",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "example.com", "author": "example.com",

View File

@ -201,7 +201,8 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
/*创建新的ppt文件*/ /*创建新的ppt文件*/
ipcMain.on('creat-file-default', (e, { name, uploadData, cookie }) => { ipcMain.on('creat-file-default', (e, { name, uploadData, cookie }) => {
createFolder('tempFile').then(() => { createFolder('tempFile').then(() => {
let path = appTempFilePath + name let path = appTempFilePath + name.replace(/[\\/:*?"<>|]/, '')
console.log(path)
fs.writeFileSync(path, '', 'utf-8') fs.writeFileSync(path, '', 'utf-8')
let fileType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation' let fileType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
let formData = new FormData() let formData = new FormData()
@ -237,7 +238,8 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
//下载文件 //下载文件
ipcMain.on('download-file-default', (e, { url, fileName }) => { ipcMain.on('download-file-default', (e, { url, fileName }) => {
createFolder('selfFile').then(async () => { createFolder('selfFile')
.then(async () => {
const browserWindow = BrowserWindow.getFocusedWindow() const browserWindow = BrowserWindow.getFocusedWindow()
const id = await manager.download({ const id = await manager.download({
window: browserWindow, window: browserWindow,
@ -268,6 +270,9 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
} }
}) })
}) })
.catch((error) => {
e.reply('download-file-default' + fileName, false)
})
}) })
/**... /**...

View File

@ -73,6 +73,7 @@ const handleOutLink = (path, type) => {
fullPath = fullPath.replaceAll('//', '/') fullPath = fullPath.replaceAll('//', '/')
// //
ipcRenderer.send('openWindow', { ipcRenderer.send('openWindow', {
key: path,
fullPath: fullPath, fullPath: fullPath,
cookieData: { ...configObj.data } cookieData: { ...configObj.data }
}) })

View File

@ -4,20 +4,28 @@
class="reserv-dialog" class="reserv-dialog"
title="预约课程" title="预约课程"
destroy-on-close destroy-on-close
:before-close="closeDialog"
width="600" width="600"
style="text-align: left" style="text-align: left"
> >
<el-form :model="form" label-width="auto" style="max-width: 600px"> <el-form
<el-form-item label="课程名称"> ref="ruleFormDialog"
:model="form"
:rules="ruleForm"
label-width="auto"
style="max-width: 600px"
>
<el-form-item label="课程名称" prop="name">
<el-input v-model="form.name" /> <el-input v-model="form.name" />
</el-form-item> </el-form-item>
<el-form-item label="课程类型" prop="location"> <el-form-item label="课程类型" prop="type">
<el-segmented v-model="form.type" :block="false" :options="locationOptions" /> <el-segmented v-model="form.type" :block="false" :options="locationOptions" />
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;" prop="location"> <el-form-item label="&nbsp;">
<div>{{ locationMessage }}</div> <div>{{ locationMessage }}</div>
</el-form-item> </el-form-item>
<el-form-item label="上课时间"> <el-form-item label="上课时间">
<el-form-item prop="day">
<el-col :span="6"> <el-col :span="6">
<el-date-picker <el-date-picker
v-model="form.day" v-model="form.day"
@ -29,15 +37,18 @@
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
/> />
</el-col> </el-col>
</el-form-item>
<el-col :span="2" class="text-center"> <el-col :span="2" class="text-center">
<span class="text-gray-500">-</span> <span class="text-gray-500">-</span>
</el-col> </el-col>
<el-form-item prop="time">
<el-col :span="11"> <el-col :span="11">
<el-time-picker <el-time-picker
v-model="form.time" v-model="form.time"
is-range is-range
:editable="false" :editable="false"
format="HH:mm" format="HH:mm"
value-format="HH:mm"
class="reserv-time-pick" class="reserv-time-pick"
range-separator="-" range-separator="-"
start-placeholder="开始时间" start-placeholder="开始时间"
@ -45,19 +56,22 @@
/> />
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="授课对象">
<el-radio-group v-model="form.resource">
<el-radio v-for="(item, index) in classList" :key="index" :value="item.id">{{item.caption}}({{item.classstudentcount}})</el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="教室"> <el-form-item label="授课对象" prop="resource">
<el-checkbox-group v-model="form.resource">
<el-checkbox v-for="(item, index) in classList" :key="index" name="type" :value="item.id"
>{{ item.caption }}({{ item.classstudentcount }})
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="教室" prop="classRoom">
<el-input v-model="form.classRoom" /> <el-input v-model="form.classRoom" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="centerDialogVisible = false">取消</el-button> <el-button @click="centerDialogVisible = false">取消</el-button>
<el-button type="primary" @click="centerDialogVisible = false"> 提交 </el-button> <el-button type="primary" @click="submitForm"> 提交 </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -66,17 +80,24 @@
import { ref, defineExpose, onMounted, reactive, computed } from 'vue' import { ref, defineExpose, onMounted, reactive, computed } from 'vue'
import { listClassmain } from '@/api/classManage' import { listClassmain } from '@/api/classManage'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
const ruleFormDialog = ref(null)
const userStore = useUserStore().user const userStore = useUserStore().user
const centerDialogVisible = ref(false) const centerDialogVisible = ref(false)
const form = reactive({ const form = reactive({
name: '', name: '',
type: '常规课', type: '常规课',
delivery: false, day: '',
day:'', time: '',
time:'', resource: [],
resource: '',
classRoom: '' classRoom: ''
}) })
const ruleForm = reactive({
name: [{ required: true, message: '请输入课程名称', trigger: 'blur' }],
day: [{ required: true, message: '请选择上课日期', trigger: 'change' }],
time: [{ required: true, message: '请选择上课时间', trigger: 'change' }],
classRoom: [{ required: false, message: '请选择上课时间', trigger: 'change' }],
resource: [{ required: true, message: '请选择授课对象', trigger: 'change' }]
})
const locationOptions = [ const locationOptions = [
{ {
label: '常规课', label: '常规课',
@ -85,9 +106,9 @@ const locationOptions = [
message: '现场公屏授课,学生无需长时间打开平板上。' message: '现场公屏授课,学生无需长时间打开平板上。'
}, },
{ {
label: '公开课', label: '互动课',
value: '公开课', value: '互动课',
disabled: true, disabled: false,
message: '现场公屏授课,学生需打开平开与老师进行互动,如点赞、互动作业。' message: '现场公屏授课,学生需打开平开与老师进行互动,如点赞、互动作业。'
}, },
{ {
@ -104,6 +125,7 @@ const openDialog = () => {
centerDialogVisible.value = true centerDialogVisible.value = true
} }
const closeDialog = () => { const closeDialog = () => {
ruleFormDialog.value.resetFields()
centerDialogVisible.value = false centerDialogVisible.value = false
} }
const classList = ref([]) const classList = ref([])
@ -114,6 +136,15 @@ onMounted(() => {
} }
) )
}) })
const submitForm = async () => {
const formEl = ruleFormDialog.value
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
centerDialogVisible.value = false
}
})
}
defineExpose({ defineExpose({
openDialog, openDialog,
closeDialog closeDialog

View File

@ -13,7 +13,8 @@
<el-button class="btn" @click="handleOutLink('aiModel')">教学大模型</el-button> <el-button class="btn" @click="handleOutLink('aiModel')">教学大模型</el-button>
</div> </div>
<el-button type="primary" class="to-class-btn" @click="openLesson"> <el-button type="primary" class="to-class-btn" @click="openLesson">
<i class="iconfont icon-lingdang"></i>上课</el-button> <i class="iconfont icon-lingdang"></i>上课</el-button
>
<div class="top-zoom-style"></div> <div class="top-zoom-style"></div>
</div> </div>
<div class="prepare-body-header"> <div class="prepare-body-header">
@ -22,7 +23,13 @@
<el-popover placement="top-start" :width="250" trigger="hover"> <el-popover placement="top-start" :width="250" trigger="hover">
<template #default> <template #default>
<div> <div>
<el-button v-if="lastAsyncAllTime" type="success" size="small" :icon="Check" circle /> <el-button
v-if="lastAsyncAllTime"
type="success"
size="small"
:icon="Check"
circle
/>
{{ lastAsyncAllTime ? toTimeText(lastAsyncAllTime) + '同步成功' : '' }} {{ lastAsyncAllTime ? toTimeText(lastAsyncAllTime) + '同步成功' : '' }}
</div> </div>
</template> </template>
@ -40,24 +47,60 @@
<el-button @click="handleOutLink('feedback')">作业反馈</el-button> <el-button @click="handleOutLink('feedback')">作业反馈</el-button>
<el-button @click="handleOutLink('homeWork')">布置作业</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>
</div> </div>
<el-checkbox-group v-model="checkFileList" class="prepare-body-main" <el-checkbox-group
:style="{ 'margin-bottom': checkFileList.length > 0 ? '40px' : '0' }"> v-model="checkFileList"
<file-list-item v-for="(item, index) in currentFileList" :key="index" :item="item" :index="index" class="prepare-body-main"
@on-move="onMoveSingleFile" @on-delete="deleteTalk" @on-set="openSet" @on-delhomework="delhomework"> :style="{ 'margin-bottom': checkFileList.length > 0 ? '40px' : '0' }"
<el-checkbox label="" :value="item" v-if="!item.uniquekey" /> >
<file-list-item
v-for="(item, index) in currentFileList"
:key="index"
:item="item"
:index="index"
@on-move="onMoveSingleFile"
@on-delete="deleteTalk"
@on-set="openSet"
@on-delhomework="delhomework"
>
<el-checkbox v-if="!item.uniquekey" label="" :value="item" />
</file-list-item>
<file-list-item
v-for="(item, index) in currentWorkList"
:key="'work_' + index"
:item="item"
:index="index"
@on-move="onMoveSingleFile"
@on-delete="deleteTalk"
@on-set="openSet"
@on-delhomework="delhomework"
>
<el-checkbox v-if="!item.uniquekey" label="" :value="item" />
</file-list-item> </file-list-item>
</el-checkbox-group> </el-checkbox-group>
<file-oper-batch v-show="checkFileList.length > 0" <file-oper-batch
v-show="checkFileList.length > 0"
:indeterminate="checkFileList.length > 0 && checkFileList.length < currentFileList.length" :indeterminate="checkFileList.length > 0 && checkFileList.length < currentFileList.length"
:choose="checkFileList" :check-all="isCheckAll" @click-delete="clickDelete" @click-move="clickMove" :choose="checkFileList"
@cancel="checkFileList = []" @click-choose="clickChoose"></file-oper-batch> :check-all="isCheckAll"
@click-delete="clickDelete"
@click-move="clickMove"
@cancel="checkFileList = []"
@click-choose="clickChoose"
></file-oper-batch>
</div> </div>
<MoveFile v-model="isMoveDialogOpen" @on-submit="chooseMoveCata" /> <MoveFile v-model="isMoveDialogOpen" @on-submit="chooseMoveCata" />
<uploadDialog v-model="isDialogOpen" @submit-file="submitFile" /> <uploadDialog v-model="isDialogOpen" @submit-file="submitFile" />
<SetHomework v-model="setDialog" :entpcourseid="entpcourseid" :row="row" @on-close="closeHomework" /> <SetHomework
v-model="setDialog"
:entpcourseid="entpcourseid"
:row="row"
@on-close="closeHomework"
/>
</div> </div>
<reserv ref="reservDialog"></reserv> <reserv ref="reservDialog"></reserv>
</template> </template>
@ -86,7 +129,7 @@ import outLink from '@/utils/linkConfig'
import { createWindow } from '@/utils/tool' import { createWindow } from '@/utils/tool'
import { uniqBy, cloneDeep } from 'lodash' import { uniqBy, cloneDeep } from 'lodash'
import { delClasswork, addEntpcourse } from '@/api/teaching/classwork' import { delClasswork, addEntpcourse } from '@/api/teaching/classwork'
const fs = require('fs'); const fs = require('fs')
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
export default { export default {
@ -112,6 +155,7 @@ export default {
fileList: [], fileList: [],
currentNode: {}, currentNode: {},
currentFileList: [], currentFileList: [],
currentWorkList: [],
curBookPath: '', curBookPath: '',
lastAsyncAllTime: '', lastAsyncAllTime: '',
uploadData: { uploadData: {
@ -155,7 +199,7 @@ export default {
}) })
this.lastAsyncAllTime = localStorage.getItem('lastAsyncAllTime') this.lastAsyncAllTime = localStorage.getItem('lastAsyncAllTime')
}, },
mounted() { }, mounted() {},
activated() { activated() {
if (this.uploadData.textbookId !== null) { if (this.uploadData.textbookId !== null) {
this.asyncAllFile() this.asyncAllFile()
@ -167,7 +211,7 @@ export default {
let fileName = this.curBookPath let fileName = this.curBookPath
if (!fileName) return if (!fileName) return
fileName = fileName.replace('.txt', '.pdf') fileName = fileName.replace('.txt', '.pdf')
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject) => {
const userDataPath = Remote.app.getPath('userData') const userDataPath = Remote.app.getPath('userData')
const appRootFilePath = userDataPath + '\\selfFile\\' const appRootFilePath = userDataPath + '\\selfFile\\'
let filePath = appRootFilePath + fileName let filePath = appRootFilePath + fileName
@ -182,14 +226,14 @@ export default {
ipcRenderer.once('download-file-default' + fileName, (e, isSuccess) => { ipcRenderer.once('download-file-default' + fileName, (e, isSuccess) => {
if (isSuccess === true) { if (isSuccess === true) {
resolve(appRootFilePath + fileName) resolve(appRootFilePath + fileName)
}else { } else {
ElMessage({ ElMessage({
type: 'info', type: 'info',
message: `下载教材失败!` message: `下载教材失败!`
}) })
} }
}) })
}else { } else {
resolve(appRootFilePath + fileName) resolve(appRootFilePath + fileName)
} }
}) })
@ -314,7 +358,6 @@ export default {
}) })
}, },
async nodeClick(data) { async nodeClick(data) {
console.log(data)
if (this.currentNode.id === data.node.id) return if (this.currentNode.id === data.node.id) return
this.curBookImg = data.textBook.curBookImg this.curBookImg = data.textBook.curBookImg
this.curBookPath = data.textBook.curBookPath this.curBookPath = data.textBook.curBookPath
@ -327,9 +370,9 @@ export default {
this.uploadData.textbookId = data.textBook.curBookId this.uploadData.textbookId = data.textBook.curBookId
this.initHomeWork() this.initHomeWork()
await this.asyncAllFile() await this.asyncAllFile()
}, },
async initHomeWork() { async initHomeWork() {
this.currentWorkList = []
if (this.timerId) { if (this.timerId) {
clearInterval(this.timerId) clearInterval(this.timerId)
} }
@ -338,8 +381,7 @@ export default {
let { rows } = await this.getChapterId() let { rows } = await this.getChapterId()
if (rows.length > 0) { if (rows.length > 0) {
this.entpcourseid = rows[0].id this.entpcourseid = rows[0].id
} } else {
else{
await this.createEntpcourse() await this.createEntpcourse()
let { rows } = await this.getChapterId() let { rows } = await this.getChapterId()
this.entpcourseid = rows[0].id this.entpcourseid = rows[0].id
@ -351,27 +393,27 @@ export default {
}, },
// entpcourse // entpcourse
createEntpcourse() { createEntpcourse() {
var cform = {}; var cform = {}
cform.entpid = this.userStore.deptId; cform.entpid = this.userStore.deptId
cform.level = 1; cform.level = 1
cform.parentid = 0; cform.parentid = 0
cform.dictid = 0; cform.dictid = 0
cform.evalid = this.currentNode.id; cform.evalid = this.currentNode.id
cform.evalparentid = 0; cform.evalparentid = 0
cform.edusubject = this.currentNode.edusubject; cform.edusubject = this.currentNode.edusubject
cform.edudegree = this.currentNode.edudegree; cform.edudegree = this.currentNode.edudegree
cform.edustage = this.currentNode.edustage; cform.edustage = this.currentNode.edustage
cform.coursetype = '课标学科'; cform.coursetype = '课标学科'
cform.coursetitle = this.currentNode.itemtitle; cform.coursetitle = this.currentNode.itemtitle
cform.coursedesc = ''; cform.coursedesc = ''
cform.status = ''; cform.status = ''
cform.dflag = 0; cform.dflag = 0
cform.edituserid = this.userStore.userId; cform.edituserid = this.userStore.userId
cform.createblankfile = 'yes'; cform.createblankfile = 'yes'
return addEntpcourse(cform) return addEntpcourse(cform)
}, },
openReserv(){ openReserv() {
// this.$refs['reservDialog'].openDialog() this.$refs['reservDialog'].openDialog()
}, },
// //
handleOutLink(key) { handleOutLink(key) {
@ -463,9 +505,9 @@ export default {
} }
} }
// //
let ary = uniqBy([...this.currentFileList, ...list], 'id') let ary = uniqBy([...list], 'id')
// //
this.currentFileList = cloneDeep(ary) this.currentWorkList = cloneDeep(ary)
}) })
}, },
// //
@ -476,12 +518,14 @@ export default {
// //
delhomework(item) { delhomework(item) {
this.isLoading = true this.isLoading = true
delClasswork(item.id).then(async res => { delClasswork(item.id)
.then(async (res) => {
ElMessage.success('操作成功') ElMessage.success('操作成功')
this.isLoading = false this.isLoading = false
await this.asyncAllFile() await this.asyncAllFile()
this.getHomeWorkList() this.getHomeWorkList()
}).catch(() => { })
.catch(() => {
this.isLoading = false this.isLoading = false
}) })
}, },