Compare commits
13 Commits
ae4f7d3b49
...
6b8c6c8c7f
Author | SHA1 | Date |
---|---|---|
朱浩 | 6b8c6c8c7f | |
zhengdegang | fa5e132c2d | |
zdg | 99c6fe85d4 | |
zdg | 05074f3145 | |
lyc | 34b35d8beb | |
lyc | 921ce6ecb0 | |
lyc | 1be862a0f2 | |
lyc | 9ef553f8eb | |
lyc | e53eab0c31 | |
朱浩 | 1a51af93f6 | |
lyc | 0ba717de6e | |
lyc | 6e29229e95 | |
lyc | df84893509 |
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "electron-app",
|
"name": "aix-win",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"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",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>Electron</title>
|
<title>AIx智慧教育</title>
|
||||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||||
<!-- <meta
|
<!-- <meta
|
||||||
http-equiv="Content-Security-Policy"
|
http-equiv="Content-Security-Policy"
|
||||||
|
|
|
@ -17,3 +17,20 @@ export function listEntpcourse(query) {
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 布置作业
|
||||||
|
export function saveByClassWorkArray(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classwork/saveByClassWorkArray',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除classwork 作业
|
||||||
|
export function delClasswork(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classwork/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
|
@ -158,13 +158,19 @@ const getSubject = async () => {
|
||||||
curBookId.value = subjectList.value[0].id
|
curBookId.value = subjectList.value[0].id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isHaveUnit = (id) => {
|
||||||
|
return evaluationList.value.some(item => {
|
||||||
|
return item.rootid == id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const getTreeData = () => {
|
const getTreeData = () => {
|
||||||
//数据过滤
|
//数据过滤
|
||||||
let upData = transData(volumeOne.value)
|
let upData = transData(volumeOne.value)
|
||||||
let downData = transData(volumeTwo.value)
|
let downData = transData(volumeTwo.value)
|
||||||
treeData.value = upData.length ? upData : downData
|
treeData.value = upData.length ? upData : downData
|
||||||
defaultExpandedKeys.value = [treeData.value[0].id]
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
defaultExpandedKeys.value = [treeData.value[0].id]
|
||||||
currentNodeId.value = getLastLevelData(treeData.value)[0].id
|
currentNodeId.value = getLastLevelData(treeData.value)[0].id
|
||||||
currentNodeName.value = getLastLevelData(treeData.value)[0].label
|
currentNodeName.value = getLastLevelData(treeData.value)[0].label
|
||||||
emitChangeBook()
|
emitChangeBook()
|
||||||
|
|
|
@ -1453,14 +1453,14 @@ export class History {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 清除记录
|
||||||
clean() {
|
clean() {
|
||||||
this.FabricVue?.canvas?.clear()
|
this.FabricVue?.canvas?.clear()
|
||||||
this.index = 0
|
this.index = 0
|
||||||
this.diffs = []
|
this.diffs = []
|
||||||
this.canvasData = {}
|
this.canvasData = {}
|
||||||
}
|
}
|
||||||
|
// 重新加载历史记录
|
||||||
initHistory() {
|
initHistory() {
|
||||||
const canvas = this.FabricVue.canvas
|
const canvas = this.FabricVue.canvas
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ export const createWindow = async (type, data) => {
|
||||||
// parent: mainWin, // 父窗口
|
// parent: mainWin, // 父窗口
|
||||||
// autoClose: true, // 关闭窗口后自动关闭
|
// autoClose: true, // 关闭窗口后自动关闭
|
||||||
}
|
}
|
||||||
// data.isConsole = true // 是否开启控制台
|
data.isConsole = true // 是否开启控制台
|
||||||
data.option = {...defOption, ...option}
|
data.option = {...defOption, ...option}
|
||||||
const win = await toolWindow(data)
|
const win = await toolWindow(data)
|
||||||
win.type = type // 唯一标识
|
win.type = type // 唯一标识
|
||||||
|
@ -145,7 +145,7 @@ export function toolWindow({url, isConsole, option={}}) {
|
||||||
// 内部监听器-是否打印
|
// 内部监听器-是否打印
|
||||||
if (!!isConsole) {
|
if (!!isConsole) {
|
||||||
win.webContents.on('console-message', (e,leve,m,lin,s) => {
|
win.webContents.on('console-message', (e,leve,m,lin,s) => {
|
||||||
console.log('console-msg: ', m)
|
console.log(m)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-popover-item">
|
<div class="item-popover-item">
|
||||||
<el-button text @click="deleteTalk(item)">
|
<el-button text @click="deleteHomework(item)">
|
||||||
<i class="iconfont icon-shanchu"></i>
|
<i class="iconfont icon-shanchu"></i>
|
||||||
<span>删除</span>
|
<span>删除</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -159,7 +159,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: { 'on-move': null, 'on-delete': null, 'on-set': null },
|
emits: { 'on-move': null, 'on-delete': null, 'on-set': null, 'on-delhomework': null },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
listenList: []
|
listenList: []
|
||||||
|
@ -248,6 +248,10 @@ export default {
|
||||||
//布置
|
//布置
|
||||||
setHomeWork(item) {
|
setHomeWork(item) {
|
||||||
this.$emit('on-set', item)
|
this.$emit('on-set', item)
|
||||||
|
},
|
||||||
|
// 删除作业
|
||||||
|
deleteHomework(item){
|
||||||
|
this.$emit('on-delhomework', item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="dialogVisible" center top="10vh" width="600px" :show-close="false"
|
<el-dialog v-model="dialogVisible" center top="10vh" width="600px" :show-close="false" append-to-body
|
||||||
style="border-radius: 10px; padding: 10px 15px;">
|
style="border-radius: 10px; padding: 10px 15px;">
|
||||||
|
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="homerwork-header flex">
|
<div class="homerwork-header flex">
|
||||||
<span>布置作业</span>
|
<span>布置作业</span>
|
||||||
<i class="iconfont icon-guanbi" @click="cloneDialog"></i>
|
<i class="iconfont icon-guanbi" @click="cloneDialog"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div v-loading="setLoading">
|
||||||
<el-form :model="form" label-width="80px">
|
<el-form :model="form" label-width="80px" ref="ruleForm" :rules="rules">
|
||||||
<el-form-item label="班级">
|
<el-form-item label="班级" prop="grade">
|
||||||
<el-tree ref="treeRef" :data="treeData" :props="defaultProps" :load="getLoad" node-key="id"
|
<el-scrollbar max-height="200px" style="width: 100%;">
|
||||||
|
<el-tree ref="treeRef" :data="gradeList" :props="defaultProps" :load="getLoad" node-key="id"
|
||||||
@check="handleCheckChange" lazy show-checkbox />
|
@check="handleCheckChange" lazy show-checkbox />
|
||||||
|
</el-scrollbar>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="选中学生">
|
<el-form-item label="选中学生" prop="student">
|
||||||
<el-scrollbar max-height="200px">
|
<el-scrollbar max-height="200px">
|
||||||
<el-tag v-for="(tag, index) in studentList" :key="tag.studentid" closable type="primary"
|
<el-tag v-for="(tag, index) in studentList" :key="tag.studentid" closable type="primary"
|
||||||
@close="delStudent(index)">
|
@close="delStudent(index)">
|
||||||
|
@ -22,17 +23,17 @@
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="完成要求">
|
<el-form-item label="完成要求" prop="feedback">
|
||||||
<el-radio-group v-model="form.feedtype">
|
<el-radio-group v-model="form.feedback">
|
||||||
<el-radio value="必做" size="large">必做</el-radio>
|
<el-radio value="必做" size="large">必做</el-radio>
|
||||||
<el-radio value="选做" size="large">选做</el-radio>
|
<el-radio value="选做" size="large">选做</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="截至时间">
|
<el-form-item label="截止时间" prop="deaddate">
|
||||||
<el-date-picker v-model="endTime" value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择截至时间"
|
<el-date-picker v-model="form.deaddate" value-format="YYYY-MM-DD HH:mm" format="YYYY-MM-DD HH:mm"
|
||||||
@change="changeTime" />
|
time-format="HH:mm" type="datetime" :clearable="false" placeholder="请选择截止时间" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="推荐用时">
|
<el-form-item label="推荐用时" prop="timelength">
|
||||||
<el-input-number v-model="form.timelength" :min="1" :max="500" />
|
<el-input-number v-model="form.timelength" :min="1" :max="500" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
@ -41,7 +42,7 @@
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="cloneDialog">取消</el-button>
|
<el-button @click="cloneDialog">取消</el-button>
|
||||||
<el-button type="primary" @click="dialogVisible = false">
|
<el-button type="primary" @click="onSubmit('ruleForm')">
|
||||||
确定
|
确定
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,17 +51,27 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
import { listClassmain, listClassgroup } from '@/api/classManage/index'
|
import { listClassmain, listClassgroup } from '@/api/classManage/index'
|
||||||
|
import { saveByClassWorkArray } from '@/api/teaching/classwork'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { uniqBy, cloneDeep } from 'lodash'
|
import { uniqBy, groupBy } from 'lodash'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
entpcourseid: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
|
@ -68,7 +79,7 @@ export default {
|
||||||
label: 'label',
|
label: 'label',
|
||||||
isLeaf: 'leaf',
|
isLeaf: 'leaf',
|
||||||
},
|
},
|
||||||
treeData: [],
|
setLoading: false,
|
||||||
// 用户信息
|
// 用户信息
|
||||||
userInfo: null,
|
userInfo: null,
|
||||||
// 班级列表
|
// 班级列表
|
||||||
|
@ -80,19 +91,26 @@ export default {
|
||||||
studentList: [],
|
studentList: [],
|
||||||
// 表单
|
// 表单
|
||||||
form: {
|
form: {
|
||||||
feedtype: '必做',
|
feedback: '必做',
|
||||||
endTime: '',
|
deaddate: '',
|
||||||
timelength: 1
|
timelength: 1
|
||||||
},
|
},
|
||||||
endTime: ''
|
// 表单规则
|
||||||
|
rules: {
|
||||||
|
grade: [
|
||||||
|
{ validator: this.validateGrade, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
student: [
|
||||||
|
{ validator: this.validateStudent, trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
//截至时间默认值
|
//截至时间默认值
|
||||||
this.endTime = this.getCurrentDate() + ' ' + '10:00:00'
|
this.form.deaddate = this.getCurrentDate() + ' ' + '10:00:00'
|
||||||
this.userInfo = useUserStore().user
|
this.userInfo = useUserStore().user
|
||||||
this.getGradeList()
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 获取班级列表
|
// 获取班级列表
|
||||||
|
@ -104,28 +122,31 @@ export default {
|
||||||
item.level = 0
|
item.level = 0
|
||||||
item.children = []
|
item.children = []
|
||||||
item.classstudentlist = JSON.parse("[" + item.classstudentlist + "]")
|
item.classstudentlist = JSON.parse("[" + item.classstudentlist + "]")
|
||||||
|
item.classstudentlist.forEach(el => {
|
||||||
|
el.classId = item.id
|
||||||
|
})
|
||||||
})
|
})
|
||||||
console.log(list)
|
|
||||||
this.gradeList = list
|
this.gradeList = list
|
||||||
this.treeData = list
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 获取节点下一级
|
||||||
getLoad(node, resolve) {
|
getLoad(node, resolve) {
|
||||||
console.log(node.level)
|
|
||||||
if (node.level == 0) return resolve([])
|
if (node.level == 0) return resolve([])
|
||||||
|
// 获取二级节点 小组
|
||||||
if (node.level == 1) {
|
if (node.level == 1) {
|
||||||
listClassgroup({ classid: node.key, orderby: 'orderidx', pageSize: 100 }).then(res => {
|
listClassgroup({ classid: node.key, orderby: 'orderidx', pageSize: 100 }).then(res => {
|
||||||
console.log(res)
|
|
||||||
if (res.rows.length > 0) {
|
if (res.rows.length > 0) {
|
||||||
let ary = []
|
let ary = []
|
||||||
res.rows.forEach(item => {
|
res.rows.forEach(item => {
|
||||||
if (item.parentid === 0) {
|
if (item.parentid === 0) {
|
||||||
|
//studentGroup 小组学生
|
||||||
let studentGroup = JSON.parse("[" + item.studentlist + "]")
|
let studentGroup = JSON.parse("[" + item.studentlist + "]")
|
||||||
studentGroup.forEach(el => {
|
studentGroup.forEach(el => {
|
||||||
el.label = el.name
|
el.label = el.name
|
||||||
el.leaf = true
|
el.leaf = true
|
||||||
el.level = 2,
|
el.level = 2,
|
||||||
el.id = el.studentid
|
el.id = el.studentid
|
||||||
|
el.classId = item.classid
|
||||||
})
|
})
|
||||||
ary.push({
|
ary.push({
|
||||||
label: item.groupname,
|
label: item.groupname,
|
||||||
|
@ -135,7 +156,6 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// console.log(ary)
|
|
||||||
resolve(ary)
|
resolve(ary)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -143,23 +163,28 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 三级节点 小组学生
|
||||||
if (node.level == 2) {
|
if (node.level == 2) {
|
||||||
resolve(node.data.children)
|
resolve(node.data.children)
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
//节点勾选后触发 拿学生
|
||||||
handleCheckChange(data, checked) {
|
handleCheckChange(data, checked) {
|
||||||
this.studentList = []
|
this.studentList = []
|
||||||
// 选中节点集合
|
// 选中节点集合
|
||||||
let checkNodes = checked.checkedNodes
|
let checkNodes = checked.checkedNodes
|
||||||
let ary = []
|
let ary = []
|
||||||
checkNodes.forEach(item => {
|
checkNodes.forEach(item => {
|
||||||
|
// 一级节点 班级
|
||||||
if (item.level == 0) {
|
if (item.level == 0) {
|
||||||
ary = [...ary, ...(item.classstudentlist)]
|
ary = [...ary, ...(item.classstudentlist)]
|
||||||
}
|
}
|
||||||
|
// 二级节点 班级下面的小组
|
||||||
if (item.level == 1) {
|
if (item.level == 1) {
|
||||||
ary = [...ary, ...(item.children)]
|
ary = [...ary, ...(item.children)]
|
||||||
}
|
}
|
||||||
|
// 三级节点 小组下面的学生
|
||||||
if (item.level == 2) {
|
if (item.level == 2) {
|
||||||
ary = [...ary, item]
|
ary = [...ary, item]
|
||||||
}
|
}
|
||||||
|
@ -170,13 +195,63 @@ export default {
|
||||||
delStudent(index) {
|
delStudent(index) {
|
||||||
this.studentList.splice(index, 1)
|
this.studentList.splice(index, 1)
|
||||||
},
|
},
|
||||||
|
onSubmit(formName) {
|
||||||
|
|
||||||
|
this.$refs[formName].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
/**
|
||||||
|
* 根据学生列表中的classId分班
|
||||||
|
* studentList 为选中的所有学生 这些学生可能来自不同班级
|
||||||
|
*/
|
||||||
|
let gradeObj = groupBy(this.studentList, 'classId')
|
||||||
|
// 处理要提交的参数
|
||||||
|
let ary = []
|
||||||
|
for (const value in gradeObj) {
|
||||||
|
//这些参数 参照AIx web端 作业推送
|
||||||
|
let obj = {
|
||||||
|
id: 0,
|
||||||
|
parentid: this.row.id,
|
||||||
|
classid: value,
|
||||||
|
classcourseid: 0,
|
||||||
|
entpcourseid: this.entpcourseid,
|
||||||
|
studentlist: JSON.stringify(gradeObj[value]),
|
||||||
|
feedback: this.form.feedback,
|
||||||
|
workkey: "",
|
||||||
|
timelength: this.form.timelength,
|
||||||
|
weights: 1,
|
||||||
|
deaddate: this.form.deaddate,
|
||||||
|
workdate: this.getCurrentDate(),
|
||||||
|
uniquekey: this.row.uniquekey,
|
||||||
|
entpcourseworklist: "[" + this.row.entpcourseworklist + "]",
|
||||||
|
needMsgNotifine: 'false',
|
||||||
|
msgkey: 'newclasswork',
|
||||||
|
title: "作业任务",
|
||||||
|
msgcontent: '',
|
||||||
|
teachername: this.userInfo.nickName,
|
||||||
|
unixstamp: new Date().getTime(),
|
||||||
|
}
|
||||||
|
ary.push(obj)
|
||||||
|
}
|
||||||
|
this.setLoading = true
|
||||||
|
saveByClassWorkArray({
|
||||||
|
classworkarray: JSON.stringify(ary)
|
||||||
|
}).then(() => {
|
||||||
|
this.setLoading = false
|
||||||
|
ElMessage.success('操作成功')
|
||||||
|
this.cloneDialog()
|
||||||
|
}).catch(()=>{
|
||||||
|
this.setLoading = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
cloneDialog() {
|
cloneDialog() {
|
||||||
this.$emit('on-close')
|
this.$emit('on-close')
|
||||||
},
|
this.studentList = []
|
||||||
//
|
this.$refs['ruleForm'].resetFields();
|
||||||
changeTime(value) {
|
|
||||||
console.log(value, 100)
|
|
||||||
},
|
},
|
||||||
// 获取当前年月日
|
// 获取当前年月日
|
||||||
getCurrentDate() {
|
getCurrentDate() {
|
||||||
|
@ -185,13 +260,33 @@ export default {
|
||||||
const month = now.getMonth() + 1; // 月份是从0开始的,所以需要+1
|
const month = now.getMonth() + 1; // 月份是从0开始的,所以需要+1
|
||||||
const day = now.getDate()
|
const day = now.getDate()
|
||||||
return `${year}-${month.length == 2 ? month : '0' + month}-${day.length == 2 ? day : '0' + day}`;
|
return `${year}-${month.length == 2 ? month : '0' + month}-${day.length == 2 ? day : '0' + day}`;
|
||||||
|
},
|
||||||
|
validateGrade(rule, value, callback) {
|
||||||
|
if (this.studentList.length == 0) {
|
||||||
|
callback(new Error('请勾选班级或者学生'));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validateStudent(rule, value, callback) {
|
||||||
|
if (this.studentList.length == 0) {
|
||||||
|
callback(new Error('学生不能为空'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue(val) {
|
modelValue(val) {
|
||||||
this.dialogVisible = val
|
this.dialogVisible = val
|
||||||
|
if (val) {
|
||||||
|
this.getGradeList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -212,4 +307,14 @@ export default {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
.dialog-footer{
|
||||||
|
padding-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-checkbox){
|
||||||
|
transform : scale(1.3)
|
||||||
|
}
|
||||||
|
:deep(.el-icon){
|
||||||
|
transform : scale(1.3)
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -65,8 +65,9 @@
|
||||||
@on-move="onMoveSingleFile"
|
@on-move="onMoveSingleFile"
|
||||||
@on-delete="deleteTalk"
|
@on-delete="deleteTalk"
|
||||||
@on-set="openSet"
|
@on-set="openSet"
|
||||||
|
@on-delhomework="delhomework"
|
||||||
>
|
>
|
||||||
<el-checkbox label="" :value="item" />
|
<el-checkbox label="" :value="item" v-if="!item.uniquekey"/>
|
||||||
</file-list-item>
|
</file-list-item>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
<file-oper-batch
|
<file-oper-batch
|
||||||
|
@ -82,7 +83,7 @@
|
||||||
</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" @on-close="closeHomework" />
|
<SetHomework v-model="setDialog" :entpcourseid="entpcourseid" :row="row" @on-close="closeHomework" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -106,6 +107,7 @@ import SetHomework from './container/set-homework.vue'
|
||||||
import outLink from '@/utils/linkConfig'
|
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 } from '@/api/teaching/classwork'
|
||||||
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
|
||||||
|
@ -147,7 +149,8 @@ export default {
|
||||||
entpcourseid: '',
|
entpcourseid: '',
|
||||||
timerId: null,
|
timerId: null,
|
||||||
// 布置作业弹窗
|
// 布置作业弹窗
|
||||||
setDialog: false
|
setDialog: false,
|
||||||
|
row: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -309,9 +312,10 @@ export default {
|
||||||
this.uploadData.textbookId = data.textBook.curBookId
|
this.uploadData.textbookId = data.textBook.curBookId
|
||||||
await this.asyncAllFile()
|
await this.asyncAllFile()
|
||||||
if (this.uploadData.levelSecondId) {
|
if (this.uploadData.levelSecondId) {
|
||||||
// 获取作业列表所需ID
|
// 获取作业列表所需ID 可能存在没有
|
||||||
const res = await this.getChapterId()
|
const { rows } = await this.getChapterId()
|
||||||
this.entpcourseid = res.rows[0].id
|
if(!rows.length) return
|
||||||
|
this.entpcourseid = rows[0].id
|
||||||
// 查询作业
|
// 查询作业
|
||||||
this.getHomeWorkList()
|
this.getHomeWorkList()
|
||||||
}
|
}
|
||||||
|
@ -339,7 +343,7 @@ export default {
|
||||||
pageSize: 500
|
pageSize: 500
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
//
|
// 清除查询作业列表定时器
|
||||||
createTimer() {
|
createTimer() {
|
||||||
this.timerId = setInterval(() => {
|
this.timerId = setInterval(() => {
|
||||||
this.getHomeWorkList()
|
this.getHomeWorkList()
|
||||||
|
@ -412,9 +416,22 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 打开布置作业窗口
|
// 打开布置作业窗口
|
||||||
openSet() {
|
openSet(row) {
|
||||||
|
this.row = row
|
||||||
this.setDialog = true
|
this.setDialog = true
|
||||||
},
|
},
|
||||||
|
// 删除作业
|
||||||
|
delhomework(item){
|
||||||
|
this.isLoading = true
|
||||||
|
delClasswork(item.id).then( async res =>{
|
||||||
|
ElMessage.success('操作成功')
|
||||||
|
this.isLoading = false
|
||||||
|
await this.asyncAllFile()
|
||||||
|
this.getHomeWorkList()
|
||||||
|
}).catch(()=>{
|
||||||
|
this.isLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
closeHomework() {
|
closeHomework() {
|
||||||
this.setDialog = false
|
this.setDialog = false
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,27 +4,28 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
// 功能说明:画板
|
// 功能说明:画板
|
||||||
import { ref, onMounted, watchEffect } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import {FabricVue, TYPES} from '@/plugins/fabric'
|
import {FabricVue, TYPES} from '@/plugins/fabric'
|
||||||
const canvasRef = ref(null) // 画布
|
const canvasRef = ref(null) // 画布
|
||||||
const isMouse = ref(true) // 鼠标是否在画布上
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: String
|
modelValue: String
|
||||||
})
|
})
|
||||||
|
const emit = defineEmits(['update:modelValue'])
|
||||||
// 画板初始化配置
|
// 画板初始化配置
|
||||||
onMounted(async() => {
|
onMounted(async() => {
|
||||||
if (canvasRef.value) {
|
if (canvasRef.value) {
|
||||||
FabricVue.drawConfig.drawColors = ['red']
|
FabricVue.drawConfig.drawColors = ['red']
|
||||||
|
FabricVue.boardConfig.mode = TYPES.ActionMode.OTHER
|
||||||
FabricVue.boardConfig.backgroundColor = 'transparent'
|
FabricVue.boardConfig.backgroundColor = 'transparent'
|
||||||
const option = { freeDrawingCursor: 'default' }
|
const option = { freeDrawingCursor: 'default' }
|
||||||
await FabricVue.initCanvas(canvasRef.value, option)
|
await FabricVue.initCanvas(canvasRef.value, option)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听
|
// 监听
|
||||||
watchEffect(() => {
|
watch(() => props.modelValue, (newVal, oldVal) => {
|
||||||
// console.log('board 画板: ', props.modelValue)
|
// console.log(newVal, oldVal)
|
||||||
isMouse.value = false
|
switch(newVal) {
|
||||||
switch(props.modelValue) {
|
|
||||||
case 'select': // 选择模式
|
case 'select': // 选择模式
|
||||||
FabricVue.handleMode(TYPES.ActionMode.OTHER)
|
FabricVue.handleMode(TYPES.ActionMode.OTHER)
|
||||||
break
|
break
|
||||||
|
@ -35,6 +36,10 @@ watchEffect(() => {
|
||||||
case 'eraser': // 板擦模式
|
case 'eraser': // 板擦模式
|
||||||
FabricVue.handleMode(TYPES.ActionMode.ERASE)
|
FabricVue.handleMode(TYPES.ActionMode.ERASE)
|
||||||
break
|
break
|
||||||
|
case 'clear': // 清空画布
|
||||||
|
FabricVue.history?.clean()
|
||||||
|
emit('update:modelValue', oldVal)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 工具栏-拖拽 自定义指令
|
||||||
|
*/
|
||||||
|
class Drag {
|
||||||
|
isDrag = false // 是否开始拖拽
|
||||||
|
rafId // requestAnimationFrame id
|
||||||
|
x = 0 // 鼠标按下时的x坐标
|
||||||
|
y = 0 // 鼠标按下时的y坐标
|
||||||
|
data // 其他参数 元素实际坐标值
|
||||||
|
el; handle; // el, handle 挂载元素和拖拽元素
|
||||||
|
pos // 拖拽元素实际坐标值
|
||||||
|
max // 拖拽元素最大边界
|
||||||
|
// 构造器
|
||||||
|
constructor(el, binding) {
|
||||||
|
this.el = el
|
||||||
|
const { value } = binding
|
||||||
|
const handleSelector = value instanceof Object ? value.handle : value
|
||||||
|
if (!!handleSelector) {
|
||||||
|
if (handleSelector instanceof HTMLElement) this.handle = handleSelector
|
||||||
|
else {
|
||||||
|
this.handle = document.querySelector(handleSelector)
|
||||||
|
// .forEach((child) => { this.handleArray.push(child) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.handle) this.handle = el // 默认为当前元素
|
||||||
|
// 被拖拽元素初始坐标
|
||||||
|
const pos = this.handle?.getBoundingClientRect()
|
||||||
|
this.data = {left:this.toRound(pos.left), top:this.toRound(pos.top)}
|
||||||
|
this.pos = pos
|
||||||
|
this.max = {w: window.innerWidth, h: window.innerHeight}
|
||||||
|
}
|
||||||
|
// 移入
|
||||||
|
down(e) {
|
||||||
|
this.isDrag = true
|
||||||
|
const {cx, cy} = this.getMousePos(e)
|
||||||
|
this.x = cx
|
||||||
|
this.y = cy
|
||||||
|
// 手动-触发事件 v-drag-start
|
||||||
|
this.el.dispatchEvent(new CustomEvent('v-drag-start', {detail:{drag: this}}))
|
||||||
|
}
|
||||||
|
// 移动过程
|
||||||
|
move = (e) => {
|
||||||
|
if (!this.isDrag) return
|
||||||
|
if (this.rafId) cancelAnimationFrame(this.rafId) // 清除上一次动画
|
||||||
|
this.rafId = requestAnimationFrame(() => this.updatePosition(e))
|
||||||
|
}
|
||||||
|
// 移出
|
||||||
|
up = (e) => {
|
||||||
|
// e.preventDefault(); // 阻止默认行为
|
||||||
|
// e.stopPropagation(); // 阻止事件传播
|
||||||
|
this.isDrag = false
|
||||||
|
cancelAnimationFrame(this.rafId)
|
||||||
|
this.rafId = null
|
||||||
|
document.removeEventListener('mousemove', this.move);
|
||||||
|
document.removeEventListener('mouseup', this.up);
|
||||||
|
document.addEventListener('touchmove', this.move);
|
||||||
|
document.addEventListener('touchend', this.up);
|
||||||
|
}
|
||||||
|
// 业务逻辑
|
||||||
|
updatePosition(e) {
|
||||||
|
const {cx, cy} = this.getMousePos(e)
|
||||||
|
const {left, top} = this.data
|
||||||
|
const dx = cx - this.x
|
||||||
|
const dy = cy - this.y
|
||||||
|
this.x = cx
|
||||||
|
this.y = cy
|
||||||
|
const {x, y} = this.getPos(left + dx, top + dy) // 调用边界函数
|
||||||
|
this.data.left = x // 设置边界-x
|
||||||
|
this.data.top = y // 设置边界-y
|
||||||
|
// console.log(JSON.stringify(this))
|
||||||
|
this.handle.style.left = `${this.data?.left}px`
|
||||||
|
this.handle.style.top = `${this.data?.top}px`
|
||||||
|
this.handle.style.bottom = 'unset'
|
||||||
|
this.handle.style.transform = 'unset'
|
||||||
|
this.rafId = requestAnimationFrame(() => this.updatePosition(e))
|
||||||
|
}
|
||||||
|
// 获取鼠标位置 | Get mouse position
|
||||||
|
getMousePos(e){
|
||||||
|
let cx = e.clientX || e.touches[0].clientX
|
||||||
|
let cy = e.clientY || e.touches[0].clientY
|
||||||
|
cx = this.toRound(cx)
|
||||||
|
cy = this.toRound(cy)
|
||||||
|
return {cx, cy}
|
||||||
|
}
|
||||||
|
// 获取移动后坐标
|
||||||
|
getPos(x, y) {
|
||||||
|
const w = this.max.w - this.toRound(this.el.clientWidth)
|
||||||
|
const h = this.max.h - this.toRound(this.el.clientHeight)
|
||||||
|
x = x < 0 ? 0 : x > w ? w : x
|
||||||
|
y = y < 0 ? 0 : y > h ? h : y
|
||||||
|
return { x, y }
|
||||||
|
}
|
||||||
|
// 小数转整数
|
||||||
|
toRound = v => Math.round(v)
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
mounted(el, binding) {
|
||||||
|
// const { style } = binding.value
|
||||||
|
const drag = new Drag(el, binding)
|
||||||
|
const dragStart = (e) => {
|
||||||
|
drag.down(e)
|
||||||
|
document.addEventListener('mousemove', drag.move);
|
||||||
|
document.addEventListener('mouseup', drag.up);
|
||||||
|
document.addEventListener('touchmove', drag.move);
|
||||||
|
document.addEventListener('touchend', drag.up);
|
||||||
|
}
|
||||||
|
el.addEventListener('mousedown', dragStart)
|
||||||
|
el.addEventListener('touchstart', dragStart)
|
||||||
|
},
|
||||||
|
}
|
|
@ -1,14 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="warp-all">
|
<div class="warp-all">
|
||||||
<board-vue v-model="tabActive"></board-vue>
|
<board-vue v-model="tabActive"></board-vue>
|
||||||
<!-- 底部工具栏 -->
|
<!-- 底部工具栏 :style="dataPos.style"-->
|
||||||
<div ref="tool" class="tool-bottom-all" :style="dataPos.style"
|
<div class="tool-bottom-all"
|
||||||
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
|
||||||
<div @mousedown="e => dargHandle(e,'down')"
|
<div v-drag="{handle:'.tool-bottom-all', dragtime}"
|
||||||
@mousemove="e => dargHandle(e,'move')"
|
@v-drag-start="dragtime = Date.now()">
|
||||||
@mouseup="e => dargHandle(e,'up')">
|
|
||||||
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
|
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
|
||||||
<el-image :src="logo" />
|
<el-image :src="logo" draggable="false" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tool-btns" v-show="!isFold">
|
<div class="tool-btns" v-show="!isFold">
|
||||||
|
@ -16,7 +15,7 @@
|
||||||
@change="tabChange">
|
@change="tabChange">
|
||||||
<template #default="{item}">
|
<template #default="{item}">
|
||||||
<div class="c-btn flex flex-col items-center gap-2 p-2">
|
<div class="c-btn flex flex-col items-center gap-2 p-2">
|
||||||
<i class="iconfont" :class="item.icon"></i>
|
<i class="iconfont" :class="item.icon" :style="item.style"></i>
|
||||||
<span>{{item.label}}</span>
|
<span>{{item.label}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -31,27 +30,27 @@
|
||||||
import { onMounted, ref, reactive } from 'vue'
|
import { onMounted, ref, reactive } 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'
|
||||||
import { tryOnUnmounted } from '@vueuse/core'
|
|
||||||
// const Remote = require('@electron/remote') // remote对象
|
// const Remote = require('@electron/remote') // remote对象
|
||||||
const { ipcRenderer } = require('electron')
|
const { ipcRenderer } = require('electron') // app使用
|
||||||
|
// const ipcRenderer = { send: () => {} } // 网页测试使用
|
||||||
|
|
||||||
const tool = ref()
|
|
||||||
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 dataPos = reactive({style:{}}) // 对象属性
|
const dragtime = ref(0)
|
||||||
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' },
|
||||||
{ label: '板擦', value: 'eraser', icon: 'icon-xiangpica' },
|
{ label: '板擦', value: 'eraser', icon: 'icon-xiangpica' },
|
||||||
{ label: '互动', value: 'interact', icon: 'icon-hudong' },
|
{ label: '清除', value: 'clear', icon: 'icon-xiangpica', style: 'color: #ccc' },
|
||||||
{ label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
// { label: '互动', value: 'interact', icon: 'icon-hudong' },
|
||||||
{ label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
// { label: '聚焦', value: 'focus', icon: 'icon-jujiao' },
|
||||||
|
// { label: '更多', value: 'more', icon: 'icon-xiazai9' },
|
||||||
]
|
]
|
||||||
let offsetX = 0, offsetY = 0, dragtime = 0
|
|
||||||
// ==== 方法 ===
|
// ==== 方法 ===
|
||||||
const tabChange = (val) => { // 切换tab-change
|
const tabChange = (val) => { // 切换tab-change
|
||||||
|
console.log(val)
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 'brush': // 画笔
|
case 'brush': // 画笔
|
||||||
break
|
break
|
||||||
|
@ -71,47 +70,11 @@ const tabChange = (val) => { // 切换tab-change
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const logoHandle = (e,t) => { // logo 点击-事件 折叠|展开
|
const logoHandle = (e,t) => { // logo 点击-事件 折叠|展开
|
||||||
if (Date.now() - dragtime < 200) {
|
if (Date.now() - dragtime.value < 200) {
|
||||||
isFold.value = !isFold.value
|
isFold.value = !isFold.value
|
||||||
}
|
}
|
||||||
console.log('click', isDrag.value)
|
|
||||||
}
|
|
||||||
const dargHandle = (e, type) => { // 拖拽处理
|
|
||||||
e.preventDefault(); // 阻止默认的拖拽行为
|
|
||||||
if (type == 'down') {
|
|
||||||
dragtime = Date.now()
|
|
||||||
return isDrag.value = true
|
|
||||||
} else if (type == 'up') {
|
|
||||||
return isDrag.value = false
|
|
||||||
} else {
|
|
||||||
if (!isDrag.value) return false
|
|
||||||
if (!e.clientX&&!e.clientY){ // 最后一次松开坐标为0
|
|
||||||
offsetX = 0
|
|
||||||
offsetY = 0
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!offsetX&&!offsetY) { // 第一次, 获取元素坐标
|
|
||||||
setStyle()
|
|
||||||
} else {
|
|
||||||
const x = e.clientX - offsetX
|
|
||||||
const y = e.clientY - offsetY
|
|
||||||
setStyle(x, y)
|
|
||||||
}
|
|
||||||
offsetX = e.clientX
|
|
||||||
offsetY = e.clientY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const setStyle = (x, y) => { // 拖拽-设置值
|
|
||||||
if (offsetX && offsetY) { // 有值
|
|
||||||
const {left, top} = dataPos.style
|
|
||||||
const ox = parseInt(left.replace('px',''))
|
|
||||||
const oy = parseInt(top.replace('px',''))
|
|
||||||
dataPos.style = {...dataPos.style, left: ox + x + 'px', top: oy + y + 'px'}
|
|
||||||
} else { // 初始值
|
|
||||||
const {left, top} = tool.value.getBoundingClientRect() // 获取元素位置
|
|
||||||
dataPos.style = {bottom: 'unset', transform:'unset', left: left+'px', top: top+'px'}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
||||||
let resBool = false
|
let resBool = false
|
||||||
if (tabActive.value == 'select') resBool = !!bool
|
if (tabActive.value == 'select') resBool = !!bool
|
||||||
|
@ -153,8 +116,7 @@ const mouseChange = (bool) => { // 鼠标移入工具栏 是否穿透
|
||||||
:deep(.el-segmented__item){
|
:deep(.el-segmented__item){
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 0.5rem;
|
margin: 0 0.5rem;
|
||||||
&:nth-last-child(1):before,
|
&:not(:nth-of-type(1)):before{
|
||||||
&:nth-last-child(2):before{
|
|
||||||
content: "";
|
content: "";
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: calc(100% - 20px);
|
height: calc(100% - 20px);
|
||||||
|
|
Loading…
Reference in New Issue