diff --git a/.env.production b/.env.production index 05e26a6..e103054 100644 --- a/.env.production +++ b/.env.production @@ -18,4 +18,4 @@ VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktx VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/' -VITE_SHOW_DEV_TOOLS = 'true' +VITE_SHOW_DEV_TOOLS = 'false' diff --git a/.env.test b/.env.test index 3d671e1..ea57966 100644 --- a/.env.test +++ b/.env.test @@ -17,3 +17,5 @@ VITE_BUILD_COMPRESS = gzip VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktxt/' VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/' + +VITE_SHOW_DEV_TOOLS = 'true' diff --git a/.env.old b/.env.yc similarity index 89% rename from .env.old rename to .env.yc index 8640aa3..e103054 100644 --- a/.env.old +++ b/.env.yc @@ -1,5 +1,5 @@ # 页面标题 -VITE_APP_TITLE = AIX智慧课堂 +VITE_APP_TITLE = 文枢课堂 # 生产环境配置 VITE_APP_ENV = 'production' @@ -17,3 +17,5 @@ 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/' + +VITE_SHOW_DEV_TOOLS = 'false' diff --git a/electron-builder-old.yml b/electron-builder-yc.yml similarity index 84% rename from electron-builder-old.yml rename to electron-builder-yc.yml index 9dfb51e..c3fddbc 100644 --- a/electron-builder-old.yml +++ b/electron-builder-yc.yml @@ -1,10 +1,10 @@ appId: com.electron.app -productName: AIx +productName: 文枢课堂 directories: output: dist buildResources: build win: - executableName: AIx + executableName: 文枢课堂 icon: resources/logo2.ico files: - '!**/.vscode/*' @@ -17,7 +17,7 @@ asarUnpack: nsis: oneClick: false allowToChangeInstallationDirectory: true - artifactName: ${name}-${version}-setup.${ext} + artifactName: ${name}-yc-${version}-setup.${ext} shortcutName: ${productName} uninstallDisplayName: ${productName} createDesktopShortcut: always @@ -30,7 +30,7 @@ mac: - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. notarize: false dmg: - artifactName: ${name}-${version}.${ext} + artifactName: ${name}-yc-${version}.${ext} linux: target: - AppImage @@ -39,11 +39,11 @@ linux: maintainer: electronjs.org category: Utility appImage: - artifactName: ${name}-${version}.${ext} + artifactName: ${name}-yc-${version}.${ext} npmRebuild: false publish: provider: generic - url: https://prev.ysaix.com:7868/src/assets/smarttalk/ + url: https://prev.ysaix.com:7868/src/assets/smarttalkyc/ electronDownload: mirror: https://npmmirror.com/mirrors/electron/ # 额外依赖打包到输出目录 diff --git a/package.json b/package.json index 75da1f6..57803ba 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "aix-win", - "version": "2.1.12", + "version": "2.1.36", "description": "", "main": "./out/main/index.js", - "author": "example.com", + "author": "上海交大重庆人工智能研究院", "homepage": "https://electron-vite.org", "scripts": { "format": "prettier --write .", @@ -16,7 +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:yc": "electron-vite build --mode yc && electron-builder --win --config ./electron-builder-yc.yml", "build:mac": "electron-vite build --mode production && electron-builder --mac --config ./electron-builder-prod.yml", "build:linux": "npm run build && electron-builder --linux" }, diff --git a/src/main/index.js b/src/main/index.js index 87a0ef1..22f49a2 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -46,7 +46,7 @@ if(!gotTheLock){ function createLoginWindow() { if (loginWindow) return loginWindow = new BrowserWindow({ - width: 888, + width: import.meta.env.MODE==='yc'?1160:888, height: 520, show: false, frame: false, @@ -175,6 +175,7 @@ async function createLinkWin(data) { data.fullPath += '?urlSource=smarttalk&t' + Date.now() } linkWin[data.key].loadURL(data.fullPath) + if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') linkWin[data.key].webContents.openDevTools() linkWin[data.key].once('ready-to-show', () => { linkWin[data.key].show() @@ -271,12 +272,13 @@ app.on('window-all-closed', () => { function handleAll() { const chatInstance = chat.initialize() // im-chat 实例 // 新窗口创建-监听 - ipcMain.on('new-window', (e, data) => { + ipcMain.handle('new-window', (e, data) => { const { id, type } = data const win = BrowserWindow.fromId(id) win.type = type // 绑定独立标识 remote.enable(win.webContents) // 开启远程服务 chatInstance.enable(win.webContents) // 开启im-chat + console.log(`主进程 [${type}]: 窗口注册-远程代理-完毕(${Date.now()})`) }) // 用于监听-状态管理变化-同步所有窗口 ipcMain.handle('pinia-state-change', (e, storeName, jsonStr) => { diff --git a/src/main/store.js b/src/main/store.js index a34bd90..22e61dd 100644 --- a/src/main/store.js +++ b/src/main/store.js @@ -23,7 +23,9 @@ const defaultData = { curNode: null, // 当前选中的节点 defaultExpandedKeys: [], //展开的节点 subjectTree: [] // "树结构" 章节 - } + }, + env: {}, // 不走同步 Pinia - 变量 + curr: {} // 不走同步 Pinia - 当前信息 }, local: { // 本地(永久localStorage) }, diff --git a/src/renderer/src/api/classTask/index.js b/src/renderer/src/api/classTask/index.js index bf03614..8a95531 100644 --- a/src/renderer/src/api/classTask/index.js +++ b/src/renderer/src/api/classTask/index.js @@ -71,6 +71,16 @@ export function updateClassworkeval(data) { }) } + +// 修改classworkeval +export function updateClassworkevalList(data) { + return request({ + url: '/education/classworkeval/updateList', + method: 'put', + data: data + }) +} + // 修改classworkdata export function updateClassworkdata(data) { return request({ @@ -79,6 +89,13 @@ export function updateClassworkdata(data) { data: data }) } +export function updateClassWorkDataAutoFinish(data) { + return request({ + url: '/education/classworkdata/updAutoFinish', + method: 'put', + data: data + }) +} // 修改classwork export function updateClasswork(data) { @@ -108,90 +125,90 @@ export function addClassworkeval(data) { // 查询evaluationclue列表 export function listEvaluationclue(query) { return request({ - url: '/education/evaluationclue/list', - method: 'get', - params: query + url: '/education/evaluationclue/list', + method: 'get', + params: query }) } // 查询evaluationclue详细 export function getEvaluationclue(id) { return request({ - url: '/education/evaluationclue/' + id, - method: 'get' + url: '/education/evaluationclue/' + id, + method: 'get' }) } // 新增evaluationclue export function addEvaluationclueReturnId(data) { return request({ - url: '/education/evaluationclue/addReturnId', - method: 'post', - data: data + url: '/education/evaluationclue/addReturnId', + method: 'post', + data: data }) } // 新增evaluationclue export function addEvaluationclue(data) { return request({ - url: '/education/evaluationclue', - method: 'post', - data: data + url: '/education/evaluationclue', + method: 'post', + data: data }) } // 修改evaluationclue export function updateEvaluationclue(data) { return request({ - url: '/education/evaluationclue', - method: 'put', - data: data + url: '/education/evaluationclue', + method: 'put', + data: data }) } // 删除evaluationclue export function delEvaluationclue(id) { return request({ - url: '/education/evaluationclue/' + id, - method: 'delete' + url: '/education/evaluationclue/' + id, + method: 'delete' }) } // 新增evaluationclue,保存base64图片 export function saveBase64File(data) { return request({ - url: '/education/evaluationclue/saveBase64File', - method: 'post', - data: data + url: '/education/evaluationclue/saveBase64File', + method: 'post', + data: data }) } // 新增evaluationclue,上传 export function saveEvaluationClueUploadFile(data) { return request({ - url: '/education/evaluationclue/saveUploadFile', - method: 'post', - data: data + url: '/education/evaluationclue/saveUploadFile', + method: 'post', + data: data }) } // 读取文件内容 export function readFile(data) { return fetch(import.meta.env.VITE_APP_RES_FILE_PATH + data.cluelink, { - method: "get", - headers: { - 'Content-Type': 'text/plain', // 请求头设置为纯文本 - 'Accept': 'text/plain' // 接受头设置为纯文本 - }, + method: "get", + headers: { + 'Content-Type': 'text/plain', // 请求头设置为纯文本 + 'Accept': 'text/plain' // 接受头设置为纯文本 + }, }) - .then(response => response.text()) - .then(text => { - return Promise.resolve(text); - }) - .catch(error => { - console.error('读取文件出错:', error); - return Promise.reject(); - }); + .then(response => response.text()) + .then(text => { + return Promise.resolve(text); + }) + .catch(error => { + console.error('读取文件出错:', error); + return Promise.reject(); + }); /*return request({ url: '/education/evaluationclue/readFile', method: 'post', diff --git a/src/renderer/src/api/file/index.js b/src/renderer/src/api/file/index.js index e655614..7d401d6 100644 --- a/src/renderer/src/api/file/index.js +++ b/src/renderer/src/api/file/index.js @@ -24,6 +24,13 @@ export const getPrepareById = (id) => { }) } +export const addFileToKj = (id) => { + return request({ + url: '/smarttalk/file/addFileToKj/' + id, + method: 'get' + }) +} + export function deleteSmarttalk(id) { return request({ url: '/smarttalk/file/' + id, @@ -53,3 +60,14 @@ export const moveSmarttalk = (params) => { params }) } + +export const addFileToPrepareThird = (data) => { + return request({ + url: '/smarttalk/file/addFileToPrepareThird', + method: 'post', + headers: { + 'Content-Type': 'multipart/form-data' + }, + data + }) +} diff --git a/src/renderer/src/assets/iconfont/iconfont.css b/src/renderer/src/assets/iconfont/iconfont.css index 75ba33d..f13d533 100644 --- a/src/renderer/src/assets/iconfont/iconfont.css +++ b/src/renderer/src/assets/iconfont/iconfont.css @@ -1,9 +1,9 @@ @font-face { font-family: "iconfont"; /* Project id 2794390 */ - src: url('iconfont.woff2?t=1728543886557') format('woff2'), - url('iconfont.woff?t=1728543886557') format('woff'), - url('iconfont.ttf?t=1728543886557') format('truetype'), - url('iconfont.svg?t=1728543886557#iconfont') format('svg'); + src: url('iconfont.woff2?t=1732002934577') format('woff2'), + url('iconfont.woff?t=1732002934577') format('woff'), + url('iconfont.ttf?t=1732002934577') format('truetype'), + url('iconfont.svg?t=1732002934577#iconfont') format('svg'); } .iconfont { @@ -14,6 +14,26 @@ -moz-osx-font-smoothing: grayscale; } +.icon-a-shiyanpingshiyanyanjiu:before { + content: "\e9a0"; +} + +.icon-banji2:before { + content: "\e6c0"; +} + +.icon-set:before { + content: "\e691"; +} + +.icon-shouye:before { + content: "\e637"; +} + +.icon-gongzuotai:before { + content: "\e690"; +} + .icon-A1:before { content: "\e635"; } diff --git a/src/renderer/src/assets/iconfont/iconfont.js b/src/renderer/src/assets/iconfont/iconfont.js index e5c0dbb..9d75b40 100644 --- a/src/renderer/src/assets/iconfont/iconfont.js +++ b/src/renderer/src/assets/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_2794390='',(c=>{var h=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var a,t,i,z,p,v=function(h,l){l.parentNode.insertBefore(h,l)};if(h&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(h){console&&console.log(h)}}a=function(){var h,l=document.createElement("div");l.innerHTML=c._iconfont_svg_string_2794390,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(h=document.body).firstChild?v(l,h.firstChild):h.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(a,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),a()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(i=a,z=c.document,p=!1,d(),z.onreadystatechange=function(){"complete"==z.readyState&&(z.onreadystatechange=null,M())})}function M(){p||(p=!0,i())}function d(){try{z.documentElement.doScroll("left")}catch(h){return void setTimeout(d,50)}M()}})(window); \ No newline at end of file +window._iconfont_svg_string_2794390='',(c=>{var l=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var a,t,i,z,p,v=function(l,h){h.parentNode.insertBefore(l,h)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}a=function(){var l,h=document.createElement("div");h.innerHTML=c._iconfont_svg_string_2794390,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(l=document.body).firstChild?v(h,l.firstChild):l.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(a,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),a()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(i=a,z=c.document,p=!1,d(),z.onreadystatechange=function(){"complete"==z.readyState&&(z.onreadystatechange=null,M())})}function M(){p||(p=!0,i())}function d(){try{z.documentElement.doScroll("left")}catch(l){return void setTimeout(d,50)}M()}})(window); \ No newline at end of file diff --git a/src/renderer/src/assets/iconfont/iconfont.json b/src/renderer/src/assets/iconfont/iconfont.json index de96ea7..d2cf203 100644 --- a/src/renderer/src/assets/iconfont/iconfont.json +++ b/src/renderer/src/assets/iconfont/iconfont.json @@ -1,10 +1,45 @@ { "id": "2794390", - "name": "electron", + "name": "文枢2.1", "font_family": "iconfont", "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "41507853", + "name": "实验瓶", + "font_class": "a-shiyanpingshiyanyanjiu", + "unicode": "e9a0", + "unicode_decimal": 59808 + }, + { + "icon_id": "1017928", + "name": "班级", + "font_class": "banji2", + "unicode": "e6c0", + "unicode_decimal": 59072 + }, + { + "icon_id": "376364", + "name": "设置", + "font_class": "set", + "unicode": "e691", + "unicode_decimal": 59025 + }, + { + "icon_id": "5835474", + "name": "首页", + "font_class": "shouye", + "unicode": "e637", + "unicode_decimal": 58935 + }, + { + "icon_id": "19108133", + "name": "工作台", + "font_class": "gongzuotai", + "unicode": "e690", + "unicode_decimal": 59024 + }, { "icon_id": "11657531", "name": "A", diff --git a/src/renderer/src/assets/iconfont/iconfont.svg b/src/renderer/src/assets/iconfont/iconfont.svg index 105c931..76a5447 100644 --- a/src/renderer/src/assets/iconfont/iconfont.svg +++ b/src/renderer/src/assets/iconfont/iconfont.svg @@ -14,6 +14,16 @@ /> + + + + + + + + + + diff --git a/src/renderer/src/assets/iconfont/iconfont.ttf b/src/renderer/src/assets/iconfont/iconfont.ttf index efbbc57..1a9b595 100644 Binary files a/src/renderer/src/assets/iconfont/iconfont.ttf and b/src/renderer/src/assets/iconfont/iconfont.ttf differ diff --git a/src/renderer/src/assets/iconfont/iconfont.woff b/src/renderer/src/assets/iconfont/iconfont.woff index 8fd280e..8a98877 100644 Binary files a/src/renderer/src/assets/iconfont/iconfont.woff and b/src/renderer/src/assets/iconfont/iconfont.woff differ diff --git a/src/renderer/src/assets/iconfont/iconfont.woff2 b/src/renderer/src/assets/iconfont/iconfont.woff2 index f0667a9..6d80dc0 100644 Binary files a/src/renderer/src/assets/iconfont/iconfont.woff2 and b/src/renderer/src/assets/iconfont/iconfont.woff2 differ diff --git a/src/renderer/src/assets/images/login/yc-logo.png b/src/renderer/src/assets/images/login/yc-logo.png new file mode 100644 index 0000000..59db44e Binary files /dev/null and b/src/renderer/src/assets/images/login/yc-logo.png differ diff --git a/src/renderer/src/assets/images/login/ycpeitu.png b/src/renderer/src/assets/images/login/ycpeitu.png new file mode 100644 index 0000000..433a296 Binary files /dev/null and b/src/renderer/src/assets/images/login/ycpeitu.png differ diff --git a/src/renderer/src/components/choose-textbook/index.vue b/src/renderer/src/components/choose-textbook/index.vue index 3c4414d..9f6c27d 100644 --- a/src/renderer/src/components/choose-textbook/index.vue +++ b/src/renderer/src/components/choose-textbook/index.vue @@ -139,16 +139,23 @@ const handleNodeClick = (data) => { * data : 当前节点数据 */ let nodeData = cloneDeep(toRaw(data)); - //增加一个label 之前取的label nodeData.label = nodeData.itemtitle - // 父级节点 如果当前是一级节点 父级则为null - let parent = { - id: nodeData.parentid, - label: nodeData.parenttitle, - itemtitle: nodeData.parenttitle - } - const parentNode = nodeData.parentid ? parent : null + + let parentNode + // 存在children 则为一级节点 + if(nodeData.children){ + // 为一级节点 + parentNode = null + } + else{ + parentNode = { + id: nodeData.parentid, + label: nodeData.parenttitle, + itemtitle: nodeData.parenttitle + } + } + nodeData.parentNode = parentNode let curData = { textBook: { diff --git a/src/renderer/src/components/exam-question/examDetailsDrawer.vue b/src/renderer/src/components/exam-question/examDetailsDrawer.vue new file mode 100644 index 0000000..12de43c --- /dev/null +++ b/src/renderer/src/components/exam-question/examDetailsDrawer.vue @@ -0,0 +1,74 @@ + + + + + + \ No newline at end of file diff --git a/src/renderer/src/components/set-homework/index.vue b/src/renderer/src/components/set-homework/index.vue index 17127b8..a237a80 100644 --- a/src/renderer/src/components/set-homework/index.vue +++ b/src/renderer/src/components/set-homework/index.vue @@ -213,7 +213,7 @@ const delStudent = (index) => { const onSubmit = (formEl) => { if (!formEl) return // 课堂id - const classRoomId = sessionStore.get('curClassRoom.id') + const classRoomId = sessionStore.get('curr.curClassRoom.id') formEl.validate((valid) => { if (valid) { /** @@ -244,7 +244,8 @@ const onSubmit = (formEl) => { entpcourseworklist: '[' + props.rows[i].entpcourseworklist + ']', needMsgNotifine: 'false', msgkey: 'newclasswork', - title: '作业任务', + //title: '作业任务', + title: props.rows[i].title, msgcontent: '', teachername: userInfo.nickName, unixstamp: new Date().getTime(), @@ -254,14 +255,16 @@ const onSubmit = (formEl) => { ary.push(obj) } } + console.log('ary->', ary) setLoading.value = true saveByClassWorkArray({ classworkarray: JSON.stringify(ary) }) .then((res) => { + setLoading.value = false ElMessage.success('操作成功') - emit('on-success', res.data) + emit('on-success', res) cloneDialog(formEl) }) .catch(() => { diff --git a/src/renderer/src/components/thirdFile-preview/index.vue b/src/renderer/src/components/thirdFile-preview/index.vue new file mode 100644 index 0000000..391ddd6 --- /dev/null +++ b/src/renderer/src/components/thirdFile-preview/index.vue @@ -0,0 +1,35 @@ + + + + \ No newline at end of file diff --git a/src/renderer/src/components/window-tools/index.vue b/src/renderer/src/components/window-tools/index.vue index da66f80..b2d9057 100644 --- a/src/renderer/src/components/window-tools/index.vue +++ b/src/renderer/src/components/window-tools/index.vue @@ -8,9 +8,10 @@ +onMounted(() =>{ + isMaxSize.value = Remote.getCurrentWindow().isMaximized() +}) + + \ No newline at end of file + diff --git a/src/renderer/src/hooks/useProcessList.js b/src/renderer/src/hooks/useProcessList.js index 1a1ca4f..e7329eb 100644 --- a/src/renderer/src/hooks/useProcessList.js +++ b/src/renderer/src/hooks/useProcessList.js @@ -15,9 +15,10 @@ export const isJson = (str) => { /** * @description processList 格式化试题 - * @param {*} row + * @param {*} row + * @param {*} aloneOption 选择题中选项是否为每行一个 */ -export const processList = (row) => { +export const processList = (row, aloneOption=false) => { for (var i = 0; i < row.length; i++) { if (isJson(row[i].workanalysis)) { //1、先默认格式化 格式化各项内容(待优化, 后续界面显示的为format的值) @@ -55,19 +56,25 @@ export const processList = (row) => { const workDescArr = element.split('#&') let tmp = '' let j = 0 - for (; j < workDescArr.length; j++) { - if (j % 2 == 0) { - tmp += `
` + for(; j${char}.${workDescArr[j]}
`; } - const char = String.fromCharCode(65 + j) - tmp += `
${char}.${workDescArr[j]}
` - if (j % 2 == 1) { - tmp += '' + else { + if(j%2 == 0){ + tmp += `
`; + } + + tmp += `
${char}.${workDescArr[j]}
`; + if(j%2 == 1){ + tmp += '
'; + } } } // j此刻已自增1, 故当选项为单数时, 需要补充结束标签 - if (j % 2 == 1) { - tmp += '' + if(!aloneOption && j%2 == 1){ + tmp += ''; } // workDescArr为 [''] 表示为 判断题或者填空题,这里不需要选项 @@ -136,31 +143,36 @@ export const processList = (row) => { * ] */ let workDescArr = JSON.parse(row[i].workdesc) - let workDescHtml = `
` workDescArr.map((item, index) => { if (item.type == '单选题' || item.type == '多选题') { - workDescHtml += `
${index + 1}. ${item.title}
` + workDescHtml += `
${index + 1}. ${item.title}
` let tmp = '' let j = 0 let optionsArr = item.options - for (; j < optionsArr.length; j++) { - if (j % 2 == 0) { - tmp += `
` + for(; j${char}.${optionsArr[j]}
`; } - const char = String.fromCharCode(65 + j) - tmp += `
${char}.${optionsArr[j]}
` - if (j % 2 == 1) { - tmp += '
' + else { + if(j%2 == 0){ + tmp += `
`; + } + + tmp += `
${char}.${optionsArr[j]}
`; + if(j%2 == 1){ + tmp += '
'; + } } } // j此刻已自增1, 故当选项为单数时, 需要补充结束标签 - if (j % 2 == 1) { - tmp += '' + if(!aloneOption && j%2 == 1){ + tmp += ''; } - workDescHtml += tmp } else if (item.type == '填空题' || item.type == '判断题' || item.type == '主观题') { - workDescHtml += `
${index + 1}. ${item.title}
` + workDescHtml += `
${index + 1}. ${item.title}
` } }) workDescHtml += '' @@ -265,18 +277,24 @@ export const processList = (row) => { // 处理[选项显示] - 拼接ABCD首序号 let tmp = '' let j = 0 - for (; j < workDescArr.length; j++) { - if (j % 2 == 0) { - tmp += `
` + for(; j${char}.${workDescArr[j]}
`; } - const char = String.fromCharCode(65 + j) - tmp += `
${char}.${workDescArr[j]}
` - if (j % 2 == 1) { - tmp += '' + else { + if(j%2 == 0){ + tmp += `
`; + } + + tmp += `
${char}.${workDescArr[j]}
`; + if(j%2 == 1){ + tmp += '
'; + } } } - if (j % 2 == 0) { - tmp += '' + if(!aloneOption && j%2== 0){ + tmp += ''; } row[i].workdescFormat = tmp diff --git a/src/renderer/src/layout/components/Header.vue b/src/renderer/src/layout/components/Header.vue index 6b3e875..e07e422 100644 --- a/src/renderer/src/layout/components/Header.vue +++ b/src/renderer/src/layout/components/Header.vue @@ -29,11 +29,15 @@
- + + + @@ -61,25 +56,29 @@ import { ref, onMounted, onUnmounted, computed, watch } from 'vue' import { listByDeadDate, listClassworkdata } from '@/api/classTask' import TaskItem from '@/views/classTask/container/classTask/task-item.vue' -// import ItemDialog from '@/views/classTask/container/item-dialog.vue' import { useToolState } from '@/store/modules/tool' -import { getCurrentTime } from '@/utils/date' +import { getDateFormatDate, getTheOtherDay, getTheOtheNextDay } from '@/utils/date' import useUserStore from '@/store/modules/user' -import useClassTaskStore from "@/store/modules/classTask"; import {createWindow} from '@/utils/tool' -import {sessionStore} from '@/utils/store' import {debounce } from '@/utils/comm' const toolState = useToolState(); - -const classTaskStore = useClassTaskStore() const userStore = useUserStore().user -// const itemDialogRef = ref(null) -const tabOptions = ref(['进行中', '已结束']) -const tabActive = ref('进行中') + +const tabOptions = ref(['待批改', '已批改']) +const tabActive = ref('待批改') const dataList = ref([]) -const EndDate = ref(getCurrentTime('YYYY-MM-DD')) +// 默认起止时间:当前日期前2天后3天;默认查询一周的数据 +const startEndDate = ref([ + getTheOtherDay(3), + getTheOtheNextDay(3), +]) +const defaultTime = ref<[Date, Date]>([ + getTheOtherDay(3), + getTheOtheNextDay(3), +]) + // 所有班级作业列表 const classWorkList = ref([]) @@ -91,23 +90,18 @@ const loading = ref(false) const activeDataList = computed(() => { return classWorkList.value }) +const doneDataList = computed(() => { + return classWorkList.value +}) const deleteReserv = (item) => { console.log('删除待开发', item) // dataList.value = dataList.value.filter((is) => { // return is.id !== item.id // }) } -const doneDataList = computed(() => { - return classWorkList.value -}) -// 当日之后的日期禁用 -const disabledDate = (time) => { - return time.getTime() > Date.now() -} -// 截止日期改变 -const changeEndDate = (val) => { - console.log('截止日期改变', val) +const changeStartEndDate = (val) => { + console.log('起止日期改变', val) getData() // 加载数据 } @@ -115,245 +109,202 @@ const changeEndDate = (val) => { const getData = async () => { classWorkList.value = [] loading.value = true - // 1、班级列表 - // getClassList() - // 2、班级作业 + // 1、班级作业 await getClassWorkList() - // 3、班级学生作业 包含多个班级 + // 2、班级学生作业 包含多个班级 getStudentClassWorkData() loading.value = false } + /** - * 1、获取班级列表数据 - * TODO 这里暂时取班级id的list,后续需要在修改 - */ -const getClassList = () => { - if(classTaskStore.classListIds.length==0){ - // 获取 班级列表ids 这里暂时取班级id的list,后续需要在修改 - classTaskStore.listClassmain({ classuserid: userStore.userId, pageSize: 100, status: 'open' }) - } -} -/** - * 2、获取班级作业 + * 1、获取班级作业 */ const getClassWorkList = async () => { - //if(classTaskStore.classListIds.length>0){ - { - // 班级作业数据,包含多个班级 homeworklist - const response = await listByDeadDate({ - edituserid: userStore.userId, // 老师的id - edustage: userStore.edustage, // 学段 - edusubject: userStore.edusubject,//学科 - // deaddate: tabActive.value === '进行中'? getTomorrow() : EndDate.value,// 进行中:明天,已结束:选择的日期 弃用 - deaddate: EndDate.value,// 进行中:明天,已结束:选择的日期 - status: '1', // 作业状态:1-已发布 - orderby: 'deaddate DESC', - pageSize: 100, - }) + // 班级作业数据,包含多个班级 homeworklist + const response = await listByDeadDate({ + edituserid: userStore.userId, // 老师的id + edustage: userStore.edustage, // 学段 + edusubject: userStore.edusubject,//学科 + startdate: tabActive.value === '待批改'? '' : getDateFormatDate(startEndDate.value[0]), + deaddate: tabActive.value === '待批改'? '' : getDateFormatDate(startEndDate.value[1]),// 待批改:明天,已批改:选择的日期 + status: tabActive.value === '待批改'? '1' : '2', // 作业状态:1-已发布 + orderby: 'deaddate DESC', + pageSize: 100, + }) - /** - * 2024-10-17 由于 后面截止时间加了 时分,特加判断 - * 1、进行中、以前是以明天判断。现改为传当天的日期,并根据当前日期的时分与截止日期进行判断, - * 2、已结束、以前默认是以明天判断。现依然以明天为判断,并根据当前日期时分大于截止日期时分判断。 - */ - let list = []; - if(tabActive.value === '进行中'){ - // 进行中 当前日期时间 小于 截止 日期时间 - list = response.rows&&response.rows.filter(item => item.deaddate && getCurrentTime('YYYY-MM-DD HH:mm') < item.deaddate); // 进行中 - }else{ - list = response.rows&&response.rows.filter(item => item.deaddate && getCurrentTime('YYYY-MM-DD HH:mm') > item.deaddate); // 已结束 + let list = response.rows || []; + for (var i = 0; i < list.length; i++) { + // 初始化部分新增字段值 + list[i].workdatalist = [] // 当前任务中有多少个学生的数据集合 + list[i].workdatalistVisible = false + list[i].feedtimelength = 0 // 已交的学生人中,汇总计算用时 + list[i].rightAnswerCount = 0 + list[i].scoingRate = 0 + '%' // 得分率 + list[i].averagetime = 0 // 平均用时 + + // ---------------------------------------------- + // 处理任务类型的UI + if (list[i].worktype == '学习目标定位') { + list[i].workclass = 'success' + list[i].workcodesList = JSON.parse(list[i].workcodes) + } else if (list[i].worktype == '教材研读') { + list[i].workclass = 'primary' + } else if (list[i].worktype == '框架梳理') { + list[i].workclass = 'warning' + } else if (list[i].worktype == '学科定位') { + list[i].workclass = 'info' + } else if (list[i].worktype == '习题训练') { + list[i].workclass = 'danger' + } else { + list[i].workclass = '' } - - - for (var i = 0; i < list.length; i++) { - // 初始化部分新增字段值 - list[i].workdatalist = [] - list[i].workdatacount = 0 // 人数 - list[i].workdatalistVisible = false - list[i].workdatafeedbackcount = 0 // 已交人数 - list[i].feedtimelength = 0 - list[i].rightAnswerCount = 0 - list[i].scoingRate = 0 + '%' // 得分率 - list[i].averagetime = 0 // 平均用时 - - // ---------------------------------------------- - // 处理任务类型的UI - if (list[i].worktype == '学习目标定位') { - list[i].workclass = 'success' - list[i].workcodesList = JSON.parse(list[i].workcodes) - } else if (list[i].worktype == '教材研读') { - list[i].workclass = 'primary' - } else if (list[i].worktype == '框架梳理') { - list[i].workclass = 'warning' - } else if (list[i].worktype == '学科定位') { - list[i].workclass = 'info' - } else if (list[i].worktype == '习题训练') { - list[i].workclass = 'danger' - } else { - list[i].workclass = '' - } - // 如果是习题训练任务,则检查一共有多少道 - if (list[i].entpcourseworklist != '') { - list[i].entpcourseworklistarray = JSON.parse( - '[' + list[i].entpcourseworklist + ']' - ) - } else { - list[i].entpcourseworklistarray = [] - } - // 根据 classworkdatastudentids 初始化判断分配的人数 - if ( - list[i].classworkdatastudentids != '' && - list[i].classworkdatastudentids != null && - list[i].classworkdatastudentids != 'null' - ) { - const stuList = JSON.parse('[' + list[i].classworkdatastudentids + ']') - list[i].workdatacount = stuList.length - } + // 如果是习题训练任务,则检查一共有多少道 + if (list[i].entpcourseworklist != '') { + list[i].entpcourseworklistarray = JSON.parse( + '[' + list[i].entpcourseworklist + ']' + ) + } else { + list[i].entpcourseworklistarray = [] } - // 显示分配人数(workdatacount)>0 的 - if (list && list.length > 0) { - classWorkList.value = list && list.filter((item) => item.workdatacount > 0) - //TODO: 这里没分页,貌似这个 total 不重要,后续看 - total.value = 0 - }else{ - classWorkList.value = [] - total.value = 0 - } - loading.value = false } + + // 显示分配人数(workdataresultsum)>0 的 + if (list && list.length > 0) { + classWorkList.value = list && list.filter((item) => item.workdataresultsum > 0) + //TODO: 这里没分页,貌似这个 total 不重要,后续看 + total.value = 0 + }else{ + classWorkList.value = [] + total.value = 0 + } + loading.value = false } /** - * 3、获取多个班级学生作业数据 + * 2、获取多个班级学生作业数据 + * 查询已交的列表 + * @param workList :需要更新的作业list + * @param Refresh :true 不用刷新,false 需要刷新 */ -const getStudentClassWorkData = async() => { - // const { chapterId } = await useGetHomework(props.bookobj.node) - // this.entpcourseid = chapterId - //if(classTaskStore.classListIds.length>0){ - // listClassworkdataByDeadDate({ - // edituserid: userStore.userId, // 老师的id - // classids: classTaskStore.classListIds.join(','), - // edusubject: userStore.edusubject,//学科 - // deaddate: tabActive.value === '进行中'? getTomorrow() : EndDate.value,// 进行中:明天,已结束:选择的日期 - // deaddate: EndDate.value,// 进行中:明天,已结束:选择的日期 - // //status: '1', // 作业状态:1-已发布 - // orderby: "deaddate DESC",// - // pageSize: 1000, - // }) +const getStudentClassWorkData = async(workList = [], Refresh = true) => { + // 获取 已交的 列表数据(workdataresultcount 已交的学生数) + let SubmitClWorkList = []; + if(Refresh){ + SubmitClWorkList = classWorkList.value.filter((item) => item.workdataresultcount > 0) ; + }else{ + SubmitClWorkList = workList; + } - // listClassworkdataNew({ - // classworkids: ids, // 作业id - // edituserid: userStore.userId, // 老师的id - // edusubject: userStore.edusubject,//学科 - // evalStatus: 1, - // pageSize: 1000, - // }) + console.log('有提交的作业', SubmitClWorkList) + const ids = SubmitClWorkList&&SubmitClWorkList.map((item) => item.id).join(','); + if (ids == '') { + return; + } + listClassworkdata({ + classworkids: ids, + pageSize: 1000, + }).then((res) => { + for (var t = 0; t < classWorkList.value.length; t++) { + for (var i = 0; i < res.rows.length; i++) { + // finishtimelength != '0' 已交 + if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].finishtimelength != '0') { + console.log('==================') + // 有几个学生完成/正在完成学习任务 + // 至少resultcount不是0 + //classWorkList.value[t].workdataresultcount++ - - { - const ids = classWorkList.value.map((item) => item.id).join(','); - if (ids == '') { - return; - } - listClassworkdata({ - classworkids: ids, - pageSize: 1000, - }).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].finishtimelength != '0') { - console.log('==================') - // 有几个学生完成/正在完成学习任务 - // 至少resultcount不是0 - classWorkList.value[t].workdatafeedbackcount++ + // 已交的学生人中,汇总计算用时 + classWorkList.value[t].feedtimelength += parseInt(res.rows[i].finishtimelength) - // 在参与学习任务的人中,汇总计算用时 - classWorkList.value[t].feedtimelength += parseInt(res.rows[i].finishtimelength) + // 计算得分率 + if ( + res.rows[i].classworkevallist != '' && + res.rows[i].classworkevallist != null && + res.rows[i].classworkevallist != 'null' + ) { + let replacedString = res.rows[i].classworkevallist.replace(/""/g, '"') + // 将标签中双引号改为转义, 测试数据: "{\"id\":172907, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":358520, \"feedcontent\":\"④①⑤③②\", \"score\":4, \"rightanswer\":\"④①⑤③②\"},{\"id\":172908, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":358521, \"feedcontent\":\"气壮山威,鲲鹏展翅楚云飞\", \"score\":4, \"rightanswer\":\"志远天高,春风杨柳麓山青\"},{\"id\":172909, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363096, \"feedcontent\":\"《红烛》化用“蜡矩”这一古典意象,赋予它新的含义,赞美了红烛以“蜡炬成灰”来点亮世界的奉献精神。\", \"score\":4, \"rightanswer\":\"《立在地球边上放号》中,全诗采用间接抒情的方式,描绘了太平洋的浪潮,吟唱了一曲惊心动魄的力的颂歌,意在赞美摧毁旧世界、创造新生活的“五四”精神。\"},{\"id\":172910, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363098, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\"},{\"id\":172911, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363100, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\"}" + replacedString = escapeHtmlQuotes(res.rows[i].classworkevallist).replace( + /"(\[.*\])"/g, + '$1' + ) + replacedString = escapeHtmlQuotes(res.rows[i].classworkevallist) + var evalarray + try { + evalarray = JSON.parse('[' + res.rows[i].classworkevallist + ']') + } catch { + evalarray = JSON.parse('[' + replacedString + ']') + } - // 计算得分率 - if ( - res.rows[i].classworkevallist != '' && - res.rows[i].classworkevallist != null && - res.rows[i].classworkevallist != 'null' - ) { - let replacedString = res.rows[i].classworkevallist.replace(/""/g, '"') - // 将标签中双引号改为转义, 测试数据: "{\"id\":172907, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":358520, \"feedcontent\":\"④①⑤③②\", \"score\":4, \"rightanswer\":\"④①⑤③②\"},{\"id\":172908, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":358521, \"feedcontent\":\"气壮山威,鲲鹏展翅楚云飞\", \"score\":4, \"rightanswer\":\"志远天高,春风杨柳麓山青\"},{\"id\":172909, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363096, \"feedcontent\":\"《红烛》化用“蜡矩”这一古典意象,赋予它新的含义,赞美了红烛以“蜡炬成灰”来点亮世界的奉献精神。\", \"score\":4, \"rightanswer\":\"《立在地球边上放号》中,全诗采用间接抒情的方式,描绘了太平洋的浪潮,吟唱了一曲惊心动魄的力的颂歌,意在赞美摧毁旧世界、创造新生活的“五四”精神。\"},{\"id\":172910, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363098, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\"},{\"id\":172911, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363100, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,浮想联翩。\"}" - replacedString = escapeHtmlQuotes(res.rows[i].classworkevallist).replace( - /"(\[.*\])"/g, - '$1' - ) - replacedString = escapeHtmlQuotes(res.rows[i].classworkevallist) - var evalarray - try { - evalarray = JSON.parse('[' + res.rows[i].classworkevallist + ']') - } catch { - evalarray = JSON.parse('[' + replacedString + ']') + for (var e = 0; e < evalarray.length; e++) { + if (res.rows[i].worktype == '常规作业') { + evalarray[e].feedcontent = escapeHtmlQuotes(evalarray[e].feedcontent).replace( + /"(\[.*\])"/g, + '$1' + ) + evalarray[e].feedcontent = escapeHtmlQuotes(evalarray[e].feedcontent) } - - for (var e = 0; e < evalarray.length; e++) { - if (res.rows[i].worktype == '常规作业') { - evalarray[e].feedcontent = escapeHtmlQuotes(evalarray[e].feedcontent).replace( - /"(\[.*\])"/g, - '$1' - ) - evalarray[e].feedcontent = escapeHtmlQuotes(evalarray[e].feedcontent) - } - if (evalarray[e].feedcontent == evalarray[e].rightanswer) { - // 正确,得分 - classWorkList.value[t].rightAnswerCount++ - } + if (evalarray[e].feedcontent == evalarray[e].rightanswer) { + // 正确,得分 + classWorkList.value[t].rightAnswerCount++ } } } - // 当前这个学习任务,共推送给了几个学生,workdatacount - if (res.rows[i].classworkid == classWorkList.value[t].id) { - classWorkList.value[t].workdatalist.push(res.rows[i]) - } } - // 计算完成进度 workdatacount人数要大于0 - if ( - classWorkList.value[t].workdataresultcount > 0 && - classWorkList.value[t].workdatacount > 0 - ) { - classWorkList.value[t].finishpercent = parseInt( - (classWorkList.value[t].workdataresultcount / classWorkList.value[t].workdatacount) * 100 - ) - } else { - classWorkList.value[t].finishpercent = 0 + // 当前这个学习任务,共推送给了几个学生,workdataresultsum + if (res.rows[i].classworkid == classWorkList.value[t].id) { + classWorkList.value[t].workdatalist.push(res.rows[i]) } - - // 以下四个参数,都要计算 - // 2024-04-12,酉阳,by jackyshen - - // 计算参与学习任务的平均用时 - if (classWorkList.value[t].workdatafeedbackcount > 0) { - classWorkList.value[t].averagetime = Math.ceil(classWorkList.value[t].feedtimelength / classWorkList.value[t].workdatafeedbackcount / 60).toFixed(0) - } else { - classWorkList.value[t].averagetime = 0 - } - - // 计算批阅异常,需要获取每个题目的类型,找出主观题 - // 暂缓 - - // 计算平均得分率: 正确题数/(题目总数*学生人数)*100 - if ( - classWorkList.value[t].entpcourseworklistarray && - classWorkList.value[t].entpcourseworklistarray.length > 0 - ) { - var dd = - (classWorkList.value[t].rightAnswerCount / - (classWorkList.value[t].entpcourseworklistarray.length * - classWorkList.value[t].workdatacount)) * - 100 - classWorkList.value[t].scoingRate = dd.toFixed(0) + '%' - } else { - classWorkList.value[t].scoingRate = '0%' - } - // 设定典型作答,需要获取每个题目的类型,找出主观题 - // 暂缓 } - }) - } + + + // 计算完成进度: workdataresultcount 学生提交了的个数; workdataresultsum 人数要大于0; + if (classWorkList.value[t].workdataresultcount > 0 && classWorkList.value[t].workdataresultsum > 0 ) { + classWorkList.value[t].finishpercent = parseInt( + (classWorkList.value[t].workdataresultcount / classWorkList.value[t].workdataresultsum) * 100 + ) + } else { + classWorkList.value[t].finishpercent = 0 + } + + /** 计算 已批阅进度 */ + // workdataresultsum 人数 teacherrationgcount 已批阅人数 + // 已批阅百分比: (人数-已批阅数) / 人数 * 100 + if (classWorkList.value[t].workdataresultsum > 0) { + classWorkList.value[t].teacherCorrectionProgress = parseInt( + ((classWorkList.value[t].teacherrationgcount) / classWorkList.value[t].workdataresultsum) * 100 + ) + } else { + classWorkList.value[t].teacherCorrectionProgress = 0 + } + + // 以下四个参数,都要计算 + // 2024-04-12,酉阳,by jackyshen + + // 计算参与学习任务的平均用时:学生总用时/ 提交学生数 + if (classWorkList.value[t].workdataresultcount > 0) { + classWorkList.value[t].averagetime = Math.ceil(classWorkList.value[t].feedtimelength / classWorkList.value[t].workdataresultcount / 60).toFixed(0) + } else { + classWorkList.value[t].averagetime = 0 + } + + // 计算平均得分率: 正确题数/(题目总数*学生人数)*100 + if ( + classWorkList.value[t].entpcourseworklistarray && + classWorkList.value[t].entpcourseworklistarray.length > 0 + ) { + var dd = + (classWorkList.value[t].rightAnswerCount / + (classWorkList.value[t].entpcourseworklistarray.length * + classWorkList.value[t].workdataresultsum)) * + 100 + classWorkList.value[t].scoingRate = dd.toFixed(0) + '%' + } else { + classWorkList.value[t].scoingRate = '0%' + } + } + }) + } @@ -379,6 +330,7 @@ const getStudentClassWorkDataPolling = () => { getStudentVisible() // 在轮询 pollingST.value = setInterval(() => { + console.log('轮询查询学生作业进度') getStudentVisible() }, 1000 * 10) } @@ -413,75 +365,56 @@ onUnmounted(() => { // [作业反馈] - 实际查询逻辑 const getStudentVisible = async () => { - if (classTaskStore.classListIds.length <= 0) { - return + if(!classWorkList.value.length>0){ + return; } - // 班级作业数据,多个班级 const response = await listByDeadDate({ - classidarray: classTaskStore.classListIds.join(','), edituserid: userStore.userId, // 老师的id - edustage: userStore.edustage,// 学段 + edustage: userStore.edustage, // 学段 edusubject: userStore.edusubject,//学科 - // deaddate: tabActive.value === '进行中'? getTomorrow() : EndDate.value,// 进行中:明天,已结束:选择的日期 - deaddate: EndDate.value,// 进行中:明天,已结束:选择的日期 - status: '1', // 作业状态:1-已发布 - // orderby: 'concat(deaddate,uniquekey) DESC', + startdate: tabActive.value === '待批改'? '' : getDateFormatDate(startEndDate.value[0]), + deaddate: tabActive.value === '待批改'? '' : getDateFormatDate(startEndDate.value[1]),// 待批改:明天,已批改:选择的日期 + status: tabActive.value === '待批改'? '1' : '2', // 作业状态:1-已发布 orderby: 'deaddate DESC', - pageSize: 100 + pageSize: 100, }) - /** - * 2024-10-17 由于 后面截止时间加了 时分,特加判断 - * 1、进行中、以前是以明天判断。现改为传当天的日期,并根据当前日期的时分与截止日期进行判断, - * 2、已结束、以前默认是以明天判断。现依然以明天为判断,并根据当前日期时分大于截止日期时分判断。 - */ - let list = []; - if(tabActive.value === '进行中'){ - // 进行中 当前日期时间 小于 截止 日期时间 - list = response.rows&&response.rows.filter(item => item.deaddate && getCurrentTime('YYYY-MM-DD HH:mm') < item.deaddate); // 进行中 - }else{ - list = response.rows&&response.rows.filter(item => item.deaddate && getCurrentTime('YYYY-MM-DD HH:mm') > item.deaddate); // 已结束 - } + let list = response.rows || []; - const curWorkList = list - - /** - * warn: 这里仅更新了finishpercent(进度条), 且当前作业布置推送新任务时, curWorkList中会查到新的任务与当前页面中this.classWorkList长度不一致, - * 故这里需循环this.classWorkList且只更新当前页面中的存在的任务进度 - */ - for (let t = 0; t < classWorkList.value.length; t++) { - // 当前时间超过[作业任务]截止时间的跳过 - // if( getDateTime > classWorkList.value[t].deaddate ){ - // continue; - // } - // 确保当前拿到的任务与页面中存在的任务能一对一(避免因删除其他操作而删除作业任务导致两个数组的index不统一而越界) - let curWork = curWorkList.find((work) => work.id === classWorkList.value[t].id) - // workdataresultcount 完成人数 workdatacount人数要大于0 - if (curWork && curWork.workdataresultcount > 0 && classWorkList.value[t].workdatacount > 0) { - classWorkList.value[t].workdataresultcount = curWork.workdataresultcount - // 桌面端貌似不需要进度条了? - classWorkList.value[t].finishpercent = parseInt( - (classWorkList.value[t].workdataresultcount / classWorkList.value[t].workdatacount) * 100 - ) - // 计算参与学习任务的平均用时 - if (classWorkList.value[t].workdatafeedbackcount > 0) { - classWorkList.value[t].averagetime = Math.ceil(classWorkList.value[t].feedtimelength / classWorkList.value[t].workdatafeedbackcount / 60).toFixed(0) - } else { - classWorkList.value[t].averagetime = 0 + let newList = []; + for(let i = 0; i < classWorkList.value.length; i++){ + // 父list的id与子list的id相等,在进行对比;若是不等? 有可能是老师批阅完了这个list数据,变成了已批改状态中,则父list数据需要删除 + const isList = list.filter((item) => item.id === classWorkList.value[i].id); + if(isList.length === 0){ + // 父list的id与子list的id不相等,则删除父list数据 + classWorkList.value.splice(i,1); + } + for(let j = 0; j < list.length; j++){ + // workdataresultcount 学生提交了的个数; + if(classWorkList.value[i].id === list[j].id && classWorkList.value[i].workdataresultcount != list[j].workdataresultcount){ + // 学生提交数 != 学生提交数? + newList.push(list[j]); } - // 更新批阅数 - classWorkList.value[t].teacherrationgcount = curWork.teacherrationgcount - } else { - // 学生未完成,但是老师批改了? - if(curWork && curWork.workdataresultcount == 0){ - // 更新批改数 - classWorkList.value[t].teacherrationgcount = curWork.teacherrationgcount + // teacherrationgcount 已批阅人数 + if(classWorkList.value[i].id === list[j].id && classWorkList.value[i].teacherrationgcount != list[j].teacherrationgcount){ + // 更新批阅进度条 + if (classWorkList.value[i].workdataresultsum > 0) { + // 更新批阅数、 进度条 + classWorkList.value[i].teacherrationgcount = list[j].teacherrationgcount; + classWorkList.value[i].teacherCorrectionProgress = parseInt( + ((list[j].teacherrationgcount) / list[j].workdataresultsum) * 100 + ) + } else { + classWorkList.value[i].teacherCorrectionProgress = 0 + } } - classWorkList.value[t].finishpercent = 0 } } - - return 1 + if(newList.length>0){ + // 更新学生提交后的数据? 作业进度条、平均用时、得分率 + const list = newList&&newList.filter((item) => item.workdataresultcount > 0) ; + getStudentClassWorkData(list,false); + } } @@ -489,16 +422,27 @@ const getStudentVisible = async () => { watch( () => [dataList, toolState.isTaskWin], () => { - console.log('=监听到批改窗口打开了===', toolState.isTaskWin) + console.log('监听--批改窗口是否打开===', toolState.isTaskWin) if(!toolState.isTaskWin){ - - closeDialog();// 开启轮询 + if(tabActive.value === '待批改'){ + closeDialog();// 开启轮询 + } } } ) + watch(tabActive, (newVal,oldVal)=>{ console.log('newVal',newVal); getData() // 加载数据 + if(newVal === '待批改'){ + // 轮询查询 + console.log('监听---开启轮询') + closeDialog(); + }else{ + // 关闭轮询 + console.log('监听---关闭轮询') + clearInterval(pollingST.value); + } }) diff --git a/src/renderer/src/views/classTask/container/classOverview.vue b/src/renderer/src/views/classTask/container/classOverview.vue index fbe48ce..33c7726 100644 --- a/src/renderer/src/views/classTask/container/classOverview.vue +++ b/src/renderer/src/views/classTask/container/classOverview.vue @@ -72,15 +72,15 @@ const props = defineProps({ }, }) let studentList = ref([]) // 学生数据 -const stuHasAnswers = ref([]) // 已经答过题的学生不管对错 // 初始-数据处理 const initData = () => { - console.log('xxx', props) // window.test = activeCourse studentList.value = props.activeData.studentList || [] const activeWorkFeedList = props.activeData.workFeedList || [] const quizlist = props.activeData.quizlist || [] + console.log(quizlist,'quizlist'); + // 习题特殊处理 let data = quizlist.map(o => { // 解析题选项 @@ -90,7 +90,9 @@ const initData = () => { let rightIds = [] // 正确学生 let hasAnswers= [] // 答过题的学生 let timeAnalyse = [] // 平均时长和编号 + // let subjectCourese = [] // 题目编号 const quizFeedList = activeWorkFeedList.filter(f => f.entpcourseworkid == o.id) // 做该题的列表 + let children = [] const allStudents = []; if (o.worktype == '单选题') { // '单选题','多选题' @@ -101,6 +103,11 @@ const initData = () => { // 改选项的学生id const studentIds = quizFeedList.filter(f => f.feedcontent==v&&f.finishtimelength!='0').map(f => f.studentid)||[]; accSum += studentIds.length; + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) + if (isOk) { activeIds.push(...studentIds) } @@ -115,7 +122,7 @@ const initData = () => { const res = isSame((f.feedcontent||'').split(','), workanswer); return f.entpcourseworkid == o.id && f.finishtimelength!='0' && res; }); - + const list = workdesc.includes('#&') ? workdesc.split('#&') : isJson(workdesc)?JSON.parse(workdesc):[]; children = list.map((v,i) => { const isOne = o.worktype == '单选题' @@ -128,6 +135,10 @@ const initData = () => { if (studentIds.length>0) { allStudents.push(...studentIds); } + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) if(isOk) { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 } @@ -136,8 +147,12 @@ const initData = () => { }) } else if (o.worktype == '填空题') { // 填空题 - const regex = /(.*?)/g // 定义正则表达式,匹配 xxx 格式的内容 - children = (o.title||'').match(regex).map((v,i) => { + let title = o.title.replace(/_{3,}/g, '_____'); //将3-10的下划线统一格式为5个 + let regex = /(.*?)/g // 定义正则表达式,匹配 xxx 格式的内容 + if (title.indexOf('_____') != -1) { + regex = /_{5}/g // 定义正则表达式,匹配 xxx 格式的内容 + } + children = (title||'').match(regex).map((v,i) => { const def = `填空项 ${i+1}` //const code = '( )' const code = '(略)', txt=v @@ -146,6 +161,10 @@ const initData = () => { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 hasAnswers=[...new Set(hasAnswers.concat(studentIds))] accSum = activeIds.length + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) return { def, code, txt, isOk:true, studentIds } }) } else if (o.worktype == '判断题') { // 判断题 @@ -187,6 +206,10 @@ const initData = () => { accSum += studentIds.length; if(isOk) activeIds.push(...studentIds) hasAnswers.push(...studentIds) + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) return { def: v, code: v, isOk, studentIds } }) } else { // 论述题 @@ -196,6 +219,10 @@ const initData = () => { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 hasAnswers=[...new Set(hasAnswers.concat(studentIds))] accSum = activeIds.length + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) children = [{ def, code, isOk:true, studentIds }] } @@ -215,11 +242,10 @@ const initData = () => { } // def: 原始题数据 type 类型 active: 选中 points: 得分率, accSum 题解答人数 - return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, rightSum, children,hasAnswers } + return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, rightSum, children,hasAnswers,timeAnalyse,score:o.workScore } }) - console.log('获取数据: ', data) - stuHasAnswers.value = [...data[0].hasAnswers] - provide('hasAnswer', stuHasAnswers.value) + if (data.length === 0) return + useOverview.getAllData([...data]) } // 百分比现在 0-100 const percent = v => v > 1 ? 1 : v < 0 ? 0 : Math.round(v * 100) @@ -232,6 +258,20 @@ const isJson = str => {if(typeof str == 'string'){ if(typeof res == 'object' && res) return true } catch (error) {}}return false } +// 获取到学生的平均回答时间 +const groupByField = (array, field) => { + const groupedMap = {}; + array.forEach(item => { + const key = item[field]; + if (!groupedMap[key]) { + groupedMap[key] = []; + } + groupedMap[key].push(item); + }); + + // 将映射对象转换为二维数组 + return Object.values(groupedMap); +} watch(() => props.tableList,() => { useOverview.getTableList(props.tableList) diff --git a/src/renderer/src/views/classTask/container/classOverview/distribution.vue b/src/renderer/src/views/classTask/container/classOverview/distribution.vue index 5ff15c1..ab7a702 100644 --- a/src/renderer/src/views/classTask/container/classOverview/distribution.vue +++ b/src/renderer/src/views/classTask/container/classOverview/distribution.vue @@ -14,8 +14,8 @@ - - - diff --git a/src/renderer/src/views/classTask/container/newTask/taskTypeView.vue b/src/renderer/src/views/classTask/container/newTask/taskTypeView.vue index 431913f..de215d4 100644 --- a/src/renderer/src/views/classTask/container/newTask/taskTypeView.vue +++ b/src/renderer/src/views/classTask/container/newTask/taskTypeView.vue @@ -55,6 +55,7 @@ -
- +
+ + +
- + @change="getPaginationList" /> +
@@ -224,29 +267,37 @@ + + +
diff --git a/src/renderer/src/views/classTask/container/quizStats.vue b/src/renderer/src/views/classTask/container/quizStats.vue index de5b73b..da72dcc 100644 --- a/src/renderer/src/views/classTask/container/quizStats.vue +++ b/src/renderer/src/views/classTask/container/quizStats.vue @@ -1,9 +1,9 @@