Compare commits

..

89 Commits
2.0.0 ... main

Author SHA1 Message Date
朱浩 27c7033522 Merge pull request 'yangws' (#249) from yangws into main
Reviewed-on: #249
2024-09-22 16:47:12 +08:00
朱浩 4c66cc90c0 BUG修复 2024-09-22 16:46:37 +08:00
lyc c2b54714ac Merge pull request '跳转增加bookid' (#248) from lyc-dev into main 2024-09-22 16:41:45 +08:00
lyc cafea2d719 跳转增加bookid 2024-09-22 16:41:49 +08:00
yangws d5afede36c fix:2.0.4bug修改; 2024-09-22 16:28:10 +08:00
朱浩 03e61c8440 Merge pull request '打包联通文枢课堂' (#247) from zhuhao_dev into main
Reviewed-on: #247
2024-09-22 14:28:29 +08:00
朱浩 79b9a0726a 打包联通文枢课堂 2024-09-22 14:27:48 +08:00
朱浩 0ccde18f00 Merge pull request 'zhuhao_dev' (#246) from zhuhao_dev into main
Reviewed-on: #246
2024-09-22 14:02:32 +08:00
朱浩 274c80ad0a Merge branch 'main' into zhuhao_dev 2024-09-22 14:02:02 +08:00
yangws 923006eab1 Merge pull request 'fix:2.0.4bug修改;' (#245) from yangws into main
Reviewed-on: #245
2024-09-22 12:52:53 +08:00
yangws a64ba24742 fix:2.0.4bug修改; 2024-09-22 12:51:58 +08:00
lyc df1f8737bd Merge pull request '点击章节 存储章节id (临时)' (#244) from lyc-dev into main 2024-09-22 12:34:16 +08:00
lyc 19a3b948c5 点击章节 存储章节id (临时) 2024-09-22 12:34:15 +08:00
朱浩 622cdfe0fe BUG修复 #811,V2.0.3 APT设计-添加活动,与当前选择的章节不一致 2024-09-22 11:14:19 +08:00
朱浩 78b795bf4f BUG修复 #801,V2.0.3 教学实践-作业,红框部分去掉 2024-09-22 10:53:23 +08:00
lyc 92667a7d25 Merge pull request '注册账号-班级修改为可选' (#243) from lyc-dev into main 2024-09-22 10:38:38 +08:00
lyc 71f7e4e5a1 注册账号-班级修改为可选 2024-09-22 10:38:31 +08:00
朱浩 3cced30959 Merge branch 'main' into zhuhao_dev 2024-09-20 16:56:44 +08:00
朱浩 ef9fe838a3 BUG修复 2024-09-20 16:56:26 +08:00
zhangxuelin 9ff824e082 Merge pull request '修改工具拖动' (#242) from zdg into main
Reviewed-on: #242
2024-09-20 16:27:54 +08:00
zhangxuelin 8975784ce0 修改工具拖动 2024-09-20 16:27:12 +08:00
lyc e586755b75 Merge pull request 'edit' (#241) from lyc-dev into main 2024-09-20 15:38:39 +08:00
lyc ef771f4e0b edit 2024-09-20 15:38:37 +08:00
朱浩 049768c8b6 Merge pull request 'BUG修复' (#240) from zhuhao_dev into main
Reviewed-on: #240
2024-09-20 15:29:56 +08:00
朱浩 ac599a2c39 BUG修复 2024-09-20 15:29:21 +08:00
lyc 00871797bf edit 2024-09-20 15:24:23 +08:00
lyc fa7a44472b Merge pull request 'edit' (#239) from lyc-dev into main 2024-09-20 15:24:19 +08:00
lyc 85529ad81f Merge pull request 'edit' (#238) from lyc-dev into main 2024-09-20 15:20:27 +08:00
lyc f9a87143aa edit 2024-09-20 15:19:33 +08:00
zhengdegang 17ef183741 Merge pull request 'zdg' (#237) from zdg into main
Reviewed-on: #237
2024-09-20 15:17:16 +08:00
zdg d5833f6f03 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into zdg 2024-09-20 15:16:43 +08:00
zdg c93eeeb308 修复异常 2024-09-20 15:16:34 +08:00
zhengdegang 0d48111e50 Merge pull request '解决 值为null问题' (#236) from zdg into main
Reviewed-on: #236
2024-09-20 15:06:33 +08:00
zdg ca57e72e9c 解决 值为null问题 2024-09-20 15:04:14 +08:00
zhengdegang 928a1401db Merge pull request 'zdg' (#235) from zdg into main
Reviewed-on: #235
2024-09-20 14:57:41 +08:00
zdg e0d3a6da6a Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into zdg 2024-09-20 14:56:54 +08:00
zdg 1a9b426ec3 修复-上课 提示 2024-09-20 14:56:48 +08:00
lyc d4cfedf883 Merge pull request 'lyc-dev' (#234) from lyc-dev into main 2024-09-20 14:43:21 +08:00
lyc b5fd1f2a9d edit 2024-09-20 14:42:58 +08:00
lyc c6477d5ca9 edit 2024-09-20 14:34:22 +08:00
lyc 27ec047981 edit 教材选择 2024-09-20 14:30:36 +08:00
zhengdegang 7da4defed4 Merge pull request 'zdg' (#233) from zdg into main
Reviewed-on: #233
2024-09-20 13:54:51 +08:00
zdg 51cb1989a1 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into zdg 2024-09-20 13:53:53 +08:00
zdg 4ab4d5dff2 恢复修改 2024-09-20 13:53:42 +08:00
lyc 80d6e1c59c Merge pull request 'edit' (#232) from lyc-dev into main 2024-09-20 13:41:22 +08:00
lyc 75c6777933 edit 2024-09-20 13:41:18 +08:00
朱浩 a75f151b19 Merge pull request 'BUG修复' (#231) from zhuhao_dev into main
Reviewed-on: #231
2024-09-20 09:22:02 +08:00
朱浩 2531c25d7c BUG修复 2024-09-20 09:21:31 +08:00
朱浩 9e5527d822 Merge pull request 'zhuhao_dev' (#230) from zhuhao_dev into main
Reviewed-on: #230
2024-09-20 09:19:10 +08:00
朱浩 e002ef5f7d Merge branch 'main' into zhuhao_dev 2024-09-20 09:18:30 +08:00
朱浩 2ca637072d BUG修复 2024-09-20 09:18:12 +08:00
baigl bd7f6f765f Merge pull request 'baigl' (#229) from baigl into main
Reviewed-on: #229
2024-09-19 16:58:13 +08:00
白了个白 ef6c3d2a2b Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into baigl 2024-09-19 16:57:03 +08:00
白了个白 9ea05568e1 作业批改:同步web端164逻辑修改 2024-09-19 16:56:15 +08:00
zhengdegang 93a061ca78 Merge pull request 'zdg' (#228) from zdg into main
Reviewed-on: #228
2024-09-19 16:37:45 +08:00
zdg c5075af2fc 已上课 2024-09-19 16:37:07 +08:00
zdg 7da60f0815 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into zdg 2024-09-19 16:35:43 +08:00
zdg 02a25db5e2 修复 2024-09-19 16:35:36 +08:00
yangws 59de30b6b2 Merge pull request 'fix: 解决空数据的判断;' (#227) from yangws into main
Reviewed-on: #227
2024-09-19 16:03:39 +08:00
yangws 746cb150c4 fix: 解决空数据的判断; 2024-09-19 16:02:56 +08:00
lyc 893be27671 切换学科 2024-09-19 16:02:42 +08:00
lyc b0b429c7aa Merge pull request '切换学科' (#226) from lyc-dev into main 2024-09-19 16:02:41 +08:00
lyc dbfa1a4037 Merge pull request '路由title' (#225) from lyc-dev into main 2024-09-19 15:55:19 +08:00
lyc ce8b2e6ab0 路由title 2024-09-19 15:55:19 +08:00
baigl a082b437b7 Merge pull request 'baigl' (#224) from baigl into main
Reviewed-on: #224
2024-09-19 15:32:32 +08:00
白了个白 9eb6d991c1 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into baigl 2024-09-19 15:31:45 +08:00
白了个白 0cbb513a60 作业批改:常规作业ui修改 2024-09-19 15:29:52 +08:00
lyc be765b21b6 Merge pull request 'lyc-dev' (#223) from lyc-dev into main 2024-09-19 15:15:26 +08:00
lyc 34c1c66b31 edit 教材 2024-09-19 15:15:16 +08:00
lyc 5f06657b09 教学实践 2024-09-19 14:58:54 +08:00
白了个白 3ec25f07b4 作业批改:接口传参未传状态值bug修改 2024-09-19 14:25:33 +08:00
zhengdegang aa35621b59 Merge pull request 'zdg' (#222) from zdg into main
Reviewed-on: #222
2024-09-19 12:03:47 +08:00
zdg 49de9ee9c2 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into zdg 2024-09-19 12:02:51 +08:00
zdg 0ef5ef424f bug修复,以及代码优化 2024-09-19 12:02:31 +08:00
baigl 89ae43a458 Merge pull request 'baigl' (#221) from baigl into main
Reviewed-on: #221
2024-09-19 11:30:20 +08:00
白了个白 9d7aad1946 Merge branch 'zouyf_dev' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into baigl 2024-09-19 11:28:45 +08:00
lyc db2be260a7 教材edit 2024-09-19 11:25:01 +08:00
baigl b06ad0f411 Merge pull request 'baigl' (#220) from baigl into main
Reviewed-on: #220
2024-09-19 10:58:42 +08:00
白了个白 129f875469 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into baigl 2024-09-19 10:54:31 +08:00
白了个白 2c6da76cf7 作业设计跳转web端逻辑修改 2024-09-19 10:52:33 +08:00
ekooo 499e428138 Merge branch 'main' into zouyf_dev
# Conflicts:
#	src/renderer/src/components/set-homework/index.vue
2024-09-18 20:02:53 +08:00
朱浩 81f873bcc3 Merge branch 'main' into zhuhao_dev 2024-09-18 17:31:14 +08:00
“zouyf” 4e835cac82 Merge branch 'main' into zouyf_dev 2024-09-18 14:57:46 +08:00
朱浩 7303128334 Merge branch 'main' into zhuhao_dev 2024-09-18 14:14:35 +08:00
朱浩 f90e2548c6 Merge branch 'main' into zhuhao_dev 2024-09-18 13:56:53 +08:00
朱浩 fb48984e7f APT上课 2024-09-18 11:29:39 +08:00
白了个白 bae24601ef Merge branch 'zouyf_dev' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk into baigl 2024-09-18 10:24:55 +08:00
白了个白 980e4d66e8 作业设计 2024-09-18 10:23:13 +08:00
ekooo 70ba70df45 [作业设计] - 增加页面 2024-09-17 19:56:32 +08:00
39 changed files with 1742 additions and 453 deletions

19
.env.lt Normal file
View File

@ -0,0 +1,19 @@
# 页面标题
VITE_APP_TITLE = 文枢课堂
# 生产环境配置
VITE_APP_ENV = 'production'
# AIx融合数字管理系统/生产环境
VITE_APP_BASE_API = 'https://prev.ysaix.com:7868/prod-api'
VITE_APP_DOMAIN = 'prev.ysaix.com'
VITE_APP_UPLOAD_API = 'https://prev.ysaix.com:7868/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/'
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'

View File

@ -1,5 +1,5 @@
# 页面标题
VITE_APP_TITLE = AIx数字平台
VITE_APP_TITLE = AIX智慧课堂
# 生产环境配置
VITE_APP_ENV = 'production'

54
electron-builder-lt.yml Normal file
View File

@ -0,0 +1,54 @@
appId: com.electron.app
productName: 文枢课堂
directories:
output: dist
buildResources: build
win:
executableName: 文枢课堂
icon: resources/logo2.ico
files:
- '!**/.vscode/*'
- '!src/*'
- '!electron.vite.config.{js,ts,mjs,cjs}'
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
asarUnpack:
- resources/**
nsis:
oneClick: false
allowToChangeInstallationDirectory: true
artifactName: ${name}-${version}-setup.${ext}
shortcutName: ${productName}
uninstallDisplayName: ${productName}
createDesktopShortcut: always
mac:
entitlementsInherit: build/entitlements.mac.plist
extendInfo:
- NSCameraUsageDescription: Application requests access to the device's camera.
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
notarize: false
dmg:
artifactName: ${name}-${version}.${ext}
linux:
target:
- AppImage
- snap
- deb
maintainer: electronjs.org
category: Utility
appImage:
artifactName: ${name}-${version}.${ext}
npmRebuild: false
publish:
provider: generic
url: https://prev.ysaix.com:7868/src/assets/smarttalk/
electronDownload:
mirror: https://npmmirror.com/mirrors/electron/
# 额外依赖打包到输出目录
extraFiles:
- from: ./node_modules/im_electron_sdk/lib/
to: ./resources
filter:
- '**/*'

View File

@ -3,7 +3,14 @@ import path from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import vue from '@vitejs/plugin-vue'
import WindiCSS from "vite-plugin-windicss"
/*import electron from 'vite-plugin-electron'
plugins: [electron({
main: {
builderOptions: {
asar: false
}
}
})],*/
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()]

View File

@ -1,7 +1,7 @@
{
"name": "aix-win",
"version": "1.2.3",
"description": "An Electron application with Vue",
"version": "2.0.6",
"description": "",
"main": "./out/main/index.js",
"author": "example.com",
"homepage": "https://electron-vite.org",
@ -16,6 +16,7 @@
"build:dev": "npm run build && electron-builder --win --config ./electron-builder-test.yml",
"build:test": "electron-vite build --mode test && electron-builder --win --config ./electron-builder.yml",
"build:prod": "electron-vite build --mode production && electron-builder --win --config ./electron-builder-prod.yml",
"build:lt": "electron-vite build --mode lt && electron-builder --win --config ./electron-builder-lt.yml",
"build:mac": "npm run build && electron-builder --mac",
"build:linux": "npm run build && electron-builder --linux"
},
@ -45,10 +46,12 @@
"jsencrypt": "^3.3.2",
"jsondiffpatch": "0.6.0",
"lodash": "^4.17.21",
"node-addon-api": "^8.1.0",
"pdfjs-dist": "4.4.168",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"spark-md5": "^3.0.2",
"vite-plugin-electron": "^0.28.8",
"vue-qr": "^4.0.9",
"vue-router": "^4.4.0",
"xgplayer": "^3.0.19",

View File

@ -21,6 +21,27 @@ File({ app, shell, BrowserWindow, ipcMain })
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
let mainWindow, loginWindow
const additionalData = {myKey:'ys_axi_smarttalk'}
const gotTheLock = app.requestSingleInstanceLock(additionalData)
if(!gotTheLock){
app.quit()
}else{
app.on('second-instance',(event,commandLine,workingDirectory,additionalData)=>{
//输入从第二个实例中接收到的数据
console.log(additionalData)
//有人试图运行第二个实例,我们应该关注我们的窗口
if(mainWindow){
if(mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
if(loginWindow){
if(loginWindow.isMinimized()) loginWindow.restore()
loginWindow.focus()
}
})
}
//登录窗口
function createLoginWindow() {
if (loginWindow) return
@ -53,7 +74,7 @@ function createLoginWindow() {
updateInit(loginWindow)
}
loginWindow.webContents.openDevTools()
// loginWindow.webContents.openDevTools()
loginWindow.once('ready-to-show', () => {
loginWindow.show()
})
@ -101,7 +122,7 @@ function createMainWindow() {
shell.openExternal(details.url)
return { action: 'deny' }
})
mainWindow.webContents.openDevTools()
// mainWindow.webContents.openDevTools()
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])

View File

@ -2,12 +2,12 @@
<div class="book-wrap">
<el-scrollbar height="100%">
<div class="book-name flex" @click="dialogVisible = true">
<span>{{ curBookName }}</span>
<span>{{ curBook.data.itemtitle }}</span>
<i class="iconfont icon-xiangyou"></i>
</div>
<div class="book-list" v-loading="treeLoading">
<el-tree ref="refTree" :data="treeData" :props="defaultProps" node-key="id"
:default-expanded-keys="defaultExpandedKeys" :current-node-key="currentNodeId" highlight-current
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id"
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
@node-click="handleNodeClick">
<template #default="{ node }">
<span :title="node.label" class="tree-label">{{ node.label }}</span>
@ -28,9 +28,9 @@
<div class="textbook-container">
<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="curBook.data.id == item.id ? 'active-item' : ''"
:key="item.id" @click="changeBook(item)">
<img v-if="item.avartar" :src="BaseUrl + item.avartar" class="textbook-img" alt="">
<img v-if="item.avartar" :src="item.avartar.indexOf('http') === 0 ? item.avartar : BaseUrl + item.avartar" class="textbook-img" alt="">
<div v-else class="textbook-img">
<i class="iconfont icon-jiaocaixuanze" style="font-size: 40px;"></i>
</div>
@ -43,146 +43,86 @@
<script setup>
import { onMounted, ref, nextTick, toRaw, reactive } from 'vue';
import useUserStore from '@/store/modules/user'
import { listEvaluation } from '@/api/subject'
import { cloneDeep } from 'lodash'
import { useGetSubject } from '@/hooks/useGetSubject'
const BaseUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
// emit
const emit = defineEmits(['nodeClick', 'changeBook'])
// store
const userStore = useUserStore()
const { edustage, edusubject, userId } = userStore.user
//
let useSubject = null
const subjectList = ref([])
const evaluationList = ref([])
const dialogVisible = ref(false)
//
const treeData = ref([])
const defaultProps = {
children: 'children',
label: 'label',
label: 'itemtitle',
class: 'textbook-tree'
}
const treeLoading = ref(false)
//ID
const curBookId = ref(-1)
//
const curBookName = ref('')
//
const curBookImg = ref('')
//
const curBookPath = ref('')
//
const volumeOne = ref([])
//
const volumeTwo = ref([])
//
const curBook = reactive({
data: {}
})
//
const currentNode = reactive({
const curNode = reactive({
data:{}
})
// ID
const currentNodeId = ref(0)
//
const currentNodeName = ref('')
const treeLoading = ref(false)
//
const defaultExpandedKeys = ref([])
// tree
const refTree = ref(null)
// +
const getSubjectContent = async () => {
treeLoading.value = true
const params = {
edusubject,
edustage,
// entpcourseedituserid: userId,
itemgroup: 'textbook',
orderby: 'orderidx asc',
pageSize: 10000
}
if(localStorage.getItem('evaluationList')){
evaluationList.value = JSON.parse(localStorage.getItem('evaluationList'))
}
else{
const { rows } = await listEvaluation(params)
localStorage.setItem('evaluationList', JSON.stringify(rows))
evaluationList.value = rows
}
treeLoading.value = false
//
await getSubject()
//
/**
* 不区分上下册
* 2024/08/20调整
*/
// volumeOne.value = data.filter(item => item.level == 1 && item.semester == '')
// volumeTwo.value = data.filter(item => item.level == 1 && item.semester == '')
getTreeData()
}
//
const changeBook = ({ id, itemtitle, avartar, fileurl }) => {
curBookId.value = id
curBookName.value = itemtitle
curBookImg.value = BaseUrl + avartar
curBookPath.value = fileurl
getTreeData()
const changeBook = (data) => {
curBook.data = data
localStorage.setItem('curBook', JSON.stringify(data))
treeData.value = useSubject.getTreeData(data.id)
//
nextTick(() =>{
defaultExpandedKeys.value = [treeData.value[0].id]
curNode.data = getLastLevelData(treeData.value)[0]
localStorage.setItem('defaultExpandedKeys', JSON.stringify(defaultExpandedKeys.value))
localStorage.setItem('curNode',JSON.stringify(curNode.data))
emitChangeBook()
})
//
setTimeout(() => {
dialogVisible.value = false
}, 100);
}
const getTreeData = () => {
//
let upData = transData(evaluationList.value)
if(upData.length){
treeData.value = [...upData]
}
else{
treeData.value = []
return
}
nextTick(() => {
defaultExpandedKeys.value = [treeData.value[0].id]
currentNode.data = getLastLevelData(treeData.value)[0]
currentNodeId.value = getLastLevelData(treeData.value)[0].id
currentNodeName.value = getLastLevelData(treeData.value)[0].label
emitChangeBook()
})
}
const emitChangeBook = () => {
let curNode = {
id: currentNodeId.value,
label: currentNodeName.value,
itemtitle: currentNode.data.itemtitle,
edudegree: currentNode.data.edudegree,
edustage: currentNode.data.edustage,
edusubject: currentNode.data.edusubject,
}
let parentNode = findParentByChildId(treeData.value, currentNodeId.value)
curNode.parentNode = toRaw(parentNode)
const emitChangeBook = async () => {
let curData = cloneDeep(toRaw(curNode.data))
let parentNode = findParentByChildId(treeData.value, curData.id)
curData.parentNode = toRaw(parentNode)
//label label
curData.label = curData.itemtitle
const data = {
textBook: {
curBookId: curBookId.value,
curBookName: curBookName.value,
curBookImg: curBookImg.value,
curBookPath: curBookPath.value
curBookId: curBook.data.id,
curBookName: curBook.data.itemtitle,
curBookImg: BaseUrl + curBook.data.avartar,
curBookPath: curBook.data.fileurl
},
node: curNode
node: curData
}
/**
* 临时用 后续删除 unitId
*/
let levelFirstId = null
let levelSecondId = null
let bookeId = curBook.data.id
if (curData.parentNode) {
levelFirstId = curData.parentNode.id
levelSecondId = curData.id
} else {
levelFirstId = curData.id
levelSecondId = ''
}
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId}))
emit('changeBook', data)
}
@ -230,101 +170,95 @@ const findParentByChildId = (treeData, targetNodeId) => {
return null;
}
const transData = (data) => {
let ary = []
data.forEach(item => {
let obj = {}
// ID
if (item.rootid == curBookId.value) {
if(item.level == 1){
obj.label = item.itemtitle
obj.id = item.id
obj.itemtitle = item.itemtitle
obj.edudegree = item.edudegree
obj.edustage = item.edustage
obj.edusubject = item.edusubject
let ary2 = []
evaluationList.value.forEach(el => {
let obj2 = {}
if (item.id == el.parentid) {
obj2 = {
label: el.itemtitle,
id: el.id,
itemtitle : el.itemtitle,
edudegree : el.edudegree,
edustage : el.edustage,
edusubject : el.edusubject,
}
ary2.push(obj2)
}
obj.children = ary2
})
ary.push(obj)
}
}
})
return ary
}
//
const getSubject = async () => {
if(localStorage.getItem('subjectList')){
subjectList.value = JSON.parse(localStorage.getItem('subjectList'))
}
else{
const { rows } = await listEvaluation({ itemkey: "version", edusubject, edustage, pageSize: 10000,orderby: 'orderidx asc', })
// subjectList.value = rows.filter(item => item.edustage == edustage && item.edusubject == edusubject)
subjectList.value = rows
localStorage.setItem('subjectList', JSON.stringify(subjectList.value))
}
//
if(!subjectList.value.length) return
curBookName.value = subjectList.value[0].itemtitle
curBookId.value = subjectList.value[0].id
curBookImg.value = BaseUrl + subjectList.value[0].avartar
curBookPath.value = subjectList.value[0].fileurl
}
const isHaveUnit = (id) => {
return evaluationList.value.some(item => {
return item.rootid == id
})
}
const handleNodeClick = (data, node) => {
/**
* data : 当前节点数据
* node : 当前节点对象 包含当前节点所有数据 parent属性 指向父节点Node对象
*/
const nodeData = data;
let nodeData = cloneDeep(toRaw(data));
//label label
nodeData.label = nodeData.itemtitle
const parentNode = node.parent.data;
// parentNode
if (Array.isArray(parentNode)) {
//
nodeData.parentNode = null
}
else {
nodeData.parentNode = parentNode
// parentNode
nodeData.parentNode = toRaw(parentNode)
}
let curData = {
textBook: {
curBookId: curBookId.value,
curBookName: curBookName.value,
curBookImg: curBookImg.value,
curBookPath: curBookPath.value
curBookId: curBook.data.id,
curBookName: curBook.data.itemtitle,
curBookImg: BaseUrl + curBook.data.avartar,
curBookPath: curBook.data.fileurl
},
node: toRaw(nodeData)
}
currentNode.data = curData
localStorage.setItem('defaultExpandedKeys', parentNode ? JSON.stringify([parentNode.id]) : JSON.stringify([data.id]))
localStorage.setItem('curNode', JSON.stringify(nodeData))
/**
* 临时用 后续删除 unitId
*/
let levelFirstId = null
let levelSecondId = null
let bookeId = curBook.data.id
if (nodeData.parentNode) {
levelFirstId = nodeData.parentNode.id
levelSecondId = nodeData.id
} else {
levelFirstId = nodeData.id
levelSecondId = ''
}
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId}))
emit('nodeClick', curData)
}
onMounted(() => {
getSubjectContent()
onMounted( async () => {
treeLoading.value = true
try{
useSubject = await useGetSubject()
subjectList.value = useSubject.subjectList
let book = localStorage.getItem('curBook')
if(book){
book = JSON.parse(book)
curBook.data = book
treeData.value = useSubject.getTreeData(book.id)
}
else{
curBook.data = useSubject.subjectList[0]
treeData.value = useSubject.treeData
}
//
nextTick(() =>{
//
let node = localStorage.getItem('curNode')
if(node){
curNode.data = JSON.parse(node)
defaultExpandedKeys.value = JSON.parse(localStorage.getItem('defaultExpandedKeys'))
}
else{
defaultExpandedKeys.value = [treeData.value[0].id]
curNode.data = getLastLevelData(treeData.value)[0]
//
localStorage.setItem('defaultExpandedKeys', JSON.stringify(defaultExpandedKeys.value))
localStorage.setItem('curNode', JSON.stringify(curNode.data))
}
emitChangeBook()
})
} finally{
treeLoading.value = false
}
})
</script>

View File

@ -64,6 +64,8 @@ const getVertion = (data) => {
childs: []
}
})
//
if(treeData.value.length === 0) return
nextTick(() => {
defaultExpandedKeys.value = [treeData.value[0].id]
node.currentNode.data = treeData.value[0]

View File

@ -137,7 +137,7 @@ const getSubjectContent = async () => {
}
const getSubject = async () => {
subjectList.value = JSON.parse(localStorage.getItem('subjectList'))
if (localStorage.getItem('subjectList')) {
subjectList.value = JSON.parse(localStorage.getItem('subjectList'))

View File

@ -0,0 +1,202 @@
import { nextTick, toRaw } from 'vue'
import useUserStore from '@/store/modules/user'
import { listEvaluation } from '@/api/subject'
const userStore = useUserStore()
const { edustage, edusubject } = userStore.user
let evaluationList = []; // 教材版本list
let subjectList = []; // 教材list
//当前教材ID
let curBookId = -1;
/**
* 外部链接初始化获取 跳转web端的 unitId 专用
* 暂时 初始化作业设计专用后期可能会取消
*/
export const useGetClassWork = async () => {
const params = {
edusubject,
edustage,
// entpcourseedituserid: userId,
itemgroup: 'textbook',
orderby: 'orderidx asc',
pageSize: 10000
}
if(localStorage.getItem('evaluationList')){
evaluationList = JSON.parse(localStorage.getItem('evaluationList'))
}else{
const { rows } = await listEvaluation(params)
localStorage.setItem('evaluationList', JSON.stringify(rows))
evaluationList = rows
}
//获取教材版本
await getSubject()
//上册
/**
* 不区分上下册
* 2024/08/20调整
*/
// volumeOne = data.filter(item => item.level == 1 && item.semester == '上册')
// volumeTwo = data.filter(item => item.level == 1 && item.semester == '下册')
getTreeData()
}
//获取教材
const getSubject = async () => {
if(localStorage.getItem('subjectList')){
subjectList = JSON.parse(localStorage.getItem('subjectList'))
}else{
const { rows } = await listEvaluation({ itemkey: "version", edusubject, edustage, pageSize: 10000,orderby: 'orderidx asc', })
// subjectList = rows.filter(item => item.edustage == edustage && item.edusubject == edusubject)
subjectList = rows
localStorage.setItem('subjectList', JSON.stringify(subjectList))
}
// 默认第一个
if(!subjectList.length) return
// curBookName = subjectList[0].itemtitle
curBookId = subjectList[0].id
// curBookImg = BaseUrl + subjectList[0].avartar
// curBookPath = subjectList[0].fileurl
}
const getTreeData = () => {
//数据过滤
let upData = transData(evaluationList)
if(upData.length){
// treeData = [...upData]
}else{
// treeData = []
return
}
nextTick(() => {
// defaultExpandedKeys = [treeData[0].id]
// let currentNodeObj = {...getLastLevelData(upData)[0]}
let currentNodeId = getLastLevelData(upData)[0].id
let currentNodeName = getLastLevelData(upData)[0].label
let curNode = {
id: currentNodeId,
label: currentNodeName,
// itemtitle: currentNodeObj.itemtitle,
// edudegree: currentNodeObj.edudegree,
// edustage: currentNodeObj.edustage,
// edusubject: currentNodeObj.edusubject,
}
let parentNode = findParentByChildId(upData, currentNodeId)
curNode.parentNode = toRaw(parentNode)
let levelFirstId = '';
let levelSecondId = '';
if (curNode.parentNode) {
levelFirstId = curNode.parentNode.id
} else {
levelFirstId = curNode.id
levelSecondId = ''
}
let bookeId = curBookId
// 头部 教材分析、作业设计打开外部链接需要当前章节ID
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId, bookeId}))
// const data = {
// textBook: {
// curBookId: curBookId,
// curBookName: curBookName,
// curBookImg: curBookImg,
// curBookPath: curBookPath
// },
// node: curNode
// }
// emit('changeBook', data)
})
}
const getLastLevelData = (tree) => {
let lastLevelData = [];
// 递归函数遍历树形结构
function traverseTree(nodes) {
nodes.forEach((node) => {
// 如果当前节点有子节点,继续遍历
if (node.children && node.children.length > 0) {
traverseTree(node.children);
} else {
// 如果没有子节点,说明是最后一层的节点
lastLevelData.push(node);
}
});
}
// 调用递归函数开始遍历
traverseTree(tree);
// 返回最后一层的数据
return lastLevelData;
}
// 根据id 拿到父节点数据
const findParentByChildId = (treeData, targetNodeId) => {
// 递归查找函数
// 遍历树中的每个节点
for (let node of treeData) {
// 检查当前节点的子节点是否包含目标子节点 ID
if (node.children && node.children.some(child => child.id === targetNodeId)) {
// 如果当前节点的某个子节点的 ID 匹配目标子节点 ID则当前节点即为父节点
return node;
}
// 如果当前节点没有匹配的子节点,则递归检查当前节点的子节点
if (node.children) {
let parentNode = findParentByChildId(node.children, targetNodeId);
if (parentNode) {
return parentNode;
}
}
}
// 如果未找到匹配的父节点,则返回 null 或者适当的默认值
return null;
}
const transData = (data) => {
let ary = []
data.forEach(item => {
let obj = {}
// 根据当前教材ID 过滤出对应的单元、章节
if (item.rootid == curBookId) {
if(item.level == 1){
obj.label = item.itemtitle
obj.id = item.id
obj.itemtitle = item.itemtitle
obj.edudegree = item.edudegree
obj.edustage = item.edustage
obj.edusubject = item.edusubject
let ary2 = []
evaluationList.forEach(el => {
let obj2 = {}
if (item.id == el.parentid) {
obj2 = {
label: el.itemtitle,
id: el.id,
itemtitle : el.itemtitle,
edudegree : el.edudegree,
edustage : el.edustage,
edusubject : el.edusubject,
}
ary2.push(obj2)
}
obj.children = ary2
})
ary.push(obj)
}
}
})
return ary
}

View File

@ -0,0 +1,82 @@
import { ref } from 'vue'
import useUserStore from '@/store/modules/user'
import { listEvaluation } from '@/api/subject'
export const useGetSubject = async () =>{
// user store
const userStore = useUserStore()
const { edustage, edusubject, userId } = userStore.user
const BaseUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
// 章节List
const unitList = ref([])
// 教材List
let subjectList = null
// 单元章节树结构
let treeData = null
// 根据 学科 + 学段 获取所有单元章节
const getSubjectUnit = async () =>{
let strUnit = localStorage.getItem('unitList')
if(strUnit){
unitList.value = JSON.parse(strUnit)
}
else{
const unitParams = {
edusubject,
edustage,
itemgroup: 'textbook',
orderby: 'orderidx asc',
pageSize: 10000
}
const { rows } = await listEvaluation(unitParams)
unitList.value = rows
localStorage.setItem('unitList', JSON.stringify(rows))
}
await getSubject()
}
// 获取 学科 + 学段 获取教材
const getSubject = async () =>{
let strSubject = localStorage.getItem('subjectList')
if(strSubject){
subjectList = JSON.parse(strSubject)
}
else{
const subjectParams = {
itemkey: "version",
edusubject,
edustage,
pageSize: 10000,
orderby: 'orderidx asc'
}
const { rows } = await listEvaluation(subjectParams)
subjectList = rows
localStorage.setItem('subjectList', JSON.stringify(rows))
}
// 默认选中第一个教材
if(subjectList && subjectList.length){
treeData = getTreeData(subjectList[0].id)
}
}
// 单元章节数据转为“树”结构
const getTreeData = (bookId) =>{
// 根据当前教材的id 查找出对应的章节
let data = unitList.value.filter(item => item.rootid == bookId && item.level == 1)
data.forEach( item => {
item.children = unitList.value.filter( item2 => item2.parentid == item.id && item2.level == 2)
})
return data
}
await getSubjectUnit()
return { subjectList, treeData, getTreeData }
}

View File

@ -3,7 +3,7 @@
<div class="left-section">
<div class="flex title-box">
<el-image style="width: 23px; height: 23px" :src="logoIco" />
<span class="title" @click="changeTab">AIX智慧课堂</span>
<span class="title" @click="changeTab">{{homeTitle}}</span>
</div>
<div class="change-tab">
<ul class="flex">
@ -37,7 +37,7 @@
<div class="user-info flex">
<span class="user-name">{{ userStore.user.nickName }}</span>
<div class="flex">
<div class="user-depname">{{ userStore.user.deptName }}</div>
<el-dropdown @command="changeSubject">
<div class="user-subject">{{ userStore.user.edusubject }}
<el-icon class="el-icon--right"><arrow-down />
@ -52,6 +52,7 @@
</template>
</el-dropdown>
</div>
<div class="user-depname">{{ userStore.user.deptName }}</div>
</div>
</div>
@ -72,7 +73,8 @@ import { updateUserInfo } from '@/api/system/user'
import outLink from '@/utils/linkConfig'
import logoIco from '@/assets/images/logo.png'
import { listEvaluation } from '@/api/classManage/index'
import { clearBookInfo } from '@/utils/ruoyi'
let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
const { ipcRenderer } = window.electron || {}
const userStore = useUserStore()
const router = useRouter()
@ -190,6 +192,7 @@ function setLayout() {
}
//
const changeSubject = async (command) =>{
clearBookInfo()
const { userId, userName, phonenumber, plainpwd } = userStore.user
const data = {
userId,
@ -329,7 +332,7 @@ onMounted(() => {
justify-content: space-around;
.user-depname {
margin-right: 5px;
margin-right: 0;
}
.user-subject {
@ -349,8 +352,8 @@ onMounted(() => {
align-items: center;
.user-avatar {
width: 35px;
height: 35px;
width: 45px;
height: 45px;
border-radius: 10px;
margin-right: 10px;
}

View File

@ -61,14 +61,15 @@ function stateSyncWatch(storeName, newState) {
// console.log('state-change-diffData', diffData)
try {
for(const key in diffData) {
const value = diffData[key]
const value = diffData[key] || null
const newValue = {} // 重新组装pinia需要的数据 {a:{b:1}} 这种
const keyArr = key.split('.') || []
keyArr.reduce((o,c,i)=>{o[c] = i === keyArr.length-1 ? value : {};return o[c]}, newValue)
const jsonStr = JSON.stringify(newValue) // 从新组装-json数据
// // 更新本地数据-session
// 更新本地数据-session
// console.log('state-change-update:', key, value)
sessionStore.set(key, value)
// // 通知主线程更新
// 通知主线程更新
ipcRenderer?.invoke('pinia-state-change', storeName, jsonStr)
// console.log('======',key, value, jsonStr )
}
@ -171,6 +172,8 @@ const getObjValue = (obj, key) => {
const findDifferences = (obj1, obj2) => {
const differences = {};
function compareObjects(o1, o2, path = '') {
if (o1 == null) return
if (o2 == null) return
for (const key in o1) {
if (o1.hasOwnProperty(key)) {
const newPath = path ? `${path}.${key}` : key;

View File

@ -36,13 +36,13 @@ export const constantRoutes = [
path: '/resource',
component: () => import('@/views/resource/index.vue'),
name: 'resource',
meta: {title: '资源'}
meta: {title: '资源'}
},
{
path: '/prepare',
component: () => import('@/views/prepare/index.vue'),
name: 'prepare',
meta: {title: '备课'}
meta: {title: '教学实践'}
},
{
path: '/teach',
@ -68,12 +68,24 @@ export const constantRoutes = [
name: 'class',
meta: {title: '班级中心'},
},
{
path: '/classTaskAssign',
component: () => import('@/views/classTaskAssign/index.vue'),
name: 'classTaskAssign',
meta: {title: '作业设计'},
},
{
path: '/classTask',
component: () => import('@/views/classTask/classTask.vue'),
name: 'classCorrect',
meta: {title: '作业批改'},
},
{
path: '/newClassTask',
component: () => import('@/views/classTask/newClassTask.vue'),
name: 'newClassCorrect',
meta: {title: '作业设计'},
},
{
path: '/examReport',
component: () => import('@/views/examReport/index.vue'),

View File

@ -97,6 +97,9 @@ export const getCurrentTime = (format)=> {
if(format == 'HH:mm'){
return `${hours}:${minutes}`;
}
if(format == 'MMDD'){
return `${month}${day}`;
}
}
/**
*

View File

@ -257,3 +257,17 @@ export const getFileName = (filename) => {
if(!filename) return
return filename.replace(/\.[^/.]+$/, "");
}
// 清除当前选中的教材 章节 相关信息
export const clearBookInfo = () =>{
//当前选中的教材
localStorage.removeItem('curBook')
// 当前选中的节点
localStorage.removeItem('curNode')
// 所有章节单元数据
localStorage.removeItem('unitList')
// 所有教材数据
localStorage.removeItem('subjectList')
// 展开的节点
localStorage.removeItem('defaultExpandedKeys')
}

View File

@ -1,10 +1,10 @@
<template>
<el-card style="width: 100%;height: 100%;overflow: auto">
<!-- <template #header>-->
<!-- <div class="card-header" style="text-align: left">-->
<!-- <el-button type="primary" @click="addGroup">新建分组</el-button>-->
<!-- </div>-->
<!-- </template>-->
<template #header>
<div class="card-header" style="text-align: left">
<el-button type="primary" @click="addGroup">新建分组</el-button>
</div>
</template>
<template v-if="groupList.length > 0">
<div style="font-size: 16px;font-weight: bold;color: #000;text-align: left;margin-bottom: 5px">可用分组</div>
<div class="groupList">

View File

@ -186,7 +186,8 @@
])
//
const classids = ref('')
//
const classesNotAMemberOf = ref([])
//
const getClassInfo = () => {
classList.value = []
@ -199,13 +200,13 @@
});
listClassmain({entpid: userStore.deptId, status: 'open', pageSize: 100}).then(response => {
//
let arr = [...response.rows]
classesNotAMemberOf.value = [...response.rows]
classList.value.forEach(item => {
const currentIndex = arr.findIndex(items => items.id === item.id)
if(currentIndex) arr.splice(currentIndex, 1)
const currentIndex = classesNotAMemberOf.value.findIndex(items => items.id === item.id)
if(currentIndex) classesNotAMemberOf.value.splice(currentIndex, 1)
})
//
gradeTree.value = groupByCondition(arr, item => item.agekey);
gradeTree.value = groupByCondition(classesNotAMemberOf.value, item => item.agekey);
})
}
//
@ -301,7 +302,7 @@
addClasses({classIds:classids.value.join(','),userId:userStore.userId}).then(res => {
if (res.code === 200) {
dialogVisible.value = false
ElMessage({
ElMessage({x
message: res.msg,
type: 'success',
})

View File

@ -141,6 +141,7 @@ const getClassWorkList = () => {
edustage: userStore.edustage,//
edusubject: userStore.edusubject,//
deaddate: tabActive.value === '进行中'? getTomorrow() : EndDate.value,//
status: '1', // 1-
orderby: 'concat(deaddate,uniquekey) DESC',
pageSize: 100
}).then((response) => {
@ -220,7 +221,7 @@ const getStudentClassWorkData = () => {
}).then((res) => {
for (var t = 0; t < classWorkList.value.length; t++) {
for (var i = 0; i < res.rows.length; i++) {
if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].resultcount > 0) {
if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].finishtimelength != '0') {
console.log('==================')
// /
// resultcount0

View File

@ -8,15 +8,15 @@
<div class="teacher_content_con">
<!-- 题目内容习题训练 -->
<div v-if="dialogProps.studentObj.worktype == '习题训练'">
<div v-for="(quItem, qIndex) in dialogProps.quizlist" :key="quItem.id">
<div v-for="(stuItem, sIndex) in dialogProps.studentQuizAllList" :key="stuItem.id">
<div v-for="quItem in dialogProps.quizlist" :key="quItem.id">
<div v-if="stuItem.entpcourseworkid == quItem.id">
<el-card style="max-width: 100%; margin-bottom: 10px">
<!-- 题型 分值 -->
<template #header>
<div class="card-header">
<span
>{{ sIndex + 1 }}{{ quItem.worktype }}
>{{ qIndex + 1 }}{{ quItem.worktype }}
{{ stuItem.score ? stuItem.score : 0 }}</span
>
</div>
@ -79,69 +79,23 @@
<template #footer>
<el-row>
<el-col :span="6" style="padding: 10px">
<span
>参考答案
<span>参考答案
<span v-if="quItem.workanswerFormat != ''">
<sapn
style="
background-color: #0ed116;
color: white;
padding: 0 5px;
border-radius: 5px;
"
>{{ quItem.workanswerFormat.replace(/<[^>]+>/g, '') }}</sapn
>
<sapn style="background-color: #0ed116; color: white; padding: 0 5px; border-radius: 5px;">{{ formatWorkAnswer(quItem) }}</sapn>
</span>
</span>
</el-col>
<el-col :span="6" style="padding: 10px">
<!-- <span>学生答案{{ stuItem.feedcontent }}</span> -->
<span
>学生答案
<span v-if="quItem.workdesc == ''|| quItem.workdesc == '[]' ">
<!-- quItem.workdesc 没值说明是非选择题 -->
<span
v-if="stuItem.feedcontent != ''"
style="
background-color: red;
color: white;
padding: 0 5px;
border-radius: 5px;
"
>
{{ stuItem.feedcontent.replace('#', '、') }}
</span>
</span>
<span v-else>
<!-- 选择题类型学生答题转换为 ABCD格式 -->
<span
v-if="stuItem.feedcontent != ''"
style="
background-color: red;
color: white;
padding: 0 5px;
border-radius: 5px;
"
>
{{
JSON.parse(quItem.workdesc)
.map((item, index) => {
if (item == stuItem.feedcontent) {
return String.fromCharCode(65 + Number(index))
}
})
.filter(Boolean)[0]
}}
</span>
<span>学生答案
<span v-if="stuItem.feedcontent !=''" style="background-color: red; color: white; padding: 0 5px; border-radius: 5px;">
{{ formatFeedContent(stuItem, quItem) }}
</span>
</span>
</el-col>
<el-col :span="6" style="padding: 10px">
<div
v-for="(imageItem, index) in stuItem.imagefile"
v-if="stuItem.imagefile && stuItem.imagefile.length > 0"
:key="index"
>
<div v-if="stuItem.imagefile && stuItem.imagefile.length > 0">
<div v-for="(imageItem, index) in stuItem.imagefile" :key="index">
<el-image
style="width: 30px; height: 30px"
:src="imageItem"
@ -153,6 +107,7 @@
fit="contain"
/>
</div>
</div>
</el-col>
<el-col :span="6" style="padding: 10px">
<!-- 单选题 填空题 多选题 判断题 主观题 复合题 待完善
@ -254,6 +209,11 @@
<!-- 学生答题展示 -->
<div v-if="feedContentList.length > 0">
<div v-if="dialogProps.studentObj.worktype == '常规作业' && stuItem.rightanswer != ''&& stuItem.rightanswer != null">
<!-- 常规作业学生有的会答复 -->
<p style="padding: 10px 0;">学生答复内容</p>
<div style="padding: 0 20px">{{stuItem.rightanswer}}</div>
</div>
<p>学生答题附件内容</p>
<div class="image_list">
<div v-if="imageList.length > 0">
@ -290,6 +250,9 @@
</span>
</div>
</div>
<!-- 无附件内容 -->
<div v-if="imageList.length == 0 && fileList.length == 0" style="padding: 0 20px">未提交附件内容</div>
</div>
</div>
<div v-else>
@ -499,6 +462,7 @@ import { ElMessageBox, ElMessage } from 'element-plus'
import { updateClassworkeval, updateClassworkdata } from '@/api/classTask'
import { getTimeDate } from '@/utils/date'
import ReFilePreview from '@/components/refile-preview/index.vue'
import { quizStrToList } from '@/utils/comm';
const userStore = useUserStore()
@ -842,6 +806,47 @@ const acceptParams = (params) => {
analysisScoreOpen.value = true
}
const formatWorkAnswer = (quItem) => {
let format = '';
if (!Array.isArray(quItem.workanswerFormat)) {
format = quItem.workanswerFormat.replace(/<[^>]+>/g, '')
} else {
format = quItem.workanswerFormat.map(item => item.replace(/<[^>]+>/g, '')).join('、');
}
return format;
}
//
const formatFeedContent = (stuItem, quItem) => {
let format = '';
if (quItem.workdesc == '' || quItem.workdesc == '[]') {
//
const arr = stuItem.feedcontent.split('#');
return arr.map(item => {
if (item == '') {
item = '空';
}
return item;
}).join('、');
}else {
const list = quizStrToList(quItem.workdesc);
format = list.map((item,index) =>{
if (quItem.worktype == '单选题') {
const workdesc = item.replace(/<[^>]*>/g,'');
const feedcontent = stuItem.feedcontent.replace(/<[^>]*>/g,'');
if(workdesc == feedcontent){
return (String.fromCharCode(65+Number(index)))
}
} else if (quItem.worktype == '多选题') {
const arr = stuItem.feedcontent.split(',');
return arr.map(item => String.fromCharCode(65+Number(item))).join('');
}
}).filter(Boolean)[0];
}
return format;
}
//
const onClassWorkFormScoreSave = () => {
console.log(classWorkFormScore)

View File

@ -383,7 +383,7 @@ const getClassWorkStudentList = (rowId) => {
//
tableRadio.list =
classWorkAnalysis.classworkdata &&
classWorkAnalysis.classworkdata.filter((item) => item.resultcount > 0)
classWorkAnalysis.classworkdata.filter((item) => item.finishtimelength != '0')
tableRadio.value = '1'
tableRadio.num0 = classWorkAnalysis.classworkdata.length - tableRadio.list.length
tableRadio.num1 = tableRadio.list.length
@ -506,12 +506,12 @@ const tableRadioChange = (e) => {
console.log(e,'??????')
console.log("学生列表:", classWorkAnalysis.classworkdata)
if(e=='1'){
tableRadio.list = classWorkAnalysis.classworkdata.filter(item => item.resultcount > 0)
tableRadio.list = classWorkAnalysis.classworkdata.filter(item => item.finishtimelength != '0')
tableRadio.value = '1';
tableRadio.num0 = classWorkAnalysis.classworkdata.length - tableRadio.list.length;
tableRadio.num1 = tableRadio.list.length;
}else if(e=='0'){
tableRadio.list = classWorkAnalysis.classworkdata.filter(item => item.resultcount == 0)
tableRadio.list = classWorkAnalysis.classworkdata.filter(item => item.finishtimelength == '0')
tableRadio.value = '0';
tableRadio.num0 = tableRadio.list.length;
tableRadio.num1 = classWorkAnalysis.classworkdata.length - tableRadio.list.length;

View File

@ -0,0 +1,452 @@
<template>
<div class="page-typeview flex">
<el-form ref="classWorkForm" :model="classWorkForm" label-width="90" style="height: calc(100% - 55px);display: flex;flex-direction: column;">
<!-- 标题 -->
<el-row>
<el-col :span="24">
<el-form-item label="作业类型:">
<el-radio-group v-model="formType" @change="changeFormType">
<template v-for="(item) in listWorkType" :key="item">
<el-radio :value="item" >{{ item }}</el-radio>
</template>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="作业资源:" class="el-form-work-list">
<el-col :span="15" class="work-left">
<div v-if="classWorkForm.worktype=='习题训练'" style="height: 100%; display: flex; flex-direction: column;">
<el-row :gutter="10">
<el-col :span="6">
<el-form-item label="题型" label-width="70">
<el-select v-model="entpCourseWorkQueryParams.worktype" placeholder="请选择" >
<el-option v-for="(item, index) in entpCourseWorkTypeList" :key="index" :label="item.label" :value="item">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="题源" label-width="70">
<el-select v-model="entpCourseWorkQueryParams.workgroup" placeholder="请选择" >
<el-option v-for="(item, index) in entpCourseWorkGroupList" :key="index" :label="item.Value" :value="item.Key" ></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="11">
<el-form-item label="知识点" label-width="70">
<el-cascader
v-model="entpCourseWorkQueryParams.point"
clearable
style="width: 100%"
:options="entpCourseWorkPointList"
:props="knowledgePointProps"
popper-class="my-popper"
:show-all-levels="false"
collapse-tags
collapse-tags-tooltip
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" style="margin-top: 4px">
<el-col :span="6">
<el-form-item label="年份" label-width="70">
<el-select v-model="entpCourseWorkQueryParams.yearStr" placeholder="请选择" >
<el-option v-for="(item, index) in entpCourseWorkYearList" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="15">
<el-form-item label="关键词" label-width="70">
<el-input
v-model="entpCourseWorkQueryParams.keyWord"
style="width: 70%" type="text"
placeholder="请输入关键词"
/>
<el-button @click="handleQueryParamFromEntpCourseWork(1)"><el-icon><Search /></el-icon> </el-button>
</el-form-item>
</el-col>
</el-row>
<el-table :data="workResource.entpCourseWorkList" style="width: 100%;">
<el-table-column type="index" width="60" />
<el-table-column align="left" >
<template #header>
<div style="display: flex">
<div style="align-items: center;">题目内容</div>
</div>
</template>
<template #default="scope">
<div>
<div style="overflow: hidden; text-overflow: ellipsis" v-html="scope.row.titleFormat"></div>
<div style="overflow: hidden; text-overflow: ellipsis; font-size: 0.9em; margin-top: 6px;" v-html="scope.row.workdescFormat"></div>
<el-col :span="24" style="display: flex">
<div style="font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.entpname }} {{ scope.row.editusername }}</div>
<div style="margin-left: 30px; font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.worktag }}</div>
</el-col>
</div>
</template>
</el-table-column>
<el-table-column align="left" width="100">
<template #default="scope">
<el-button type="primary" @click="handleClassWorkQuizAdd('entpcourseworklist', scope.row.id)">添加</el-button>
</template>
</el-table-column>
</el-table>
<div style="height: 55px;">
<!-- 分页 -->
<pagination
v-show="entpCourseWorkTotal > 0"
v-model:page="paginationParams.pageNum"
v-model:limit="paginationParams.pageSize"
:total="entpCourseWorkTotal"
:style="{ position: 'relative', 'margin-top': '5px' }"
@pagination="getPaginationList" />
</div>
</div>
<!-- <div v-if="classWorkForm.worktype!='习题训练'">
<div :style="{ 'overflow': 'auto'}">
<template v-if="classWorkForm.worktype!='常规作业'">
<template v-for="(item, index) in workResource.teachResourceList" :key="item">
<div v-if="item.worktype==classWorkForm.worktype" style="border-bottom: 1px dotted;display: flex;justify-content: space-between;">
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
<div style="font-size: 1.2em; font-weight: bold;margin-right: 5px">{{ item.worktype }}</div>
<div style="display: flex; justify-content: space-between;">
<div style="color: silver; display: flex;align-items: center;">
<el-image :src="item.userheadimgurl" style="height: 30px; width: 30px; border-radius: 50%;"></el-image>
<div style="line-height: 18px">
<div style="margin-top: 5px; margin-left: 5px">{{ item.username }} 来自{{ item.parententpname }} {{ item.userentpname }}</div>
<div style="margin-top: 5px; margin-left: 5px">{{ item.timestamp }}</div>
</div>
</div>
</div>
</div>
<div style="display: flex;align-items: center; justify-content: space-around; margin-left: 15px; margin-right: 15px;">
<el-button @click="prevRead(item)" icon="Search">预览</el-button>
<el-button @click="handleClassWorkAddOfResource(item)" icon="FolderAdd">添加到作业</el-button>
</div>
</div>
</template>
</template>
<template v-if="classWorkForm.worktype =='常规作业'">
<div class="upload-homework" v-loading="fileLoading">
<FileUpload v-model="fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
</div>
</template>
</div>
</div> -->
<!-- <div v-if="classWorkForm.activeIndex==3">
<el-row>
<el-col :span="20">
<el-form-item label="查找筛选条件">
本节课本单元其他单元
</el-form-item>
</el-col>
<el-col :span="4" style="text-align: right;">
<el-button @click="handleQueryFromEntpCourseWork" icon="Search">更多</el-button>
</el-col>
</el-row>
<div :style="{ 'overflow': 'auto'}">
<template v-for="(item, index) in workResource.classWorkList" :key="item.id">
<template v-if="item.classid > 0">
<div style="margin-bottom: 30px; padding-left: 15px">
<div style="font-size: 1.2em; font-weight: bold">{{ item.worktype }}</div>
<div style="display: flex; justify-content: space-between;">
<div style="color: silver; display: flex">
<el-image :src="item.edituserheadimgurl" style="height: 30px; width: 30px; border-radius: 50%;"></el-image>
<div style="margin-top: 5px; margin-left: 10px">{{ item.editusername }} 来自{{ item.parententpname }} {{ item.entpname }}</div>
</div>
<div style="color: silver; margin-right: 15px; padding-top: 5px">{{item.workdate}}</div>
</div>
<div style="font-size: 1em; margin-top: 10px; margin-bottom: 10px; display: flex">
<div style="max-width: 100%;word-wrap: break-word;">{{ item.workcontent }}</div>
<div v-if="item.entpcourseworklistarray.length>0" style="margin-top: -5px; margin-left: 15px">
<el-button v-if="item.expanded==false" style="margin-right: 4px" @click="handleClassWorkResNodeClick(index)">展开</el-button>
<el-button v-if="item.expanded==true" @click="handleClassWorkResNodeClick(index)">缩回</el-button>
</div>
</div>
</div>
<template v-if="item.expanded == true">
<template v-for="(qitem, qindex) in item.quizlist" :key="qitem.id">
<el-row style="margin-bottom: 20px; border: 1px dotted; padding: 20px" >
<el-col :span="22">
<div v-html="qitem.titleFormat" style="overflow: hidden; text-overflow: ellipsis"></div>
<div v-html="qitem.workdescFormat" style="overflow: hidden; text-overflow: ellipsis; margin-top: 6px;"></div>
</el-col>
<el-col :span="2"><el-button type="primary" @click="handleClassWorkQuizAdd('classworklist', qitem.id)"><el-icon><CirclePlus /></el-icon> </el-button></el-col>
</el-row>
</template>
</template>
<div style="display: flex; justify-content: end; margin-left: 15px; margin-right: 15px">
<el-button @click="handleClassWorkPackAdd(index)" icon="FolderAdd">添加到作业</el-button>
</div>
<el-divider />
</template>
</template>
</div>
</div> -->
</el-col>
<el-col :span="8" style="padding: 0 0 0 5px;height: 60vh; overflow: auto; line-height: 26px">
<div v-if="classWorkForm.worktype=='习题训练'" :style="{ 'overflow': 'auto', 'border':'1px dotted blue','border-radius':'5px', 'background-color': '#f7f7f7'}">
<template v-for="(item,index) in classWorkForm.quizlist" :key="item.id">
<div style="margin: 5px; background-color: white">
<div v-html="item.titleFormat" style="padding: 15px 20px 5px 20px"></div>
<div style="display: flex;">
<el-form-item label="分值">
<el-input-number v-model="item.score" :min="1" :max="100" size="small"></el-input-number >
</el-form-item>
<div style="margin-left: auto; padding: 0px 20px"><el-button size="small" type="danger" @click="handleClassWorkFormQuizRemove(index)">删除</el-button></div>
</div>
</div>
</template>
</div>
<div v-if="classWorkForm.worktype!='习题训练'" :style="{'overflow': 'auto', 'border':'1px dotted blue','border-radius':'5px', 'background-color': '#f7f7f7'}">
<div style="margin: 5px; background-color: white">
<template v-for="(item,index) in chooseWorkLists" :key="item.id">
<div v-if="item.worktype==classWorkForm.worktype">
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
<div style="font-size: 1.2em; font-weight: bold;margin-right: 5px">{{ item.worktype }}</div>
<div style="display: flex;align-items: center; justify-content: space-around; margin-left: 15px; margin-right: 15px;flex: 1;">
<div style="color: silver; display: flex;align-items: center;flex: 1;">
<el-form-item label="分值">
<el-input-number v-model="item.score" :min="1" :max="100" size="small"></el-input-number >
</el-form-item>
</div>
<el-button @click="prevRead(item)" icon="Search">预览</el-button>
<el-button @click="deleteClassWorkAddOfResource(item)" type="danger" icon="Delete">删除</el-button>
</div>
</div>
</div>
</template>
</div>
</div>
</el-col>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup>
import { onMounted, ref, toRaw,watch, reactive } from 'vue'
import { useToolState } from '@/store/modules/tool'
import { getCurrentTime } from '@/utils/date'
import { processList } from '@/hooks/useProcessList'
import {listEntpcoursework, listEntpcourseworkNew} from '@/api/education/entpCourseWork'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore().user
const props = defineProps({
bookobj: {
type: Object,
default: () => ({})
},
})
const isDialogOpen = ref(false)
const toolStore = useToolState()
const openDialog = () => {
isDialogOpen.value = true
}
const formType = ref('习题训练')
// ---------------------------------------------------
const listWorkType = ref(['习题训练', '框架梳理', '课堂展示', '常规作业']); //
const entpCourseWorkTypeList = ref([
{value: 0, label: "不限"},
{value: 1, label: "单选题"},
{value: 2, label: "填空题"},
{value: 3, label: "多选题"},
{value: 4, label: "判断题"},
{value: 5, label: "主观题"},
{value: 6, label: "复合题"},
]); // -
const entpCourseWorkGroupList = ref([{
Key: -1,
Value: '不限',
}, {
Key: 1,
Value: '真题',
}, {
Key: 0,
Value: '非真题',
}]); // -
const entpCourseWorkPointList = ref([
{label: '不限', value: []},
]); // -
const entpCourseWorkYearList =ref([
{label: '不限', value: '-1'},
{label: '2024', value: '2024'},
{label: '2023', value: '2023'},
{label: '2022', value: '2022'},
{label: '2021', value: '2021'},
{label: '2020', value: '2020'},
]); // -
const paginationParams = reactive({
pageNum: 1,
pageSize: 10,
}); //
//
const entpCourseWorkQueryParams = reactive({
worktype: {
label: '不限',
value: 0,
},
workgroup: 0,
yearStr: '-1',
point: [],
keyWord: '',
});
const workResource = reactive({
options: ['学习任务', '云题库'],
worktype: '全部',
activeIndex: "3",
dialogOfTaskOpen: false,
dislogOfAssignOpen: false,
quiztype: '',
queryForm: {},
classWorkList: [], //
entpCourseWorkList: [],
}); //
const classWorkForm = reactive({
worktype: '习题训练', //
// uniquekey: userStore.edusubject+'-' + getCurrentTime('MMDD')+'-'+(this.taskList.length+1),
})
const entpCourseWorkList = ref([]); //
const entpCourseWorkTotal = ref(0); //
/***
* 作业类型切换
*/
const changeFormType = (val) => {
console.log(val)
classWorkForm.value.worktype = val;
}
const queryForm = reactive({
//
eid: props.bookobj.levelSecondId,
sectionName: props.bookobj.coursetitle,
edusubject: userStore.edusubject,
edustage: userStore.edustage,
//
//
worktype: entpCourseWorkQueryParams.worktype.label,
workTypeId: entpCourseWorkQueryParams.worktype.value,
//
workgroup: entpCourseWorkQueryParams.workgroup,
//
yearStr: entpCourseWorkQueryParams.yearStr !== '-1' ? entpCourseWorkQueryParams.yearStr:'',
//
thirdId: entpCourseWorkQueryParams.point.length > 0 ? entpCourseWorkQueryParams.point[0]:'',
//
keyword: entpCourseWorkQueryParams.keyWord && entpCourseWorkQueryParams.keyWord !== '' ? entpCourseWorkQueryParams.keyWord:'',
//
// pageNum: paginationParams.pageNum,
// pageSize: paginationParams.pageSize,
})
/**
* @desc: 新查询试题
* @return: {*}
* @param {*} queryType
* 0 - 标准查询
* 1 - 按条件查询
* 2 - 按关键词查询
*/
const handleQueryFromEntpCourseWork= (queryType) => {
//queryForm.pageNum = this.paginationParams.pageNum;
//queryForm.pageSize = this.paginationParams.pageSize;
// ( warn: )
// if (this.courseObj.edusubject=='' && this.courseObj.edustage=='') {
// // [+][+]
// queryForm.edusubject = '';
// }
console.log(queryForm)
listEntpcourseworkNew(queryForm).then(entpcourseworkres => {
// if (queryType == 1 && this.entpCourseWorkQueryParams.worktype == '') {
// // ,
// const allowedWorkTypes = ['', '', '', '', ''];
// workResource.entpCourseWorkList = entpcourseworkres.rows.filter(item => {
// return !allowedWorkTypes.includes(item.worktype);
// });
// } else {
// workResource.entpCourseWorkList = entpcourseworkres.rows;
// }
if(entpcourseworkres.data == null) {
workResource.entpCourseWorkList = [];
entpCourseWorkTotal.value = 0
return;
}
entpCourseWorkList.value = entpcourseworkres.data;
workResource.entpCourseWorkList.forEach(item=> {
if (item.worktype == '选择题') {
item.worktype = '单选题'
}
})
//
entpCourseWorkTotal.value = 0;
if (entpcourseworkres.data.length > 0) {
entpCourseWorkTotal.value = entpcourseworkres.data.length;
}
//
processList(workResource.entpCourseWorkList);
})
}
onMounted(() => {
handleQueryFromEntpCourseWork(0);
})
// watch(() => sourceStore.query.fileSource,() => {
// sourceStore.query.fileSource === ''?isThird.value = true:isThird.value = false
// })
</script>
<style lang="scss" scoped>
.page-typeview{
padding-top: 10px;
height: 100%;
.el-form-work-list{
:deep(.el-form-item__content){
align-items: normal;
}
.work-left{
height: 50vh;
background-color: white;
padding-right: 0;
padding-left: 0;
border:1px dotted blue;
border-radius:5px;
}
}
}
</style>

View File

@ -0,0 +1,164 @@
<template>
<div class="page-resource flex">
<el-menu
default-active="1"
class="el-menu-vertical-demo"
:collapse="isCollapse"
>
<!--左侧 教材 目录-->
<div v-if="!isCollapse">
<ChooseTextbook @change-book="getData" @node-click="getData" />
</div>
</el-menu>
<div class="page-right" :style="{'margin-left': isCollapse ? '0' : '20px'}">
<!-- 标题 -->
<el-row style="align-items: center; margin-bottom: 0px">
<el-col :span="12" style="padding-left: 20px; text-align: left;">
<div class="unit-top-left" @click="isCollapse = !isCollapse">
<i v-if="!isCollapse" class="iconfont icon-xiangzuo"></i>
<span>作业范围</span>
<i v-if="isCollapse" class="iconfont icon-xiangyou"></i>
</div>
</el-col>
<el-col :span="12">
<div class="classtype-right">
<el-form-item label="作业名称">
<el-input v-model="classWorkForm.uniquekey" type="text" placeholder="请输入作业名称"/>
</el-form-item>
</div>
</el-col>
</el-row>
<!-- 作业类型:内容 -->
<task-type-view :bookobj="courseObj" />
</div>
</div>
</template>
<script setup>
import { onMounted, ref, toRaw,watch, reactive } from 'vue'
// import useResoureStore from './store'
import ChooseTextbook from '@/components/choose-textbook/index.vue'
import Third from '@/components/choose-textbook/third.vue'
// import ResoureSearch from './container/resoure-search.vue'
// import ResoureList from './container/resoure-list.vue'
// import ThirdList from './container/third-list.vue'
import TaskTypeView from '@/views/classTask/container/newTask/taskTypeView.vue'
import uploadDialog from '@/components/upload-dialog/index.vue'
// import { createWindow } from '@/utils/tool'
import { useToolState } from '@/store/modules/tool'
import { getCurrentTime } from '@/utils/date'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore().user
// const sourceStore = useResoureStore()
const isDialogOpen = ref(false)
const toolStore = useToolState()
const openDialog = () => {
isDialogOpen.value = true
}
// ---------------------------------------------------
const classWorkForm = reactive({
// uniquekey: userStore.edusubject+'-' + getCurrentTime('MMDD')+'-'+(this.taskList.length+1),
uniquekey: userStore.edusubject+'-' + getCurrentTime('MMDD')+'-'+(1),
})
const isCollapse = ref(false)
const courseObj = reactive({
// : id,id,id,
textbookId: '',
levelFirstId: '',
levelSecondId: '',
coursetitle:'',
//
})
// ---------------------------------------------------
//
const getData = (data) => {
const { textBook, node } = data
let textbookId = textBook.curBookId
let levelSecondId = node.id
let levelFirstId
if (node.parentNode) {
levelFirstId = node.parentNode.id
} else {
levelFirstId = node.id
levelSecondId = ''
}
courseObj.textbookId = textbookId //
courseObj.levelFirstId = levelFirstId //
courseObj.levelSecondId = levelSecondId //
courseObj.coursetitle = node.itemtitle // (/)
// ID
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId}))
}
onMounted(() => {
init()
// sourceStore.getCreate()
})
const init = () => {
classWorkForm.uniquekey = userStore.edusubject+'-' + getCurrentTime('MMDD')+'-'+(1);
}
// watch(() => sourceStore.query.fileSource,() => {
// sourceStore.query.fileSource === ''?isThird.value = true:isThird.value = false
// })
</script>
<style lang="scss" scoped>
.page-resource {
padding-top: 10px;
height: 100%;
.el-menu--collapse {
width: 0px;
min-height: 100%;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 300px;
min-height: 100%;
}
.unit-top-left {
cursor: pointer;
.icon-xiangzuo {
margin-right: 5px;
}
}
.classtype-right{
padding: 5px;
margin-bottom: 0px !important;
}
.el-form-item--default{
margin-bottom: 0px !important;
}
.page-right {
min-width: 0;
display: flex;
flex-direction: column;
flex: 1;
margin-left: 20px;
height: 100%;
background: #ffffff;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(99, 99, 99, 0.06);
}
.icon-jiahao {
font-size: 12px;
margin-right: 3px;
font-weight: bold;
}
}
</style>

View File

@ -0,0 +1,242 @@
<template>
<div v-loading="isLoading" class="page-resource flex">
<!--左侧 教材 目录-->
<ChooseTextbook @change-book="getData" @node-click="getData" />
<!--右侧 作业设计/布置 列表 -->
<div class="page-right">
<div class="prepare-body-header">
<el-button @click="handleOutLink('design')">作业设计</el-button>
<el-button @click="handleOutLink('assign')">作业布置</el-button>
<label style="font-size: 15px; margin-left: 20px">{{ listClassWork.length }}个作业</label>&nbsp;
<el-select
v-model="queryParams.workType"
placeholder="作业类型"
size="small"
@change="queryClassWorkByParams"
style="width: 100px; margin-left: auto;"
>
<template v-for="(item, index) in listWorkType" :key="index">
<el-option :label="item.label" :value="item" />
</template>
</el-select>
</div>
<div class="prepare-work-wrap">
<FileListItem
v-for="(item, index) in desingDataList"
:key="index"
:item="item"
:index="index"
@on-set="openSet"
@on-delhomework="delhomework"
>
</FileListItem>
</div>
</div>
<SetHomework v-model="setAssingDialog" :entpcourseid="entpcourseid" :row="curClassWork" />
</div>
</template>
<script setup>
import {ref, onMounted, reactive, watch, nextTick, getCurrentInstance, computed} from 'vue'
import { ElMessage } from 'element-plus'
import { homeworklist, delClasswork } from '@/api/teaching/classwork'
import useResoureStore from '@/views/resource/store'
import useUserStore from '@/store/modules/user'
import useClassTaskStore from "@/store/modules/classTask";
import outLink from '@/utils/linkConfig'
import ChooseTextbook from '@/components/choose-textbook/index.vue'
import FileListItem from '@/views/prepare/container/file-list-item.vue'
import SetHomework from '@/components/set-homework/index.vue'
const { ipcRenderer } = require('electron')
const userStore = useUserStore().user
const classTaskStore = useClassTaskStore()
const {proxy} = getCurrentInstance();
const sourceStore = useResoureStore();
//
const curNode = ref({});
const isLoading = ref(false);
const listClassWork = ref([]);
const listWorkType = ref(['不限', '习题训练', '框架梳理', '课堂展示', '常规作业']);
const isOpenHomework = ref(false);
const curClassWork = ref({});
const setAssingDialog = ref(false);
const entpcourseid = ref(0);
const queryParams = reactive({
workType: '不限',
total: 0,
});
/**
* @desc: 更新作业任务
* @return: {*}
* @param {*} computed
*/
const desingDataList = computed(() => {
return listClassWork.value;
})
/**
* @desc: 选中单元章节后的回调, 获取单元章节信息
* @return: {*}
* @param {*} data
*/
const getData = async (data) => {
if (curNode.value.id == data.node.id) {
return;
}
// 1.
curNode.value = data.node;
listClassWork.value = [];
isLoading.value = true;
console.log(curNode.value);
// 2.
await getClassWorkList();
isLoading.value = false;
}
/**
* @desc: 根据作业类型查询作业模板
* @return: {*}
*/
const queryClassWorkByParams = async () => {
// 1.
listClassWork.value = [];
isLoading.value = true;
// 2.[]
const params = {
worktype: queryParams.workType, // []
}
if (queryParams.workType == '不限') {
delete params.worktype;
}
await getClassWorkList(params);
isLoading.value = false;
}
/**
* @desc: 获取作业设计模板
* @return: {*}
*/
const getClassWorkList = async(params) => {
// homeworklist
let query = {
evalid: curNode.value.id,
edituserid: userStore.userId,
edustage: userStore.edustage,
edusubject: userStore.edusubject,
status: '10',
orderby: 'concat(worktype,uniquekey) DESC',
pageSize: 100,
}
// query
if (params !== null && params !== undefined) {
query = {...query, ...params};
}
const res = await homeworklist(query);
if (res.rows && res.rows.length > 0) {
for (const item of res.rows) {
item.fileShowName = item.uniquekey;
}
listClassWork.value = res.rows;
//TODO total
queryParams.total = res.total
}
}
/**
* @desc: 作业设计/布置
* @return: {*}
* @param {*} key design-设计 assign-布置. 当key为设计时, url需再增加openDialog字段以便自动打开[设计新作业]
*/
const handleOutLink = (key) => {
isOpenHomework.value = true;
// key linkConfig.js
let configObj = outLink()['homeWork']
let fullPath = configObj.fullPath;
//urlunitId ID
let unitId = curNode.value.id;
fullPath += `&unitId=${unitId}`;
// , openDialog[]
if (key == 'design') {
fullPath += `&openDialog=newClassTask`;
}
//
ipcRenderer.send('openWindow', {
key,
fullPath: fullPath,
cookieData: { ...configObj.data }
})
}
const openSet = (item) => {
//
curClassWork.value = item;
setAssingDialog.value = true;
}
const delhomework = (item) => {
isLoading.value = true
delClasswork(item.id)
.then(async(res) => {
ElMessage.success('删除成功');
isLoading.value = false;
await getClassWorkList();
})
.catch(() => {
isLoading.value = false;
})
}
</script>
<style lang="scss" scoped>
.page-resource {
padding-top: 10px;
height: 100%;
//
.page-right {
min-width: 0;
display: flex;
flex-direction: column;
flex: 1;
margin-left: 20px;
height: 100%;
background: #ffffff;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(99, 99, 99, 0.06);
.prepare-body-header {
padding: 10px;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
}
.prepare-work-wrap{
flex: 1;
overflow: auto;
}
}
}
</style>

View File

@ -2,9 +2,9 @@
<div class="desktop-work-item">
<div class="item-title flex">
<span class="title">工作动态</span>
<el-radio-group v-model="type">
<!-- <el-radio-group v-model="type">
<el-radio-button label="全部" :value="-1" />
</el-radio-group>
</el-radio-group> -->
</div>
<div class="item-content" v-loading="loading">
<el-scrollbar height="500px">

View File

@ -45,6 +45,8 @@ import { useRouter } from 'vue-router'
import workTrend from './container/work-trend.vue'
import outLink from '@/utils/linkConfig'
import * as echarts from 'echarts'
import { useGetClassWork } from '@/hooks/useGetClassWork'
const router = useRouter()
const { ipcRenderer } = window.electron || {}
@ -85,7 +87,7 @@ const menuList = [{
// path: '/prepare'
// },
{
name: '教学实',
name: '教学实',
icon: 'icon-jiaoxuefenxi',
path: '/prepare'
},
@ -105,7 +107,11 @@ const menuList = [{
name: '作业设计',
icon: 'icon-jiaoxuefansi',
isOuter: true,
path: '/teaching/classtaskassign?titleName=作业布置&&openDialog=newClassTask'
path: '/teaching/classtaskassign?titleName=作业布置&openDialog=newClassTask'
//path: '/newClassTask'
//path: '/classTaskAssign'
//isOuter: true,
//path: '/teaching/classtaskassign?titleName=&&openDialog=newClassTask'
},
{
name: '作业布置',
@ -160,6 +166,16 @@ const clickMenu = ({isOuter, path, disabled}) =>{
if(isOuter){
let configObj = outLink().getBaseData()
let fullPath = configObj.fullPath + path
if(path == '/teaching/classtaskassign?titleName=作业布置&openDialog=newClassTask' || path == '/teaching/classtaskassign?titleName=作业布置'){
// ID
const { levelFirstId, levelSecondId, bookeId } = JSON.parse(localStorage.getItem('unitId'))
let unitId = levelSecondId ? levelSecondId : levelFirstId
fullPath = fullPath + `&unitId=${unitId}&bookeId=${bookeId}`
console.log(fullPath)
}
fullPath = fullPath.replaceAll('//', '/')
//
ipcRenderer.send('openWindow', {
@ -218,9 +234,22 @@ onMounted(async ()=>{
]
}
chartInstance.setOption(option);
// +
getSubjectInit();
})
const getSubjectInit = async () => {
//
let unitId = localStorage.getItem('unitId')
if(unitId){
//
} else{
// +
useGetClassWork();
}
}
</script>
<style lang="scss" scoped>

View File

@ -260,7 +260,7 @@ onMounted(() => {
<style lang="scss" scoped>
.page-resource {
padding-top: 20px;
padding-top: 10px;
height: 100%;
//

View File

@ -7,7 +7,7 @@
:before-close="handleClose"
>
<el-steps v-if="type==1" style="max-width: 100%;-webkit-app-region: no-drag;height:35px" :active="activeIndex" finish-status="success" simple>
<el-step title="1.基本信息" @click="activeIndex=1" />
<el-step title="1.基本信息" @click="activeIndex=1" style="cursor:pointer"/>
<el-step title="2.在校信息" />
</el-steps>
<el-form
@ -40,9 +40,11 @@
<el-form-item label="所属地区" prop="address" v-if="activeIndex==2">
<el-cascader
style="width:100%"
popper-class="aix-regist-address"
v-model="ruleForm.address"
:options="regionData"
@change="handleChange"
:props="{checkStrictly: true}"
/>
</el-form-item>
<el-form-item label="学校" prop="school" v-if="activeIndex==2">
@ -72,6 +74,7 @@
</el-form-item>
<el-form-item v-if="activeIndex==2">
<div class="centerDiv">
<el-button type="default" @click="activeIndex=1">上一步</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)">立即注册</el-button>
</div>
</el-form-item>
@ -211,12 +214,6 @@ const rules = reactive({
message: '请选择地址',
trigger: 'change',
},],
class:[ {
type:'array',
required: true,
message: '请选择班级',
trigger: 'change',
},],
discipline:[ {
type: 'array',
required: true,
@ -300,7 +297,6 @@ const nextStep = (formEl) => {
}
})
getSubject()
console.log(res)
})
console.log('submit!')
}
@ -314,7 +310,8 @@ const getSubject = async ()=>{
const rows= await listEvaluation({ itemkey: "subject", pageSize: 500 })
console.log(rows,'所有学科')
allSubjectList.value = rows.data
accessToDisciplines()
getClassmain()
}
const submitForm = async (formEl) => {
@ -425,9 +422,15 @@ const sbmitImg=()=>{
const handleChange = (value) => {
console.log('选中的地址值:', value);
};
const handleSchoolChange= async ()=>{
const handleSchoolChange= ()=>{
ruleForm.discipline=[];
ruleForm.class=[];
//
accessToDisciplines()
getClassmain()
}
//
const accessToDisciplines = () => {
getDept({deptId:ruleForm.school[2]}).then(res =>{
if(res.data.studying && res.data.studying.length){
let studying = res.data.studying.split(',')
@ -450,11 +453,12 @@ const handleSchoolChange= async ()=>{
schoolSubject.value = []
}
})
listClassmain( {entpid: ruleForm.school[2], pageSize: 500, status: 'open'}).then(res=>{
}
//
const getClassmain = async ()=>{
console.log(ruleForm.school)
const res = await listClassmain( {entpid: ruleForm.school[2], pageSize: 500, status: 'open'})
gradeTree.value = groupByCondition(res.rows, item => item.agekey);
console.log(gradeTree.value,'班级')
})
}
//
const groupByCondition = (arr, condition)=>{
@ -490,7 +494,10 @@ const gradeName = (key) =>{
}
}
onMounted(()=>{
//
ruleForm.address = ['50']
//
ruleForm.school = [100,255,279]
})
defineExpose({
OpenModel,
@ -504,4 +511,17 @@ defineExpose({
display: flex;
justify-content: center;
}
</style>
<style lang="scss">
.aix-regist-address{
.el-cascader-node{
position: relative!important;
.el-radio{
position: absolute!important;
width: 90%!important;
left:5px!important;
}
}
}
</style>

View File

@ -2,7 +2,7 @@
<div class="login-container">
<div class="box-item desc">
<div class="welcome">
<p>欢迎登录 AIX智慧课堂</p>
<p>欢迎登录 {{homeTitle}}</p>
</div>
<img class="welcome-img" :src="leftBg2" />
</div>
@ -93,6 +93,7 @@ const rules = reactive({
})
let curWinUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
ipcRenderer.on('update-app-progress', (e, prop) => {
downloadProp.value = prop
showDownLoading.value = prop !== 100

View File

@ -89,6 +89,8 @@ const userStore = useUserStore()
const visible = ref(false) //
const myClassActive = ref({}) // APT
const imChatRef = ref(null) // im-chat ref
const emit = defineEmits(['close'])
const classForm = reactive({ // ()
form: {}, itemOption: [], option: {}
})
@ -119,73 +121,25 @@ onMounted(() => {
*/
const open = async (id) => {
visible.value = true
if (id) {
//
reset()
// apt
if (id) await getAptInfo(id)
//
// myClassActive.value = {
// "createBy": null,
// "createTime": null,
// "updateBy": null,
// "updateTime": null,
// "remark": null,
// "id": 14740,
// "idarray": null,
// "jsonarray": null,
// "entpid": 255,
// "parentid": 14741,
// "linkids": "",
// "linklist": "",
// "entpcourseid": 7300,
// "entpcourseidarray": null,
// "evalid": 39952,
// "evaltitle": " ",
// "coursetitle": " ",
// "classid": 0,
// "ppttype": "file",
// "title": " ",
// "fileidx": 0,
// "fileurl": "",
// "pathfile": null,
// "filetype": "ppt",
// "filesize": null,
// "datacontent": "",
// "filekey": "",
// "filetag": "",
// "dflag": 0,
// "status": "",
// "edituserid": 2781,
// "editusername": "",
// "edituserheadimgurl": "/profile/avatar/2024/08/12/blob_20240812152930A001.jpeg",
// "edituserentpname": "AIx",
// "editstudentid": null,
// "editstudentname": null,
// "timestamp": "2024-09-10 15:07:20",
// "token": null,
// "base64Code": null,
// "orderby": null,
// "childcount": 4,
// "commentlikecount": 0,
// "commenttextcount": 0,
// "commentusecount": 0,
// "commentvisitcount": 90,
// "unixstamp": null,
// "classworkcount": 0,
// "classworklist": "",
// "authjson": "",
// "defaultslide": null
// }
await getAptInfo(id)
//
getClassList()
// im-chat
// nextTick(async() => {
// chat = await imChatRef.value?.initImChat()
// })
nextTick(async() => {
chat = await imChatRef.value?.initImChat()
})
}
}
//
const handleClose = async () => {
reset() //
await chat?.logout()
chat = null
emit('close')
}
// -
const initData = () => {
@ -204,6 +158,15 @@ const initData = () => {
{ label: '故障备用', prop: 'backup', show: false },
]
}
//
const reset = () => {
// -
classForm.form = {}
teacherForm.form = { classcourseid: 0 }
dt.isCreate = false
dt.isHistory = false
dt.atCourse = {}
}
// APT
const getAptInfo = async (id) => {
const res = await Http_Entpcoursefile.getEntpcoursefile(id)

View File

@ -1,6 +1,6 @@
<template>
<div class="file-oper-batch-wrap">
<div style="margin: 0 20px; line-height: 40px">
<div style="line-height: 40px">
<el-checkbox
v-model="isCheckAll"
:indeterminate="indeterminate"
@ -15,7 +15,7 @@
</template>
<script>
import { deleteSmarttalkBatch } from '@/api/file'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ElMessage } from 'element-plus'
import { exportFile } from '@/utils/talkFile'
export default {
name: 'FileOperBatch',

View File

@ -52,6 +52,7 @@
</div>
</div>
<div class="prepare-body-main-item-btn">
<!-- <el-button v-if="activeClassId==item.id" type="success" @click="clickStartClass(item)">上课中</el-button> -->
<el-button type="primary" @click="clickStartClass(item)">上课</el-button>
</div>
<div class="prepare-body-main-item-tool">
@ -65,18 +66,20 @@
<template #default>
<div style="width: 100%">
<div class="item-popover" @click="closePopver(index)">
<div v-if="userInfo.userId === Number(item.createUserId)" class="item-popover-item">
<template v-if="userInfo.userId === Number(item.createUserId)">
<div class="item-popover-item">
<el-button text @click="editTalk(item, index)">
<i class="iconfont icon-bianji"></i>
<span>标签</span>
</el-button>
</div>
<div v-if="userInfo.userId === Number(item.createUserId)" class="item-popover-item">
<div class="item-popover-item">
<el-button text @click="deleteTalk(item)">
<i class="iconfont icon-shanchu"></i>
<span>删除</span>
</el-button>
</div>
</template>
</div>
</div>
</template>
@ -98,12 +101,19 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { deleteSmarttalk, updateSmarttalk, getPrepareById } from '@/api/file'
import useUserStore from '@/store/modules/user'
import outLink from '@/utils/linkConfig'
import { sessionStore } from '@/utils/store'
const { ipcRenderer } = window.electron || {}
export default {
name: 'FileListItem',
components: { FileImage },
props: {
curNode: {
type: Object,
default: function () {
return {}
}
},
item: {
type: Object,
default: function () {
@ -115,6 +125,10 @@ export default {
default: function () {
return 0
}
},
activeClassId: { // id
type: String,
default: ''
}
},
emits: { 'on-start-class': null, 'on-delete': null, 'on-set': null, 'on-delhomework': null,'on-filearg': null },
@ -193,8 +207,9 @@ export default {
},
openFileWin(items) {
if (items.fileFlag === 'apt') {
console.log(items);
const path="/teaching/aptindex?id="+items.fileId
console.log(this.curNode);
let curBook = JSON.parse(localStorage.getItem('curBook'))
const path="/teaching/aptindex?id="+items.fileId + "&unitId=" + this.curNode.id + "&bookId=" + curBook.id;
let configObj = outLink().getBaseData()
let fullPath = configObj.fullPath + path
fullPath = fullPath.replaceAll('//', '/')

View File

@ -86,7 +86,7 @@ import useUserStore from '@/store/modules/user'
import { ElMessage } from 'element-plus'
import { getCurrentTime, getAfterMinutes } from '@/utils/date'
const emit = defineEmits(['addSuccess'])
const emit = defineEmits(['addSuccess','close'])
const props = defineProps({
bookId: {
type: Number,
@ -115,7 +115,7 @@ const updateForm = ref({})
watch(
() => props.currentNode,
(newValue, oldValue) => {
form.name = newValue.label
form.name = newValue.itemtitle
}
)
const ruleForm = reactive({
@ -216,7 +216,9 @@ const openDialog = (data) => {
const closeDialog = () => {
ruleFormDialog.value.resetFields()
centerDialogVisible.value = false
form.name = props.currentNode.label
form.name = props.currentNode.itemtitle
emit('close')
}
const classList = ref([])
onMounted(() => {

View File

@ -20,6 +20,7 @@
:key="index"
:item="item"
:index="index"
:curNode="currentNode"
@on-delete="deleteTalk"
@on-start-class="startClass"
>
@ -68,7 +69,7 @@
<el-tab-pane label="素材" name="素材">
<div class="prepare-body-header">
<div>
<label style="font-size: 15px">{{ currentFileList.length }}个文件</label>&nbsp;
<label style="font-size: 15px">{{ currentFileList.filter(ite=>ite.fileFlag!=='apt'&&ite.fileFlag!=='课件').length }}个文件</label>&nbsp;
<el-popover placement="top-start" :width="250" trigger="hover">
<template #default>
<div>
@ -115,13 +116,13 @@
</el-checkbox-group>
</el-tab-pane>
<el-tab-pane label="作业" name="作业">
<div class="prepare-body-header">
<!-- <div class="prepare-body-header">
<div>
<label style="font-size: 15px">{{ currentWorkList.length }}个作业</label>&nbsp;
<el-button size="small" @click="handleOutLink('feedback')">作业反馈</el-button>
<el-button size="small" @click="handleOutLink('homeWork')">布置作业</el-button>
</div>
</div>
</div>-->
<div class="prepare-work-wrap">
<file-list-item
v-for="(item, index) in currentWorkList"
@ -140,7 +141,7 @@
</div>
<file-oper-batch
v-show="checkFileList.length > 0"
:indeterminate="checkFileList.length > 0 && checkFileList.length < currentFileList.length"
:indeterminate="checkFileList.length > 0 && checkFileList.length < currentSCFileList.length"
:choose="checkFileList"
:check-all="isCheckAll"
@click-delete="clickDelete"
@ -158,9 +159,10 @@
:current-node="currentNode"
:book-id="uploadData.textbookId"
@add-success="initReserv"
@close="closeChange"
></reserv>
<!-- 上课配置 -->
<class-start ref="calssRef"/>
<class-start ref="calssRef" @close="closeChange"/>
</template>
<script setup>
import { Check,Plus } from '@element-plus/icons-vue'
@ -192,7 +194,7 @@ import { getClassInfo, getSelfReserv } from '@/api/classManage'
import { useGetHomework } from '@/hooks/useGetHomework'
import { addEntpcoursefileReturnId } from '@/api/education/entpcoursefile'
import ClassReserv from '@/views/classManage/classReserv.vue'
import classStart from '@/views/desktop/container/class-start.vue' //
import classStart from './container/class-start.vue' //
const toolStore = useToolState()
const fs = require('fs')
@ -246,13 +248,15 @@ export default {
//
setDialog: false,
row: '',
isOpenHomework: false
isOpenHomework: false,
//
activeClass: null,
}
},
computed: {
isCheckAll() {
return (
this.checkFileList.length > 0 && this.checkFileList.length === this.currentFileList.length
this.checkFileList.length > 0 && this.checkFileList.length === this.currentSCFileList.length
)
},
currentKJFileList() {
@ -272,6 +276,9 @@ export default {
})
this.lastAsyncAllTime = localStorage.getItem('lastAsyncAllTime')
// this.initReserv()
// zdg:
this.activeClass = sessionStore.get('activeClass') || null
},
mounted() {
this.$watch(
@ -298,15 +305,25 @@ export default {
// },
methods: {
startClass(item) {
console.log(item)
// console.log(item, sessionStore)
// ()
const id = sessionStore.has('activeClass.id') ? sessionStore.get('activeClass.id') : null
if (id && id == item.id) return ElMessage.warning('当前正在上课,请勿重复操作')
if(item.fileFlag === '课件') {
this.openReserv()
}
if(item.fileFlag === 'apt') {
//TODO apt
const { fileId: aptId } = item
this.$refs.calssRef.open(aptId)
//TODO apt - fileId: aptId
this.$refs.calssRef.open(item.fileId)
}
// -store
sessionStore.set('activeClass', item)
this.activeClass = item
},
closeChange() { // -
console.log('关闭上课弹窗')
this.activeClass = null
sessionStore.delete('activeClass')
},
initReserv(id) {
getClassInfo(id).then((res) => {
@ -352,7 +369,7 @@ export default {
this.downloadNum = num
},
createFile() {
creatPPT(this.currentNode.label + '.pptx', this.uploadData).then((res) => {
creatPPT(this.currentNode.itemtitle + '.pptx', this.uploadData).then((res) => {
this.currentFileList.unshift(res.resData)
})
},
@ -432,7 +449,7 @@ export default {
creatAPT({
...this.uploadData,
fileId: slideid,
fileShowName: this.currentNode.label + '.apt'
fileShowName: this.currentNode.itemtitle + '.apt'
}).then((res) => {
this.currentFileList.unshift(res.resData)
})
@ -649,7 +666,7 @@ export default {
'/tool/sphere?entpcourseid=' +
this.entpcourseid +
'&label=' +
this.currentNode.label +
this.currentNode.itemtitle +
'&reservId=' +
id
})

View File

@ -30,9 +30,9 @@
<li class="list-group-item">
<div class="left-align">
<Message class="Message"/>
<span>用户邮箱</span>
<span>身份证号</span>
</div>
<div class="right-align">{{ state.user.email }}</div>
<div class="right-align">{{ state.user.identity }}</div>
</li>
<li class="list-group-item">
<div class="left-align">
@ -48,7 +48,7 @@
<Avatar class="Avatar"/>
<span>所属角色</span>
</div>
<div class="right-align">{{ state.roleGroup }}</div>
<div class="right-align">{{ state.roleGroup || '教师' }}</div>
</li>
<li class="list-group-item">
<div class="left-align">

View File

@ -6,10 +6,10 @@
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="user.phonenumber" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="user.email" maxlength="50" />
<el-form-item label="身份证号" prop="identity">
<el-input v-model="user.identity" maxlength="50" />
</el-form-item>
<el-form-item label="性别">
<el-form-item label="性别" style="display: none">
<el-radio-group v-model="user.sex">
<el-radio value="0"></el-radio>
<el-radio value="1"></el-radio>
@ -18,8 +18,8 @@
<el-form-item label="学段">
<el-radio-group v-model="user.edustage" @change="semeterChange">
<template v-for="(item,index) in semesterList" :key="index">
<el-radio :value="item.title">
{{item.title }}
<el-radio :value="item.label">
{{item.label }}
</el-radio>
</template>
</el-radio-group>
@ -42,9 +42,11 @@
<script setup>
import { ref, getCurrentInstance,onMounted } from 'vue'
import {updateUserInfo } from '@/api/system/user'
import {getDept } from '@/api/login'
import { listEvaluation } from '@/api/subject/index'
import useUserStore from '@/store/modules/user'
import {ElMessage} from 'element-plus'
import { clearBookInfo } from '@/utils/ruoyi'
const props = defineProps({
user: {
@ -59,21 +61,30 @@ const userStore = useUserStore()
const semesterList = ref([
{
id:1,
title:'幼儿园'
label:'幼儿园'
},
{
id:2,
title:'小学'
label:'小学'
},
{
id:3,
title:'初中'
label:'初中'
},
{
id:4,
title:'高中'
label:'高中'
},
])
//
const getTheSection = () => {
getDept({deptId:userStore.user.deptId}).then(res => {
//
const arr = res.data.studying.split(',')
semesterList.value = semesterList.value.filter(items => {return arr.includes(items.label)}).map(item => item)
})
}
const rules = ref({
nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
@ -137,8 +148,7 @@ function submit() {
userStore.login({username:props.user.userName,password:props.user.plainpwd}).then(() => {
userStore.getInfo().then(res => {
if(res.code === 200){
localStorage.removeItem('subjectList')
localStorage.removeItem('evaluationList')
clearBookInfo()
ElMessage.success('修改成功')
}else{
ElMessage.error(response.msg)
@ -159,5 +169,6 @@ const semeterChange = (item) => {
}
onMounted(() => {
getSubject()
getTheSection()
})
</script>

View File

@ -38,7 +38,7 @@ const curBookId = ref('')
const evaluationList = ref([])
const getTreeData = () => {
evaluationList.value = JSON.parse(localStorage.getItem('evaluationList'))
evaluationList.value = JSON.parse(localStorage.getItem('unitList'))
//
/**

View File

@ -57,6 +57,8 @@ class Drag {
document.removeEventListener('mouseup', this.up);
document.addEventListener('touchmove', this.move);
document.addEventListener('touchend', this.up);
// 手动-触发事件 v-drag-start
this.el.dispatchEvent(new CustomEvent('v-drag-end', {detail:{drag: this}}))
}
// 业务逻辑
updatePosition(e) {
@ -108,6 +110,7 @@ export default {
// const { style } = binding.value
const drag = new Drag(el, binding)
const dragStart = (e) => {
// console.log('start', e)
drag.down(e)
document.addEventListener('mousemove', drag.move);
document.addEventListener('mouseup', drag.up);

View File

@ -10,10 +10,11 @@
<upvote-vue ref="upvoteRef" type="2"></upvote-vue>
<!-- im-chat 聊天组件 -->
<im-chat ref="imChatRef" @change="chatChange" isGroup />
<im-chat ref="imChatRef" @change="chatChange" group />
<!-- 底部工具栏 -->
<div class="tool-bottom-all" @mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
<div class="tool-bottom-all"
@mouseenter="mouseChange(0)" @mouseleave="mouseChange(1)">
<div v-drag="{handle:'.tool-bottom-all', dragtime}"
@v-drag-start="dragtime = Date.now()">
<div class="c-logo" @click="logoHandle" title="拖动 | 折叠 | 展开">
@ -106,7 +107,7 @@ const getClassInfo = async () => {
const tabChange = (val) => {
const bool = !toolStore.isPdfWin && !toolStore.showBoardAll
if(bool) toolStore.showBoardAll = true
console.log('tabChange:', val, bool)
// console.log('tabChange:', val, bool)
toolStore.model = val // tab
}
// logo - |
@ -143,9 +144,12 @@ const mouseChange = (bool) => {
const isPdf = !resBool && toolStore.isPdfWin
if (isPdf) resBool = true
}
// console.log('mouseChange:', bool, resBool)
console.log('mouseChange:', bool, resBool)
setIgnore(resBool)
}
const touchChange = (e) => {
console.log(e)
}
// im-chat: {type, data}
const chatChange = (type, data, ...args) => {
if (type == 'createGroup') { // -