baigl #180
|
@ -0,0 +1,237 @@
|
||||||
|
// 查询evaluation列表
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询反馈列表
|
||||||
|
|
||||||
|
// 查询classworkdata列表 班级作业列表
|
||||||
|
export function listClassworkdata(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classworkdata/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询entpcoursework列表 课程作业列表
|
||||||
|
export function listEntpcoursework(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/entpcoursework/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询classworkeval列表 课堂作业列表
|
||||||
|
export function listClassworkeval(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classworkeval/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改classworkeval
|
||||||
|
export function updateClassworkeval(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classworkeval',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 0------------------------
|
||||||
|
// 查询班级列表
|
||||||
|
export function listClassmain(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classmain/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 查询学生列表
|
||||||
|
export function listClassuser(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classuser/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 新增班级
|
||||||
|
export function addClassmain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classmain',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 查询所有学科的列表
|
||||||
|
export function listEvaluation(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/evaluation/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 新增小组
|
||||||
|
export function addClassgroup(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classgroup',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//班级详情
|
||||||
|
export function getClassmain(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classmain/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取小组列表
|
||||||
|
export function listClassgroup(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classgroup/new/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//删除小组
|
||||||
|
export function delClassgroup(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classgroup/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//查询小组信息
|
||||||
|
export function getClassgroup(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classgroup/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//修改小组信息
|
||||||
|
export function updateClassgroup(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classgroup',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//新增学生
|
||||||
|
export function addStudentmain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/studentmain',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//修改学生信息
|
||||||
|
export function updateStudentmain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/studentmain',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//获取学生信息
|
||||||
|
export function getStudentmain(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/studentmain/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//删除学生
|
||||||
|
export function leaveClass(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classuser/leaveClass',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//删除学生所有数据
|
||||||
|
export function removeStudentDataAll(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/studentmain/removeStudent/' + id,
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//删除教室
|
||||||
|
export function delClassroom(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classroom/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//导入学生
|
||||||
|
export function addStudentmainByNameArray(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/studentmain/addByNameArray',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//新增课程预约
|
||||||
|
export function addSmartClassReserv(data) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/addSmartClassReserv',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//修改课程预约
|
||||||
|
export function updateSmartClassReserv(data) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/updateSmartClassReserv',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//查询课程预约
|
||||||
|
export function getSelfReserv() {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/getSelfReserv',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function deleteSmartReserv(id) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function startClass(id, ex3) {
|
||||||
|
const params = {id}
|
||||||
|
!!ex3 && (params.ex3 = ex3)
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/startClass',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function endClass(id) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/endClass',
|
||||||
|
method: 'get',
|
||||||
|
params: {id}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 获取课堂信息
|
||||||
|
* @param {*} id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getClassInfo(id) {
|
||||||
|
return request({
|
||||||
|
url: '/smarttalk/classReserv/selectById',
|
||||||
|
method: 'get',
|
||||||
|
params: {id}
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,514 @@
|
||||||
|
export const isJson = (str) => {
|
||||||
|
if (typeof str == 'string') {
|
||||||
|
try {
|
||||||
|
let obj = JSON.parse(str)
|
||||||
|
if (typeof obj == 'object' && obj) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description processList 格式化试题
|
||||||
|
* @param {*} row
|
||||||
|
*/
|
||||||
|
export const processList = (row) => {
|
||||||
|
for (var i = 0; i < row.length; i++) {
|
||||||
|
if (isJson(row[i].workanalysis)) {
|
||||||
|
//1、先默认格式化 格式化各项内容(待优化, 后续界面显示的为format的值)
|
||||||
|
row[i].titleFormat = row[i].title // 题目
|
||||||
|
row[i].examdateFormat = row[i].examdate // ?考试日期 eg: 2024-07-11 14:39:27"
|
||||||
|
row[i].workdescFormat = row[i].workdesc // 题目选项
|
||||||
|
row[i].workanswerFormat = row[i].workanswer // 题目正确答案
|
||||||
|
if (row[i].workanswerFormat == null || row[i].workanswerFormat == '') {
|
||||||
|
row[i].workanswerFormat = '见试题解答内容'
|
||||||
|
}
|
||||||
|
|
||||||
|
// workanalysis 解析内容(analyse:解答; method:分析; discuss:点评; )
|
||||||
|
var jjj = JSON.parse(row[i].workanalysis)
|
||||||
|
row[i].analyse = jjj.analyse
|
||||||
|
row[i].method = jjj.method
|
||||||
|
row[i].discuss = jjj.discuss
|
||||||
|
//row[i].discusscollapse = false;
|
||||||
|
if (row[i].examdate !== null && row[i].examdate !== undefined) {
|
||||||
|
row[i].examdate = row[i].examdate.substring(0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 具体题型数据结构处理
|
||||||
|
if (row[i].worktype == '复合题') {
|
||||||
|
// 旧类型
|
||||||
|
if (row[i].title.indexOf('!@#$%') !== -1) {
|
||||||
|
// 1.选项解析替换
|
||||||
|
const options = JSON.parse(row[i].workdesc)
|
||||||
|
// 题目(背景材料+复合题目)
|
||||||
|
const bjTitle = row[i].title.split('!@#$%')[0]
|
||||||
|
const tmTitles = row[i].title.split('!@#$%').filter((it, ix) => ix > 0)
|
||||||
|
// console.log(bjTitle,'背景标题');
|
||||||
|
// console.log(tmTitles,'复合题目');
|
||||||
|
let titls = []
|
||||||
|
options.forEach((element, index1) => {
|
||||||
|
const workDescArr = element.split('#&')
|
||||||
|
let tmp = ''
|
||||||
|
let j = 0
|
||||||
|
for (; j < workDescArr.length; j++) {
|
||||||
|
if (j % 2 == 0) {
|
||||||
|
tmp += `<div style='width:80%;display:flex;'>`
|
||||||
|
}
|
||||||
|
const char = String.fromCharCode(65 + j)
|
||||||
|
tmp += `<div style='display:flex;margin-left:2%;width:35%;overflow:hidden;text-overflow:ellipsis;font-size:0.9em;'>${char}.${workDescArr[j]}</div>`
|
||||||
|
if (j % 2 == 1) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// j此刻已自增1, 故当选项为单数时, 需要补充结束标签
|
||||||
|
if (j % 2 == 1) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
// workDescArr为 [''] 表示为 判断题或者填空题,这里不需要选项
|
||||||
|
if (workDescArr[0] != '') {
|
||||||
|
titls.splice(index1, 1, tmp)
|
||||||
|
} else {
|
||||||
|
titls.splice(index1, 1, '')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const s = []
|
||||||
|
tmTitles.map((it, ix) => {
|
||||||
|
s.push(it)
|
||||||
|
titls.map((it2, ix2) => {
|
||||||
|
if (ix == ix2) {
|
||||||
|
s.push(it2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// console.log(s,'?????????????????')
|
||||||
|
|
||||||
|
row[i].titleFormat = bjTitle + s.join('')
|
||||||
|
row[i].workdescFormat = ''
|
||||||
|
|
||||||
|
//2.答案 - 数字转为ABCD
|
||||||
|
const answerArr = JSON.parse(row[i].workanswer)
|
||||||
|
let indexLabel = 1
|
||||||
|
let arr = []
|
||||||
|
answerArr.forEach((item) => {
|
||||||
|
const arrTmp = item.answer.split('#&')
|
||||||
|
let value = `(${indexLabel})`
|
||||||
|
arrTmp.forEach((element, i) => {
|
||||||
|
if (item.type == '单选题' || item.type == '多选题') {
|
||||||
|
value += `${String.fromCharCode(65 + Number(element))}`
|
||||||
|
}
|
||||||
|
if (item.type == '判断题' || item.type == '填空题') {
|
||||||
|
// 去除下 html标签
|
||||||
|
value += `${element.replace(/<[^>]+>/g, '')}` + (i == arrTmp.length - 1 ? '' : '、')
|
||||||
|
}
|
||||||
|
if (item.type == '主观题') {
|
||||||
|
if (element) {
|
||||||
|
console.log(element, 'element')
|
||||||
|
value += item.answer
|
||||||
|
} else {
|
||||||
|
value += '答案不唯一,请参考分析解答点评!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
arr.push(value)
|
||||||
|
indexLabel++
|
||||||
|
})
|
||||||
|
const answer = arr.join('<br />')
|
||||||
|
|
||||||
|
row[i].workanswerFormat = answer
|
||||||
|
} else {
|
||||||
|
// 处理[题干显示] - 不再需要处理
|
||||||
|
// row[i].titleFormat = row[i].title; // 仅占位提示
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理[选项显示] - 特殊结构
|
||||||
|
* [
|
||||||
|
* {type: '单选题', title: '题目1', options: ['ABC123','ABC123']},
|
||||||
|
* {type: '多选题', title: '题目1', options: ['ABC123','ABC123']},
|
||||||
|
* {type: '填空题', title: '题目1', options: []},
|
||||||
|
* {type: '判断题', title: '题目1', options: []},
|
||||||
|
* {type: '主观题', title: '题目1', options: []},
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
let workDescArr = JSON.parse(row[i].workdesc)
|
||||||
|
let workDescHtml = `<div style='width:80%;display:flex;>`
|
||||||
|
workDescArr.map((item, index) => {
|
||||||
|
if (item.type == '单选题' || item.type == '多选题') {
|
||||||
|
workDescHtml += `<div style='width:80%;display:flex;'>${index + 1}. ${item.title}</div>`
|
||||||
|
let tmp = ''
|
||||||
|
let j = 0
|
||||||
|
let optionsArr = item.options
|
||||||
|
for (; j < optionsArr.length; j++) {
|
||||||
|
if (j % 2 == 0) {
|
||||||
|
tmp += `<div style='width:80%;display:flex;'>`
|
||||||
|
}
|
||||||
|
const char = String.fromCharCode(65 + j)
|
||||||
|
tmp += `<div style='display:flex;margin-left: 2%; width: 36%'>${char}.${optionsArr[j]}</div>`
|
||||||
|
if (j % 2 == 1) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// j此刻已自增1, 故当选项为单数时, 需要补充结束标签
|
||||||
|
if (j % 2 == 1) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
workDescHtml += tmp
|
||||||
|
} else if (item.type == '填空题' || item.type == '判断题' || item.type == '主观题') {
|
||||||
|
workDescHtml += `<div style='width:80%;display:flex;'>${index + 1}. ${item.title}</div>`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
workDescHtml += '</div>'
|
||||||
|
row[i].workdescFormat = workDescHtml
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理[答案显示] - 特殊结构
|
||||||
|
* [
|
||||||
|
* {type: '单选题', answer: ['0']},
|
||||||
|
* {type: '多选题', answer: ['0','1']},
|
||||||
|
* {type: '填空题', answer: ['填空1','填空2']},
|
||||||
|
* {type: '判断题', answer: ['0'/'1']},
|
||||||
|
* {type: '主观题', answer: [xxxx]},
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
let workAnswerArr = JSON.parse(row[i].workanswer)
|
||||||
|
let workAnswerHtml = ``
|
||||||
|
workAnswerArr.map((item, index) => {
|
||||||
|
const answerArr = item.answer //JSON.parse(item.answer);
|
||||||
|
if (item.type == '单选题' || item.type == '多选题') {
|
||||||
|
const answer = answerArr
|
||||||
|
.map((item) => {
|
||||||
|
return String.fromCharCode(65 + Number(item))
|
||||||
|
})
|
||||||
|
.join('')
|
||||||
|
workAnswerHtml += `<div style='display:flex;'>${index + 1}. ${answer}</div>`
|
||||||
|
} else if (item.type == '填空题') {
|
||||||
|
const answer = answerArr.join('、')
|
||||||
|
workAnswerHtml += `<div style='display:flex;'>${index + 1}. ${answer}</div>`
|
||||||
|
} else if (item.type == '判断题') {
|
||||||
|
const answer = answerArr
|
||||||
|
.map((item) => {
|
||||||
|
return item === '1' ? '正确' : '错误'
|
||||||
|
})
|
||||||
|
.join('、')
|
||||||
|
workAnswerHtml += `<div style='display:flex;'>${index + 1}. ${answer}</div>`
|
||||||
|
} else if (item.type == '主观题') {
|
||||||
|
// 复合题里面的主观题只有一个答案,或没填
|
||||||
|
const answer = answerArr.join('、')
|
||||||
|
if (answerArr[0]) {
|
||||||
|
workAnswerHtml += `<div style='display:flex;'>${index + 1}. ${answer}</div>`
|
||||||
|
} else {
|
||||||
|
workAnswerHtml += `<div style='display:flex;'>${index + 1}. ${answer}答案不唯一,请参考分析解答点评!</div>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
row[i].workanswerFormat = workAnswerHtml
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
row[i].worktype == '主观题' ||
|
||||||
|
(row[i].worktype !== '单选题' &&
|
||||||
|
row[i].worktype !== '多选题' &&
|
||||||
|
row[i].worktype !== '填空题' &&
|
||||||
|
row[i].worktype !== '判断题')
|
||||||
|
) {
|
||||||
|
// 处理[选项显示] - 主观题中无选项, 故置空
|
||||||
|
row[i].workdescFormat = ''
|
||||||
|
row[i].workanswerFormat = ''
|
||||||
|
// 答案处理- eg: "\"不唯一的答案,参考\""
|
||||||
|
if (row[i].workanswer && row[i].workanswer != '') {
|
||||||
|
row[i].workanswerFormat = JSON.parse(row[i].workanswer)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 单选题|多选题|填空题|判断题|主观题?(待确认是否归在这里)
|
||||||
|
// 通用选项结构 ['ABC123','ABC123'] | ['ABC123','ABC123'] | [](填空题无选项) | [](判断题无选项)
|
||||||
|
let workDescArr = []
|
||||||
|
if (
|
||||||
|
row[i].workdesc.charAt(0) === '[' &&
|
||||||
|
row[i].workdesc.charAt(row[i].workdesc.length - 1) === ']'
|
||||||
|
) {
|
||||||
|
//123会直接被转换, 且不是数组对象, 故手动判断是否有[和]两个字符
|
||||||
|
workDescArr = JSON.parse(row[i].workdesc)
|
||||||
|
} else if (row[i].workdesc.indexOf('#&') !== -1) {
|
||||||
|
workDescArr = row[i].workdesc.split('#&')
|
||||||
|
} else if (row[i].workdesc.indexOf(',') !== -1) {
|
||||||
|
workDescArr = row[i].workdesc.split(',')
|
||||||
|
} else {
|
||||||
|
// 单字符串直接添加至空数组(待考虑确认)
|
||||||
|
workDescArr.push(row[i].workdesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单选题|多选题|填空题|判断题|主观题?(待确认是否归在这里)
|
||||||
|
// 通用答案结构 ['0'] | ['0','1'] | ['填空1','填空2'] | ['0'/'1']
|
||||||
|
let workAnswerArr = []
|
||||||
|
if (
|
||||||
|
row[i].workanswer.charAt(0) === '[' &&
|
||||||
|
row[i].workanswer.charAt(row[i].workanswer.length - 1) === ']'
|
||||||
|
) {
|
||||||
|
// 123会直接被转换, 且不是数组对象, 故手动判断是否有[和]两个字符
|
||||||
|
workAnswerArr = JSON.parse(row[i].workanswer)
|
||||||
|
} else if (row[i].workanswer.indexOf('#&') !== -1) {
|
||||||
|
workAnswerArr = row[i].workanswer.split('#&')
|
||||||
|
} else if (row[i].workanswer.indexOf(',') !== -1) {
|
||||||
|
workAnswerArr = row[i].workanswer.split(',')
|
||||||
|
} else {
|
||||||
|
// 单字符串直接添加至空数组(待考虑确认)
|
||||||
|
workAnswerArr.push(row[i].workanswer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 具体题型处理
|
||||||
|
if (row[i].worktype == '单选题' || row[i].worktype == '多选题') {
|
||||||
|
// 处理[选项显示] - 拼接ABCD首序号
|
||||||
|
let tmp = ''
|
||||||
|
let j = 0
|
||||||
|
for (; j < workDescArr.length; j++) {
|
||||||
|
if (j % 2 == 0) {
|
||||||
|
tmp += `<div style='width:80%;display:flex;'>`
|
||||||
|
}
|
||||||
|
const char = String.fromCharCode(65 + j)
|
||||||
|
tmp += `<div style='display:flex;margin-left: 2%; width: 36%'>${char}.${workDescArr[j]}</div>`
|
||||||
|
if (j % 2 == 1) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j % 2 == 0) {
|
||||||
|
tmp += '</div>'
|
||||||
|
}
|
||||||
|
row[i].workdescFormat = tmp
|
||||||
|
|
||||||
|
// 处理[答案显示] - 转换ABCD
|
||||||
|
let arr2Char = workAnswerArr
|
||||||
|
.map((item) => {
|
||||||
|
return String.fromCharCode(65 + Number(item))
|
||||||
|
})
|
||||||
|
.join('')
|
||||||
|
row[i].workanswerFormat = arr2Char
|
||||||
|
} else if (row[i].worktype == '填空题') {
|
||||||
|
// 处理[选项显示] - 填空题中无选项, 故置空
|
||||||
|
row[i].workdescFormat = ''
|
||||||
|
|
||||||
|
// 处理[答案显示] - 逗号连接
|
||||||
|
row[i].workanswerFormat = workAnswerArr.join('、')
|
||||||
|
} else if (row[i].worktype == '判断题') {
|
||||||
|
// 处理[选项显示] - 判断题中无选项, 故置空
|
||||||
|
row[i].workdescFormat = ''
|
||||||
|
|
||||||
|
// 处理[答案显示] - 1-正常 0-错误
|
||||||
|
const answer = workAnswerArr
|
||||||
|
.map((item) => {
|
||||||
|
return item === '1' ? '正确' : '错误'
|
||||||
|
})
|
||||||
|
.join('、')
|
||||||
|
row[i].workanswerFormat = answer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//2、处理单选题
|
||||||
|
if(row[i].worktype == '单选题' || row[i].worktype == '多选题' ){
|
||||||
|
//1.选项前增加ABCD workdesc: "①②#&①③#&②④#&③④" || "<div>为了活着</div>#&<div>为了填报肚子</div>#&<div>为了吃饭而吃饭</div>"
|
||||||
|
let workDescArr = [];
|
||||||
|
if(row[i].workdesc.indexOf('[')!==-1 && row[i].workdesc.indexOf(']')!==-1) {
|
||||||
|
//123会直接被转换, 且不是数组对象, 故手动判断是否有[和]两个字符
|
||||||
|
workDescArr = JSON.parse(row[i].workdesc);
|
||||||
|
}
|
||||||
|
else if(row[i].workdesc.indexOf('#&')) {
|
||||||
|
workDescArr = row[i].workdesc.split('#&');
|
||||||
|
}
|
||||||
|
else if(row[i].workdesc.indexOf(',')){
|
||||||
|
workDescArr = row[i].workdesc.split(',');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 待考虑
|
||||||
|
workDescArr.push(item.workdesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//2.答案 - 数字转为ABCD
|
||||||
|
if(row[i].worktype == '单选题') {
|
||||||
|
const str2Char = String.fromCharCode(65+Number(row[i].workanswer));
|
||||||
|
row[i].workanswerFormat = str2Char;
|
||||||
|
} else if (row[i].worktype == '多选题') {
|
||||||
|
const answerArr = row[i].workanswer.split('#&');
|
||||||
|
let arr2Char = '';
|
||||||
|
for(let k=0; k<answerArr.length; k++){
|
||||||
|
arr2Char += String.fromCharCode(65+Number(answerArr[k]));
|
||||||
|
}
|
||||||
|
row[i].workanswerFormat = arr2Char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(row[i].worktype == '填空题') {
|
||||||
|
// console.log(row[i].workanswer.replace(/<[^>]*>/g, "").split('#&'),'????')
|
||||||
|
// 填空题答案
|
||||||
|
row[i].workanswerFormat = row[i].workanswer.replace(/#&/g,", ");
|
||||||
|
// 填空选项不需要展示,
|
||||||
|
row[i].workdescFormat = '';
|
||||||
|
}
|
||||||
|
else if(row[i].worktype == '判断题'){
|
||||||
|
// console.log(row[i].workanswer.replace(/<[^>]*>/g, "").split('#&'),'????')
|
||||||
|
// 判断题答案
|
||||||
|
row[i].workanswerFormat = row[i].workanswer.replace(/#&/g,", ");
|
||||||
|
// 判断选项不需要展示,
|
||||||
|
row[i].workdescFormat = '';
|
||||||
|
}
|
||||||
|
else if(row[i].worktype == '复合题') {
|
||||||
|
// 1.选项解析替换
|
||||||
|
const options = JSON.parse(row[i].workdesc);
|
||||||
|
// 题目(背景材料+复合题目)
|
||||||
|
const bjTitle = row[i].title.split('!@#$%')[0];
|
||||||
|
const tmTitles = row[i].title.split('!@#$%').filter((it,ix)=>ix>0);
|
||||||
|
// console.log(bjTitle,'背景标题');
|
||||||
|
// console.log(tmTitles,'复合题目');
|
||||||
|
let titls = [];
|
||||||
|
options.forEach((element,index1) => {
|
||||||
|
const workDescArr = element.split('#&');
|
||||||
|
let tmp = '';
|
||||||
|
let j=0;
|
||||||
|
for(; j<jsonArr.length; j++){
|
||||||
|
if(j%2 == 0){
|
||||||
|
tmp += `<div style='width:80%;display:flex;'>`;
|
||||||
|
}
|
||||||
|
const char = String.fromCharCode(65+j);
|
||||||
|
tmp += `<div style='display:flex;margin-left: 2%; width: 36%'>${char}.${jsonArr[j]}</div>`;
|
||||||
|
if(j%2 == 1){
|
||||||
|
tmp += '</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(j%2== 0){
|
||||||
|
tmp += '</div>';
|
||||||
|
}
|
||||||
|
workdesc = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
row[i].workdescFormat = workdesc; // 题目选项
|
||||||
|
|
||||||
|
|
||||||
|
// 答案处理
|
||||||
|
let workanswer = '';
|
||||||
|
if(row[i].workanswer && row[i].workanswer != '') {
|
||||||
|
// 因答案内容存在多种格式: 1.["123","1234"] 2.123#&1234 3.123
|
||||||
|
if(row[i].workanswer.indexOf('[')!==-1 && row[i].workanswer.indexOf(']')!==-1) {
|
||||||
|
//123会直接被转换, 且不是数组对象, 故手动判断是否有[和]两个字符
|
||||||
|
let json = JSON.parse(row[i].workanswer);
|
||||||
|
// 单选、多选 需要 数字转为ABCD
|
||||||
|
if(row[i].worktype == '单选题') {
|
||||||
|
const str2Char = String.fromCharCode(65+Number(json[0]));
|
||||||
|
workanswer = str2Char;
|
||||||
|
} else if (row[i].worktype == '多选题') {
|
||||||
|
// const answerArr = row[i].workanswer.split('#&');
|
||||||
|
let arr2Char = '';
|
||||||
|
for(let k=0; k<json.length; k++){
|
||||||
|
arr2Char += String.fromCharCode(65+Number(json[k]));
|
||||||
|
}
|
||||||
|
workanswer = arr2Char;
|
||||||
|
} else if(row[i].worktype == '主观题' ) {
|
||||||
|
let arr2Char = '';
|
||||||
|
for(let k=0; k<json.length; k++){
|
||||||
|
const itemArr = json[k];
|
||||||
|
arr2Char += '('+ (parseInt(k) + 1) +')'+ itemArr.join('、')+ '<br />';
|
||||||
|
}
|
||||||
|
workanswer = arr2Char;
|
||||||
|
row[i].titleFormat = row[i].titleFormat.replace(/!@#\$%/g, '');
|
||||||
|
} else {
|
||||||
|
workanswer = json.join('、');
|
||||||
|
}
|
||||||
|
} else if(row[i].workanswer.indexOf('#&')) {
|
||||||
|
// 意味着多个答案或者填空内容
|
||||||
|
let workanswerList = row[i].workanswer.split('#&');
|
||||||
|
if(row[i].worktype == '多选题') {
|
||||||
|
// 数字转为ABCD
|
||||||
|
let arr2Char = '';
|
||||||
|
for(let k=0; k<workanswerList.length; k++){
|
||||||
|
arr2Char += String.fromCharCode(65+Number(workanswerList[k]));
|
||||||
|
}
|
||||||
|
workanswer = arr2Char;
|
||||||
|
}else{
|
||||||
|
workanswer = workanswerList.join('、');
|
||||||
|
}
|
||||||
|
} else if(row[i].workanswer.indexOf(',')){
|
||||||
|
// 意味这同样多个答案或者填空内容
|
||||||
|
let workanswerList = row[i].workanswer.split(',');
|
||||||
|
if(row[i].worktype == '多选题') {
|
||||||
|
// 数字转为ABCD
|
||||||
|
let arr2Char = '';
|
||||||
|
for(let k=0; k<workanswerList.length; k++){
|
||||||
|
arr2Char += String.fromCharCode(65+Number(workanswerList[k]));
|
||||||
|
}
|
||||||
|
workanswer = arr2Char;
|
||||||
|
}else{
|
||||||
|
workanswer = workanswerList.join('、');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 待考虑
|
||||||
|
workanswer = row[i].workanswer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
row[i].workanswerFormat = workanswer; // 题目正确答案
|
||||||
|
|
||||||
|
|
||||||
|
//2.答案 - 数字转为ABCD
|
||||||
|
const answerArr = JSON.parse(row[i].workanswer);
|
||||||
|
let indexLabel = 1;
|
||||||
|
let arr = [];
|
||||||
|
answerArr.forEach(item => {
|
||||||
|
const arrTmp = item.answer.split('#&');
|
||||||
|
let value = `(${indexLabel})`;
|
||||||
|
arrTmp.forEach((element,i) => {
|
||||||
|
if(item.type == '单选题' || item.type == '多选题'){
|
||||||
|
value += `${String.fromCharCode(65+Number(element))}`;
|
||||||
|
}
|
||||||
|
if(item.type == '判断题' || item.type == '填空题'){
|
||||||
|
// 去除下 html标签
|
||||||
|
value += `${element.replace(/<[^>]+>/g, '')}`+ (i==arrTmp.length-1?'':'、');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
arr.push(value);
|
||||||
|
indexLabel++;
|
||||||
|
})
|
||||||
|
const answer = arr.join('<br />');
|
||||||
|
|
||||||
|
row[i].workanswerFormat = answer;
|
||||||
|
}
|
||||||
|
else if(row[i].worktype == '主观题') {
|
||||||
|
// 1.选项解析替换---主观题没选项
|
||||||
|
// 题目(背景材料+主观题目)
|
||||||
|
const bjTitle = row[i].title.split('!@#$%')[0];
|
||||||
|
const tmTitles = row[i].title.split('!@#$%').filter((it,ix)=>ix>0);
|
||||||
|
// console.log(bjTitle,'背景标题');
|
||||||
|
// console.log(tmTitles,'主观题目');
|
||||||
|
let titls = [];
|
||||||
|
const s = [];
|
||||||
|
tmTitles.map((it,ix)=>{
|
||||||
|
s.push(it);
|
||||||
|
})
|
||||||
|
// console.log(s,'?????????????????')
|
||||||
|
|
||||||
|
row[i].titleFormat = bjTitle + s.join('');
|
||||||
|
// 填空选项不需要展示,
|
||||||
|
row[i].workdescFormat = '';
|
||||||
|
|
||||||
|
//2.答案
|
||||||
|
// 填空题答案
|
||||||
|
const workanswerList = JSON.parse(row[i].workanswer);
|
||||||
|
let tmp='';
|
||||||
|
workanswerList&&workanswerList.map((item,index)=>{
|
||||||
|
tmp += '<div>'+(index+1)+'.'+item.replace(/#&/g, ',')+'</div>';
|
||||||
|
})
|
||||||
|
row[i].workanswerFormat = tmp;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//处理答案
|
||||||
|
row[i].workanswerFormat = '见试题解答内容';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@
|
||||||
<el-dropdown-item @click="changePage('/profile')">个人中心</el-dropdown-item>
|
<el-dropdown-item @click="changePage('/profile')">个人中心</el-dropdown-item>
|
||||||
<el-dropdown-item @click="changePage('/classReserv')">课程预约</el-dropdown-item>
|
<el-dropdown-item @click="changePage('/classReserv')">课程预约</el-dropdown-item>
|
||||||
<el-dropdown-item @click="changePage('/class')">班级中心</el-dropdown-item>
|
<el-dropdown-item @click="changePage('/class')">班级中心</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click="changePage('/classTask')">作业批改</el-dropdown-item>
|
||||||
<el-dropdown-item divided command="logout">
|
<el-dropdown-item divided command="logout">
|
||||||
<span>退出登录</span>
|
<span>退出登录</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*
|
||||||
|
* @Author: 苦逼程序猿
|
||||||
|
* @Date: 2024-09-06 16:15:32
|
||||||
|
* @Warning: 千行代码,Bug露锋芒。
|
||||||
|
*/
|
||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
|
|
||||||
import Layout from '../layout/index.vue'
|
import Layout from '../layout/index.vue'
|
||||||
|
@ -57,6 +62,12 @@ export const constantRoutes = [
|
||||||
name: 'class',
|
name: 'class',
|
||||||
meta: {title: '班级中心'},
|
meta: {title: '班级中心'},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/classTask',
|
||||||
|
component: () => import('@/views/classTask/classTask.vue'),
|
||||||
|
name: 'class',
|
||||||
|
meta: {title: '作业批改'},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
...toolRouters
|
...toolRouters
|
||||||
|
|
|
@ -108,4 +108,29 @@ export const getAfterMinutes = (m) => {
|
||||||
let minutes = afterMinutes.getMinutes();
|
let minutes = afterMinutes.getMinutes();
|
||||||
minutes = minutes < 10 ? ('0' + minutes) : minutes
|
minutes = minutes < 10 ? ('0' + minutes) : minutes
|
||||||
return `${hours}:${minutes}`;
|
return `${hours}:${minutes}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格时间格式化
|
||||||
|
*/
|
||||||
|
export function formatDate(cellValue) {
|
||||||
|
if (cellValue == null || cellValue == "") return "";
|
||||||
|
var date = new Date(cellValue)
|
||||||
|
var year = date.getFullYear()
|
||||||
|
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
|
||||||
|
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
|
||||||
|
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
|
||||||
|
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
|
||||||
|
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
|
||||||
|
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
|
||||||
|
}
|
||||||
|
export function getTimeDate() {
|
||||||
|
var date = new Date()
|
||||||
|
var year = date.getFullYear()
|
||||||
|
var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
|
||||||
|
var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
|
||||||
|
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
|
||||||
|
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
|
||||||
|
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
|
||||||
|
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
|
||||||
}
|
}
|
|
@ -0,0 +1,394 @@
|
||||||
|
<!--
|
||||||
|
* @Author: 苦逼程序猿
|
||||||
|
* @Date: 2024-09-06 16:58:59
|
||||||
|
* @Warning: 千行代码,Bug露锋芒。
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-container class="class-reserv-wrap">
|
||||||
|
<div class="class-reserv-tabs">
|
||||||
|
<el-segmented v-model="tabActive" block :options="tabOptions" size="large" />
|
||||||
|
</div>
|
||||||
|
<div class="class-reserv-body">
|
||||||
|
<task-item
|
||||||
|
v-for="(item, index) in activeDataList"
|
||||||
|
v-show="tabActive === '进行中'"
|
||||||
|
:key="index"
|
||||||
|
:item="item"
|
||||||
|
:tabactive="tabActive"
|
||||||
|
@click="itemDialogRef.openDialog(item)"
|
||||||
|
@delete-reserv="deleteReserv(item)"
|
||||||
|
></task-item>
|
||||||
|
<task-item
|
||||||
|
v-for="(item, index) in doneDataList"
|
||||||
|
v-show="tabActive === '已结束'"
|
||||||
|
:key="index"
|
||||||
|
:item="item"
|
||||||
|
:tabactive="tabActive"
|
||||||
|
@click="itemDialogRef.openDialog(item)"
|
||||||
|
@delete-reserv="deleteReserv(item)"
|
||||||
|
></task-item>
|
||||||
|
</div>
|
||||||
|
<item-dialog ref="itemDialogRef"></item-dialog>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
|
||||||
|
import { getSelfReserv } from '@/api/classManage'
|
||||||
|
import { listClassmain } from '@/api/classManage/index'
|
||||||
|
import { listClassworkdata } from '@/api/classTask'
|
||||||
|
import { homeworklist } from '@/api/teaching/classwork'
|
||||||
|
|
||||||
|
import TaskItem from '@/views/classTask/container/task-item.vue'
|
||||||
|
import ItemDialog from '@/views/classTask/container/item-dialog.vue'
|
||||||
|
import { useToolState } from '@/store/modules/tool'
|
||||||
|
import { sessionStore } from '@/utils/tool'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
const userStore = useUserStore().user
|
||||||
|
const itemDialogRef = ref(null)
|
||||||
|
const tabOptions = ref(['进行中', '已结束'])
|
||||||
|
const tabActive = ref('进行中')
|
||||||
|
const dataList = ref([])
|
||||||
|
|
||||||
|
// 班级列表
|
||||||
|
const classList = ref([])
|
||||||
|
const classListIds = ref([])
|
||||||
|
// 所有班级作业列表
|
||||||
|
const classWorkList = ref([])
|
||||||
|
const total = ref(0)
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const activeDataList = computed(() => {
|
||||||
|
// return classWorkList.value
|
||||||
|
// 当前时间超过[作业任务]截止时间的跳过
|
||||||
|
return classWorkList.value && classWorkList.value.filter((item) => getDateTime > item.deaddate)
|
||||||
|
})
|
||||||
|
const deleteReserv = (item) => {
|
||||||
|
console.log('删除待开发', item)
|
||||||
|
// dataList.value = dataList.value.filter((is) => {
|
||||||
|
// return is.id !== item.id
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
const doneDataList = computed(() => {
|
||||||
|
// return classWorkList.value
|
||||||
|
return classWorkList.value && classWorkList.value.filter((item) => getDateTime < item.deaddate)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const getData = () => {
|
||||||
|
// 获取班级列表
|
||||||
|
listClassmain({ classuserid: userStore.userId, pageSize: 100, status: 'open' }).then((res) => {
|
||||||
|
var clslist = []
|
||||||
|
for (var i = 0; i < res.rows.length; i++) {
|
||||||
|
if (res.rows[i].classstudentlist != '') {
|
||||||
|
var array = JSON.parse('[' + res.rows[i].classstudentlist + ']')
|
||||||
|
res.rows[i].classstudents = array
|
||||||
|
}
|
||||||
|
classListIds.value.push(res.rows[i].id)
|
||||||
|
clslist.push(res.rows[i])
|
||||||
|
}
|
||||||
|
classList.value = clslist
|
||||||
|
|
||||||
|
// 班级作业数据,包含多个班级
|
||||||
|
homeworklist({
|
||||||
|
classidarray: classListIds.value.join(','),
|
||||||
|
entpcourseid: '', // 章节id? 这里要全课程的作业 不分章节?
|
||||||
|
orderby: 'uniquekey DESC',
|
||||||
|
pageSize: 100
|
||||||
|
}).then((response) => {
|
||||||
|
for (var i = 0; i < response.rows.length; i++) {
|
||||||
|
// 初始化部分新增字段值
|
||||||
|
response.rows[i].workdatalist = []
|
||||||
|
response.rows[i].workdatacount = 0 // 人数
|
||||||
|
response.rows[i].workdatalistVisible = false
|
||||||
|
response.rows[i].workdatafeedbackcount = 0
|
||||||
|
response.rows[i].feedtimelength = 0
|
||||||
|
response.rows[i].rightAnswerCount = 0
|
||||||
|
response.rows[i].scoingRate = 0 + '%' // 得分率
|
||||||
|
response.rows[i].averagetime = 0 // 平均用时
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
// 处理任务类型的UI
|
||||||
|
if (response.rows[i].worktype == '学习目标定位') {
|
||||||
|
response.rows[i].workclass = 'success'
|
||||||
|
response.rows[i].workcodesList = JSON.parse(response.rows[i].workcodes)
|
||||||
|
} else if (response.rows[i].worktype == '教材研读') {
|
||||||
|
response.rows[i].workclass = 'primary'
|
||||||
|
} else if (response.rows[i].worktype == '框架梳理') {
|
||||||
|
response.rows[i].workclass = 'warning'
|
||||||
|
} else if (response.rows[i].worktype == '学科定位') {
|
||||||
|
response.rows[i].workclass = 'info'
|
||||||
|
} else if (response.rows[i].worktype == '习题训练') {
|
||||||
|
response.rows[i].workclass = 'danger'
|
||||||
|
} else {
|
||||||
|
response.rows[i].workclass = ''
|
||||||
|
}
|
||||||
|
// 如果是习题训练任务,则检查一共有多少道
|
||||||
|
if (response.rows[i].entpcourseworklist != '') {
|
||||||
|
response.rows[i].entpcourseworklistarray = JSON.parse(
|
||||||
|
'[' + response.rows[i].entpcourseworklist + ']'
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
response.rows[i].entpcourseworklistarray = []
|
||||||
|
}
|
||||||
|
// 根据 classworkdatastudentids 初始化判断分配的人数
|
||||||
|
if (
|
||||||
|
response.rows[i].classworkdatastudentids != '' &&
|
||||||
|
response.rows[i].classworkdatastudentids != null &&
|
||||||
|
response.rows[i].classworkdatastudentids != 'null'
|
||||||
|
) {
|
||||||
|
const stuList = JSON.parse('[' + response.rows[i].classworkdatastudentids + ']')
|
||||||
|
response.rows[i].workdatacount = stuList.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示分配人数>0 的
|
||||||
|
if (response.rows && response.rows.length > 0) {
|
||||||
|
classWorkList.value =
|
||||||
|
response.rows && response.rows.filter((item) => item.workdatacount > 0)
|
||||||
|
//TODO: 这里没分页,貌似这个 total 不重要,后续看
|
||||||
|
total.value = response.total
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
|
||||||
|
// 再查找多个班级里,每个学生的作业数据
|
||||||
|
getStudentClassWorkData()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
//--------------
|
||||||
|
// getSelfReserv().then((res) => {
|
||||||
|
// const list = res.data || []
|
||||||
|
// list.sort((a, b) => {
|
||||||
|
// if (a.status == '上课中') return -1
|
||||||
|
// else return 0
|
||||||
|
// })
|
||||||
|
// dataList.value = list
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
const toolStore = useToolState()
|
||||||
|
|
||||||
|
// 将标签中的双引号增加转义
|
||||||
|
const escapeHtmlQuotes = (str) => {
|
||||||
|
// 后端已replace双引号, 故前端不用在处理
|
||||||
|
return str
|
||||||
|
|
||||||
|
// 只对双引号进行转义
|
||||||
|
// return str.replace(/(<[^>]+>)/g, function (match) {
|
||||||
|
// return match.replace(/"/g, '\\"')
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
const pollingST = ref(null) //轮询定时器标识
|
||||||
|
onMounted(() => {
|
||||||
|
getData() // 加载数据
|
||||||
|
// 轮询查询
|
||||||
|
pollingST.value = setInterval(() => {
|
||||||
|
getStudentVisible()
|
||||||
|
}, 1000 * 60)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearInterval(pollingST.value)
|
||||||
|
//clearInterval(this.classWorkActiveData.timerId) // 关闭定时器 作业概况的
|
||||||
|
})
|
||||||
|
|
||||||
|
const getDateTime = () => {
|
||||||
|
//获取当前时间
|
||||||
|
const now = new Date()
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(now.getDate()).padStart(2, '0')
|
||||||
|
const hh = String(now.getHours()).padStart(2, '0')
|
||||||
|
const mm = String(now.getMinutes()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day} ${hh}:${mm}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// [作业反馈] - 实际查询逻辑
|
||||||
|
const getStudentVisible = async () => {
|
||||||
|
if (classListIds.value.length <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 班级作业数据,多个班级
|
||||||
|
const response = await homeworklist({
|
||||||
|
classidarray: classListIds.value.join(','),
|
||||||
|
entpcourseid: '', // 章节???这里不需要,全课程的
|
||||||
|
orderby: 'uniquekey DESC',
|
||||||
|
pageSize: 100
|
||||||
|
})
|
||||||
|
const curWorkList = response.rows
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
)
|
||||||
|
// 计算参与学习任务的平均用时
|
||||||
|
console.log('平均用时??---', classWorkList.value[t].workdatafeedbackcount)
|
||||||
|
if (classWorkList.value[t].workdatafeedbackcount > 0) {
|
||||||
|
classWorkList.value[t].averagetime = (
|
||||||
|
classWorkList.value[t].feedtimelength / classWorkList.value[t].workdatafeedbackcount
|
||||||
|
).toFixed(0)
|
||||||
|
console.log('平均用时---', classWorkList.value[t].averagetime)
|
||||||
|
} else {
|
||||||
|
classWorkList.value[t].averagetime = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classWorkList.value[t].finishpercent = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取多个班级学生作业数据
|
||||||
|
const getStudentClassWorkData = () => {
|
||||||
|
// 再查找多个班级里,每个学生的作业数据
|
||||||
|
console.log('======????????""""""""""')
|
||||||
|
listClassworkdata({
|
||||||
|
classids: classListIds.value.join(','),
|
||||||
|
entpcourseid: '', // 章节id? 这里要全课程的作业 不分章节?
|
||||||
|
pageSize: 1000
|
||||||
|
}).then((res) => {
|
||||||
|
console.log('多个班级里,每个学生的作业数据', res.rows)
|
||||||
|
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) {
|
||||||
|
// if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].resultcount > 0) {
|
||||||
|
console.log('==================')
|
||||||
|
// 有几个学生完成/正在完成学习任务
|
||||||
|
// 至少resultcount不是0
|
||||||
|
classWorkList.value[t].workdatafeedbackcount++
|
||||||
|
|
||||||
|
// 在参与学习任务的人中,汇总计算用时
|
||||||
|
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\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\"},{\"id\":172911, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363100, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\"}"
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以下四个参数,都要计算
|
||||||
|
// 2024-04-12,酉阳,by jackyshen
|
||||||
|
|
||||||
|
// 计算参与学习任务的平均用时
|
||||||
|
if (classWorkList.value[t].workdatafeedbackcount > 0) {
|
||||||
|
classWorkList.value[t].averagetime =
|
||||||
|
(
|
||||||
|
classWorkList.value[t].feedtimelength / classWorkList.value[t].workdatafeedbackcount
|
||||||
|
).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%'
|
||||||
|
}
|
||||||
|
// 设定典型作答,需要获取每个题目的类型,找出主观题
|
||||||
|
// 暂缓
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [dataList, toolStore.isToolWin],
|
||||||
|
() => {
|
||||||
|
console.log('====', toolStore)
|
||||||
|
setTimeout(() => {
|
||||||
|
getData() // 加载数据
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.class-reserv-wrap {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 15px 30px;
|
||||||
|
.class-reserv-tabs {
|
||||||
|
width: 30%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.class-reserv-body {
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,964 @@
|
||||||
|
<template>
|
||||||
|
<el-form ref="classWorkFormScoreRef" :model="classWorkFormScore">
|
||||||
|
<div class="teacher_content" :style="{ height: dialogProps.maxheight + 'px' }">
|
||||||
|
<div style="font-size: 18px; width: 100%; padding: 5px 10px" class="sticky">
|
||||||
|
{{ classWorkFormScore.name }} 答题详情
|
||||||
|
</div>
|
||||||
|
<div class="teacher_content_con">
|
||||||
|
<!-- 题目内容:习题训练 -->
|
||||||
|
<div v-if="dialogProps.studentObj.worktype == '习题训练'">
|
||||||
|
<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 }}
|
||||||
|
{{ stuItem.score ? stuItem.score : 0 }}分</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 习题训练 -->
|
||||||
|
<div v-if="dialogProps.studentObj.worktype == '习题训练'">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24" style="padding: 10px">
|
||||||
|
<!-- 题源、题目标题、题目选项 -->
|
||||||
|
<span>{{ quItem.worktag }}</span>
|
||||||
|
<span style="margin-left: 4px" v-html="quItem.titleFormat"></span>
|
||||||
|
<div :span="24" style="padding: 10px" v-html="quItem.workdescFormat"></div>
|
||||||
|
<!-- 折叠: 详情分析解答 -->
|
||||||
|
<div class="demo-collapse">
|
||||||
|
<el-collapse>
|
||||||
|
<el-collapse-item title="详情分析解答" name="1">
|
||||||
|
<el-row style="padding: 1% 4%; border: 2px dotted">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-col :span="2" style="padding: 10px 0px"
|
||||||
|
><em>【答案】</em></el-col
|
||||||
|
>
|
||||||
|
<el-col
|
||||||
|
:span="21"
|
||||||
|
style="padding: 10px 0px"
|
||||||
|
v-html="quItem.workanswerFormat"
|
||||||
|
></el-col>
|
||||||
|
<el-col :span="2" style="padding: 10px 0px"
|
||||||
|
><em>【分析】</em></el-col
|
||||||
|
>
|
||||||
|
<el-col
|
||||||
|
:span="21"
|
||||||
|
style="padding: 10px 0px"
|
||||||
|
v-html="quItem.method"
|
||||||
|
></el-col>
|
||||||
|
<el-col :span="2" style="padding: 10px 0px"
|
||||||
|
><em>【解答】</em></el-col
|
||||||
|
>
|
||||||
|
<el-col
|
||||||
|
:span="21"
|
||||||
|
style="padding: 10px 0px"
|
||||||
|
v-html="quItem.analyse"
|
||||||
|
></el-col>
|
||||||
|
<el-col :span="2" style="padding: 10px 0px"
|
||||||
|
><em>【点评】</em></el-col
|
||||||
|
>
|
||||||
|
<el-col
|
||||||
|
:span="21"
|
||||||
|
style="padding: 10px 0px"
|
||||||
|
v-html="quItem.discuss"
|
||||||
|
></el-col>
|
||||||
|
</template>
|
||||||
|
</el-row>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<!-- 答案 -->
|
||||||
|
<template #footer>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="6" style="padding: 10px">
|
||||||
|
<span
|
||||||
|
>参考答案:
|
||||||
|
<span v-if="quItem.workanswerFormat != ''">
|
||||||
|
<sapn
|
||||||
|
style="
|
||||||
|
background-color: #0ed116;
|
||||||
|
color: white;
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
"
|
||||||
|
>{{ quItem.workanswerFormat.replace(/<[^>]+>/g, '') }}</sapn
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="padding: 10px">
|
||||||
|
<!-- <span>学生答案:{{ stuItem.feedcontent }}</span> -->
|
||||||
|
<span
|
||||||
|
>学生答案:
|
||||||
|
<span v-if="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>
|
||||||
|
<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>
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
<el-image
|
||||||
|
style="width: 30px; height: 30px"
|
||||||
|
:src="imageItem"
|
||||||
|
:zoom-rate="1.2"
|
||||||
|
:max-scale="7"
|
||||||
|
:min-scale="0.2"
|
||||||
|
:preview-src-list="stuItem.imagefile"
|
||||||
|
:initial-index="4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="padding: 10px">
|
||||||
|
<!-- 单选题 填空题 多选题 判断题 主观题 复合题; 待完善:
|
||||||
|
1、目前只支持单选题、多选题不用老师批改分数,这里先禁止分值修改; -->
|
||||||
|
<el-input-number
|
||||||
|
v-model="classWorkFormScore.teacherRating[sIndex].score"
|
||||||
|
:min="0"
|
||||||
|
:max="classWorkFormScore.teacherRating[sIndex].maxScore"
|
||||||
|
size="small"
|
||||||
|
:disabled="
|
||||||
|
(quItem.worktype == '单选题' || quItem.worktype == '多选题') &&
|
||||||
|
stuItem.feedcontent == stuItem.rightanswer &&
|
||||||
|
stuItem.feedcontent != ''
|
||||||
|
? true
|
||||||
|
: false
|
||||||
|
"
|
||||||
|
></el-input-number>
|
||||||
|
分
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 题目内容:常规作业、课堂展示 -->
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
dialogProps.studentObj.worktype == '常规作业' ||
|
||||||
|
dialogProps.studentObj.worktype == '课堂展示' ||
|
||||||
|
dialogProps.studentObj.worktype == '框架梳理'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div v-for="(stuItem, sIndex) in dialogProps.studentQuizAllList" :key="stuItem.id">
|
||||||
|
<el-card style="max-width: 100%; margin-bottom: 10px">
|
||||||
|
<!-- 题型 分值 -->
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>{{ sIndex + 1 }}、{{ stuItem.score ? stuItem.score : 0 }}分</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 常规作业 -->
|
||||||
|
<div
|
||||||
|
v-if="
|
||||||
|
dialogProps.studentObj.worktype == '常规作业' ||
|
||||||
|
dialogProps.studentObj.worktype == '课堂展示' ||
|
||||||
|
dialogProps.studentObj.worktype == '框架梳理'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<!-- 文件内容格式:mp3/mp4/doc/docx/excel/pdf/ppt/pptx/jpg/jpeg/gif/png/txt ->
|
||||||
|
<-- 老师附件展示 -->
|
||||||
|
<!-- 折叠: 详情分析解答 -->
|
||||||
|
<div v-if="teacherFeedContentList.length > 0">
|
||||||
|
<div class="demo-collapse" style="border: 2px dotted">
|
||||||
|
<el-collapse>
|
||||||
|
<el-collapse-item title="老师布置详情" name="1">
|
||||||
|
<div class="image_list">
|
||||||
|
<div v-if="teachImageList.length > 0">
|
||||||
|
<div style="margin-bottom: 5px">
|
||||||
|
<span style="color: red">温馨提示:点击图片可放大预览 </span>
|
||||||
|
</div>
|
||||||
|
<div v-for="(imageItem, index) in teachImageList" :key="index">
|
||||||
|
<el-image
|
||||||
|
style="width: 400px; height: 400px"
|
||||||
|
:src="imageItem.url"
|
||||||
|
:zoom-rate="1.2"
|
||||||
|
:max-scale="7"
|
||||||
|
:min-scale="0.2"
|
||||||
|
:preview-src-list="
|
||||||
|
teachImageList
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.name.indexOf('jpg') > -1 ||
|
||||||
|
item.name.indexOf('jpeg') > -1 ||
|
||||||
|
item.name.indexOf('png') > -1
|
||||||
|
)
|
||||||
|
.map((item) => item.url)
|
||||||
|
"
|
||||||
|
:initial-index="4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="teachFileList.length > 0">
|
||||||
|
<div style="margin: 10px 0">
|
||||||
|
<span style="color: red" @click="openFile"
|
||||||
|
>温馨提示:点击此处 可预览其他类型附件!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 学生答题展示 -->
|
||||||
|
<div v-if="feedContentList.length > 0">
|
||||||
|
<p>学生答题附件内容</p>
|
||||||
|
<div class="image_list">
|
||||||
|
<div v-if="imageList.length > 0">
|
||||||
|
<div style="margin-bottom: 5px">
|
||||||
|
<span style="color: red">温馨提示:点击图片可放大预览 </span>
|
||||||
|
</div>
|
||||||
|
<div v-for="(imageItem, index) in imageList" :key="index">
|
||||||
|
<el-image
|
||||||
|
style="width: 500px; height: 500px"
|
||||||
|
:src="imageItem.url"
|
||||||
|
:zoom-rate="1.2"
|
||||||
|
:max-scale="7"
|
||||||
|
:min-scale="0.2"
|
||||||
|
:preview-src-list="
|
||||||
|
imageList
|
||||||
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
item.name.indexOf('jpg') > -1 ||
|
||||||
|
item.name.indexOf('jpeg') > -1 ||
|
||||||
|
item.name.indexOf('png') > -1
|
||||||
|
)
|
||||||
|
.map((item) => item.url)
|
||||||
|
"
|
||||||
|
:initial-index="4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="fileList.length > 0">
|
||||||
|
<div style="margin: 10px 0">
|
||||||
|
<span style="color: red" @click="openFile"
|
||||||
|
>温馨提示:点击此处 可预览其他类型附件!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-empty
|
||||||
|
description="该学生还未作答"
|
||||||
|
style="width: 100%; height: 200px"
|
||||||
|
></el-empty>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 答案 -->
|
||||||
|
<!-- <template #footer>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12" style="padding: 10px">
|
||||||
|
<el-input-number v-model="classWorkFormScore.teacherRating[sIndex].score"
|
||||||
|
:controls="false"
|
||||||
|
:min="0"
|
||||||
|
:max="classWorkFormScore.teacherRating[sIndex].maxScore"
|
||||||
|
size="small"
|
||||||
|
></el-input-number> 分
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template> -->
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 批改评价与评语 -->
|
||||||
|
<div class="tacher_conten_foot">
|
||||||
|
<el-row style="padding: 1% 4%; border: 2px dotted">
|
||||||
|
<el-col :span="24" style="display: flex; flex-direction: column">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="14">
|
||||||
|
<div style="display: flex; margin: 10px auto">
|
||||||
|
<span style="display: flex; align-items: center">
|
||||||
|
<span v-if="dialogProps.studentObj.worktype == '习题训练'">
|
||||||
|
得分:<span style="margin: 0; color: red">{{
|
||||||
|
classWorkFormScore.teacherRating.reduce((a, b) => a + b.score, 0).toFixed(2)
|
||||||
|
}}</span
|
||||||
|
>分
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
得分:
|
||||||
|
<span v-if="classWorkFormScore.teacherRating.length > 0">
|
||||||
|
<el-input-number
|
||||||
|
v-model="classWorkFormScore.teacherRating[0].score"
|
||||||
|
:controls="false"
|
||||||
|
type="number"
|
||||||
|
:min="0"
|
||||||
|
:max="classWorkFormScore.teacherRating[0].maxScore"
|
||||||
|
size="small"
|
||||||
|
style="width: 60px"
|
||||||
|
@change="handleChange"
|
||||||
|
></el-input-number>
|
||||||
|
</span>
|
||||||
|
分
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div class="score-container">
|
||||||
|
<div
|
||||||
|
v-for="(score, index) in teacherRatingList"
|
||||||
|
:key="index"
|
||||||
|
:class="[
|
||||||
|
'score-circle',
|
||||||
|
{ active: classWorkFormScore.rating == score.ratingKey }
|
||||||
|
]"
|
||||||
|
@click="selectScore(score)"
|
||||||
|
>
|
||||||
|
{{ score.ratingValue }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="10" style="display: flex; align-items: center">
|
||||||
|
<el-select
|
||||||
|
v-model="value"
|
||||||
|
placeholder="常用评语"
|
||||||
|
style="width: 240px"
|
||||||
|
@change="onSelectOption"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in cities"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
<template #footer>
|
||||||
|
<el-button v-if="!isAdding" text bg size="small" @click="onAddOption">
|
||||||
|
新增常用语
|
||||||
|
</el-button>
|
||||||
|
<template v-else>
|
||||||
|
<el-input
|
||||||
|
v-model="optionName"
|
||||||
|
class="option-input"
|
||||||
|
placeholder="输入新的常用语"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
<el-button type="primary" size="small" @click="onConfirm"> 确定 </el-button>
|
||||||
|
<el-button size="small" @click="clear">取消</el-button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24" style="display: flex; flex-direction: column">
|
||||||
|
<el-form-item label="评语说明">
|
||||||
|
<el-col :span="15" style="padding: 0px">
|
||||||
|
<el-input
|
||||||
|
v-model="classWorkFormScore.teacherremark"
|
||||||
|
type="textarea"
|
||||||
|
rows="3"
|
||||||
|
placeholder="请输入评语说明"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div style="margin: 10px">
|
||||||
|
<el-button type="primary" @click="onClassWorkFormScoreSave">批阅确认</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="fileReadopen"
|
||||||
|
title="文件预览"
|
||||||
|
width="80%"
|
||||||
|
:style="{ height: dialogProps.maxheight + 'px' }"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<div class="file-read-dialog">
|
||||||
|
<div>
|
||||||
|
<!-- 老师附件 -->
|
||||||
|
<div v-if="teachFileList.length > 0">
|
||||||
|
<el-card style="max-width: 480px">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>老师文件列表</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
v-for="item in teachFileList"
|
||||||
|
:key="item"
|
||||||
|
style="margin: 10px; display: flex; align-items: center"
|
||||||
|
>
|
||||||
|
<span style="margin-right: 10px">{{ item.name }}</span>
|
||||||
|
<el-button type="primary" @click="onFileRead(item)">预览</el-button>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<!-- 学生附件 -->
|
||||||
|
<div v-if="fileList.length > 0">
|
||||||
|
<el-card style="max-width: 480px">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span>学生文件列表</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
v-for="item in fileList"
|
||||||
|
:key="item"
|
||||||
|
style="margin: 10px; display: flex; align-items: center"
|
||||||
|
>
|
||||||
|
<span style="margin-right: 10px">{{ item.name }}</span>
|
||||||
|
<el-button type="primary" @click="onFileRead(item)">预览</el-button>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 100%" :style="{ height: dialogProps.maxheight + 'px' }">
|
||||||
|
<div style="margin-left: 10px">
|
||||||
|
预览展示区域<span style="color: red; margin-left: 10px">
|
||||||
|
温馨提示:若预览失败,<span style="margin-left: 10px">{{ props.name }}</span
|
||||||
|
>可点击此处<a
|
||||||
|
:href="fileitem.url ? fileitem.url : ''"
|
||||||
|
target="_blank"
|
||||||
|
style="color: blue"
|
||||||
|
>下载!</a
|
||||||
|
></span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<!-- <ReFilePreview
|
||||||
|
:name="fileitem.name"
|
||||||
|
:type="fileitem.type"
|
||||||
|
:file-type="fileitem.type"
|
||||||
|
:file-path="fileitem.url"
|
||||||
|
:text-content="textContent"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="classWorkAnalysisScoreDialogRef">
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
// import useAppStore from '@/store/modules/app'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
// import { Plus } from '@element-plus/icons-vue'
|
||||||
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
|
import { updateClassworkeval } from '@/api/classTask'
|
||||||
|
import { getTimeDate } from '@/utils/date'
|
||||||
|
// import ReFilePreview from '@/components/ReFilePreview/index.vue'
|
||||||
|
|
||||||
|
// import mammoth from 'mammoth'
|
||||||
|
// import * as XLSX from 'xlsx'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const emits = defineEmits(['class_work_score_submit'])
|
||||||
|
const props = defineProps({})
|
||||||
|
|
||||||
|
const fileReadopen = ref(false)
|
||||||
|
const analysisScoreOpen = ref(false)
|
||||||
|
|
||||||
|
const dialogProps = ref({
|
||||||
|
maxheight: 300,
|
||||||
|
studentObj: {}, //
|
||||||
|
studentQuizAllList: [], //学生答题的list
|
||||||
|
quizlist: [] // 当前学生的所有题目list
|
||||||
|
})
|
||||||
|
//学生常规作业list
|
||||||
|
const feedContentList = ref([])
|
||||||
|
const imageList = ref([])
|
||||||
|
const fileList = ref([])
|
||||||
|
// 老师常规作业、课堂展示布置题目附件list
|
||||||
|
const teacherFeedContentList = ref([])
|
||||||
|
const teachImageList = ref([])
|
||||||
|
const teachFileList = ref([])
|
||||||
|
|
||||||
|
// 提交分值批改
|
||||||
|
const classWorkFormScore = reactive({
|
||||||
|
name: '', // 学生姓名
|
||||||
|
score: 0, // 分值
|
||||||
|
teacherRating: [], // 老师批改题目list信息
|
||||||
|
rating: 0, // 评价星数 1-优 2-优减 3-良 4-良减 5-差
|
||||||
|
teacherremark: '' //评分说明
|
||||||
|
})
|
||||||
|
const teacherRatingList = ref([
|
||||||
|
{ ratingKey: '1', ratingValue: '优' },
|
||||||
|
{ ratingKey: '2', ratingValue: '优-' },
|
||||||
|
{ ratingKey: '3', ratingValue: '良' },
|
||||||
|
{ ratingKey: '4', ratingValue: '良-' },
|
||||||
|
{ ratingKey: '5', ratingValue: '差' }
|
||||||
|
])
|
||||||
|
// 确定的线上图片数据
|
||||||
|
//#region 文件内容相关
|
||||||
|
const fileitem = reactive({
|
||||||
|
name: '',
|
||||||
|
type: '',
|
||||||
|
url: ''
|
||||||
|
})
|
||||||
|
// 文件预览
|
||||||
|
const onFileRead = (file) => {
|
||||||
|
textContent.value = '1'
|
||||||
|
//
|
||||||
|
fileitem.type = file.name.split('.').pop().toLowerCase()
|
||||||
|
fileitem.url = file.url
|
||||||
|
fileitem.name = file.name
|
||||||
|
|
||||||
|
// txt 读取
|
||||||
|
if (fileitem.type == 'txt') {
|
||||||
|
loadFileTextContent(fileitem.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const openFile = () => {
|
||||||
|
console.log('打开文件弹窗!')
|
||||||
|
fileReadopen.value = true
|
||||||
|
}
|
||||||
|
// txt文件读取
|
||||||
|
const textContent = ref('')
|
||||||
|
const loadFileTextContent = async (url) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url)
|
||||||
|
if (!response.ok) {
|
||||||
|
textContent.value = '文件读取失败,您可以点击上方链接跳到另外页面查看'
|
||||||
|
throw new Error('文件读取失败')
|
||||||
|
}
|
||||||
|
textContent.value = await response.text()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取文件时出错:', error)
|
||||||
|
textContent.value = '文件读取失败,您可以点击上方链接跳到另外页面查看'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
// 输入数字,有e这个异类可输入,处理一下
|
||||||
|
// 输入e value为null
|
||||||
|
const handleChange = (value) => {
|
||||||
|
console.log(value, '=====')
|
||||||
|
console.log(typeof value, '===value==')
|
||||||
|
// if ((value+"").includes('e')) {
|
||||||
|
// classWorkFormScore.teacherRating[0].score = value.replace('e', '');
|
||||||
|
// }
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
console.log('??????')
|
||||||
|
classWorkFormScore.teacherRating[0].score = 0
|
||||||
|
} else {
|
||||||
|
classWorkFormScore.teacherRating[0].score = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 常用评语相关
|
||||||
|
const isAdding = ref(false)
|
||||||
|
const value = ref([])
|
||||||
|
const optionName = ref('')
|
||||||
|
const cities = ref([
|
||||||
|
{
|
||||||
|
value: '需要继续加油努力哟!棒棒哒!',
|
||||||
|
label: '需要继续加油努力哟!棒棒哒!'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '做得很好',
|
||||||
|
label: '做得很好'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要改进',
|
||||||
|
label: '需要改进'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更多练习',
|
||||||
|
label: '需要更多练习'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更仔细',
|
||||||
|
label: '需要更仔细'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更清晰',
|
||||||
|
label: '需要更清晰'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更准确',
|
||||||
|
label: '需要更准确'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更详细',
|
||||||
|
label: '需要更详细'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更简洁',
|
||||||
|
label: '需要更简洁'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更有条理',
|
||||||
|
label: '需要更有条理'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '需要更有创意',
|
||||||
|
label: '需要更有创意'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const onSelectOption = (option) => {
|
||||||
|
classWorkFormScore.teacherremark = option
|
||||||
|
}
|
||||||
|
const onAddOption = () => {
|
||||||
|
isAdding.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const onConfirm = () => {
|
||||||
|
if (optionName.value) {
|
||||||
|
cities.value.push({
|
||||||
|
label: optionName.value,
|
||||||
|
value: optionName.value
|
||||||
|
})
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
optionName.value = ''
|
||||||
|
isAdding.value = false
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
const selectScore = (score) => {
|
||||||
|
console.log(score, 'score----')
|
||||||
|
classWorkFormScore.rating = score.ratingKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收父组件传过来的参数
|
||||||
|
const acceptParams = (params) => {
|
||||||
|
console.log(params)
|
||||||
|
console.log(dialogProps, 'dialogProps')
|
||||||
|
// 先重置一下 参数
|
||||||
|
// 重置提交表单
|
||||||
|
classWorkFormScore.name = '' // 学生姓名
|
||||||
|
classWorkFormScore.score = 0 // 分值
|
||||||
|
classWorkFormScore.teacherRating = [] // 教师评分
|
||||||
|
classWorkFormScore.rating = 0 // 评价星数 1-优 2-优减 3-良 4-良减 5-差
|
||||||
|
classWorkFormScore.teacherremark = '' //评分说明
|
||||||
|
value.value = '' // 常用语重置
|
||||||
|
// 学生作业预览缓存清除
|
||||||
|
feedContentList.value = []
|
||||||
|
imageList.value = []
|
||||||
|
fileList.value = []
|
||||||
|
// 老师布置附件缓存清除
|
||||||
|
teacherFeedContentList.value = []
|
||||||
|
teachImageList.value = []
|
||||||
|
teachFileList.value = []
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
dialogProps.value = params
|
||||||
|
classWorkFormScore.name = params.studentObj.studentname
|
||||||
|
|
||||||
|
// 学生答题分值初始化
|
||||||
|
if (params.studentQuizAllList.length > 0) {
|
||||||
|
if (params.studentObj.worktype == '习题训练') {
|
||||||
|
params.studentQuizAllList.forEach((item) => {
|
||||||
|
params.quizlist.forEach((item2) => {
|
||||||
|
//
|
||||||
|
if (item.entpcourseworkid == item2.id) {
|
||||||
|
// 单选题 填空题 多选题 判断题 主观题 复合题; 待完善:
|
||||||
|
classWorkFormScore.teacherRating.push({
|
||||||
|
maxScore: item.score ? item.score : 100, //分值最大值 不能大于题目的分值 ?没有,那就最大100
|
||||||
|
score:
|
||||||
|
(item2.worktype == '单选题' || item2.worktype == '多选题') &&
|
||||||
|
item.feedcontent == item.rightanswer
|
||||||
|
? item.score
|
||||||
|
: item.teacherRating
|
||||||
|
? item.teacherRating
|
||||||
|
: 0, // 教师批改分值: 单选多选 默认批改为题目分值
|
||||||
|
id: item.id // 学生答题列表的id
|
||||||
|
})
|
||||||
|
classWorkFormScore.teacherremark = item.teacherremark // 评价语
|
||||||
|
|
||||||
|
// 主观题中学生回答有图片?imagefile: “” ; “[null]”; "[\"https://wzyzoss.ee2f687.png\"]"
|
||||||
|
if (item.imagefile != '') {
|
||||||
|
// 其他: !主观题 为“”;
|
||||||
|
const filelist = JSON.parse(item.imagefile)
|
||||||
|
console.log(filelist, '学生习题附带图片fimagefile-------------')
|
||||||
|
|
||||||
|
if (filelist && filelist.length > 0 && filelist[0] != null) {
|
||||||
|
item.imagefile = filelist
|
||||||
|
} else {
|
||||||
|
item.imagefile = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 学生回答
|
||||||
|
if (params.studentObj.worktype == '常规作业') {
|
||||||
|
try {
|
||||||
|
// 老师布置的附件 datacontent TODO:常规作业、其他类型还未接入
|
||||||
|
if (params.studentObj.datacontent != '') {
|
||||||
|
const teachWorkFileList = JSON.parse(params.studentObj.datacontent)
|
||||||
|
console.log(teachWorkFileList, '老师filelist-------------')
|
||||||
|
teachWorkFileList &&
|
||||||
|
teachWorkFileList.forEach((item) => {
|
||||||
|
if (
|
||||||
|
item.name.indexOf('jpg') > -1 ||
|
||||||
|
item.name.indexOf('jpeg') > -1 ||
|
||||||
|
item.name.indexOf('png') > -1
|
||||||
|
) {
|
||||||
|
teachImageList.value.push(item)
|
||||||
|
} else {
|
||||||
|
teachFileList.value.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
teacherFeedContentList.value.push(teachWorkFileList)
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogProps.value.studentObj.datacontent = dialogProps.value.studentObj.datacontent
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Invalid JSON:', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
params.studentQuizAllList.forEach((item) => {
|
||||||
|
classWorkFormScore.teacherRating.push({
|
||||||
|
maxScore: item.score ? item.score : 100, //分值最大值 不能大于题目的分值 ?没有,那就最大100
|
||||||
|
score: item.teacherRating, // 教师批改分值: 默认批改为题目分值
|
||||||
|
id: item.id // 学生答题列表的id
|
||||||
|
})
|
||||||
|
classWorkFormScore.teacherremark = item.teacherremark // 评价语
|
||||||
|
|
||||||
|
if (item.feedcontent != '') {
|
||||||
|
const filelist = JSON.parse(item.feedcontent)
|
||||||
|
console.log(filelist, '学生filelist-------------')
|
||||||
|
// 学生答题的内容 ? feedcontent应该只包含了一个数组?
|
||||||
|
filelist &&
|
||||||
|
filelist.forEach((item) => {
|
||||||
|
if (
|
||||||
|
item.name.indexOf('jpg') > -1 ||
|
||||||
|
item.name.indexOf('jpeg') > -1 ||
|
||||||
|
item.name.indexOf('png') > -1
|
||||||
|
) {
|
||||||
|
imageList.value.push(item)
|
||||||
|
} else {
|
||||||
|
fileList.value.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
feedContentList.value.push(filelist)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (
|
||||||
|
params.studentObj.worktype == '课堂展示' ||
|
||||||
|
params.studentObj.worktype == '框架梳理'
|
||||||
|
) {
|
||||||
|
params.studentQuizAllList.forEach((item) => {
|
||||||
|
classWorkFormScore.teacherRating.push({
|
||||||
|
maxScore: item.score ? item.score : 100, //分值最大值 不能大于题目的分值 ?没有,那就最大100
|
||||||
|
score: item.teacherRating, // 教师批改分值: 默认批改为题目分值
|
||||||
|
id: item.id // 学生答题列表的id
|
||||||
|
})
|
||||||
|
classWorkFormScore.teacherremark = item.teacherremark // 评价语
|
||||||
|
// 根据移动端返回定义:只返回一张图片:rightanswer:"https://wzyzoss.eos-chongqing-3.cmecloud.cn/2024/9/5/c5d8e00a93364dd3b975f669afa217f9.png"
|
||||||
|
// 这里只有一张图片;
|
||||||
|
console.log(item.rightanswer, '----------课堂展示学生答题------------------')
|
||||||
|
|
||||||
|
if (item.rightanswer != '' && item.rightanswer != null) {
|
||||||
|
if (
|
||||||
|
item.rightanswer.indexOf('jpg') > -1 ||
|
||||||
|
item.rightanswer.indexOf('jpeg') > -1 ||
|
||||||
|
item.rightanswer.indexOf('png') > -1
|
||||||
|
) {
|
||||||
|
const imgeobj = {
|
||||||
|
name: item.rightanswer,
|
||||||
|
url: item.rightanswer
|
||||||
|
}
|
||||||
|
// 放入图片list
|
||||||
|
imageList.value.push(imgeobj)
|
||||||
|
// 没其他附件类型
|
||||||
|
//fileList.value.push(?);
|
||||||
|
feedContentList.value.push(imgeobj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 其他类型待联调
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 老师批过优良,则默认批改的优良,不然就是默认的0
|
||||||
|
console.log(params.studentQuizAllList[0].rating, '----------------------------')
|
||||||
|
// 为null 或0 则默认为0
|
||||||
|
classWorkFormScore.rating =
|
||||||
|
params.studentQuizAllList[0].rating == 0 ? 0 : params.studentQuizAllList[0].rating
|
||||||
|
}
|
||||||
|
|
||||||
|
analysisScoreOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交批改评分
|
||||||
|
const onClassWorkFormScoreSave = () => {
|
||||||
|
console.log(classWorkFormScore)
|
||||||
|
// rating评价 不为0 则批改过
|
||||||
|
if (dialogProps.value.studentQuizAllList && dialogProps.value.studentQuizAllList[0].rating != 0) {
|
||||||
|
ElMessageBox.confirm(`该学生已批改,再次批改会覆盖之前的评分!`, '温馨提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
draggable: true
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
onSubmit()
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
} else {
|
||||||
|
onSubmit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onSubmit = () => {
|
||||||
|
if (classWorkFormScore.rating == 0) {
|
||||||
|
ElMessage({
|
||||||
|
type: 'error',
|
||||||
|
message: '请您给学生一个评价吧!'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
classWorkFormScore.teacherRating &&
|
||||||
|
classWorkFormScore.teacherRating.map((item, index) => {
|
||||||
|
const queryParams = {
|
||||||
|
id: item.id,
|
||||||
|
teacherRating: item.score, // 教师评分
|
||||||
|
rating: classWorkFormScore.rating, // 评价
|
||||||
|
teacherremark: classWorkFormScore.teacherremark, //评分说明
|
||||||
|
timestamp: getTimeDate() // 时间
|
||||||
|
}
|
||||||
|
console.log(queryParams)
|
||||||
|
updateClassworkeval(queryParams).then((res) => {
|
||||||
|
// if(res.code == 200){
|
||||||
|
// 循环提交能干个啥
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: '提交成功!'
|
||||||
|
})
|
||||||
|
analysisScoreOpen.value = false
|
||||||
|
// 清空答题清空右侧 题目列表
|
||||||
|
emits('class_work_score_submit')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化请求
|
||||||
|
// onMounted(() => {})
|
||||||
|
|
||||||
|
// 暴露给父组件的参数和方法(外部需要什么,都可以从这里暴露出去)
|
||||||
|
defineExpose({
|
||||||
|
acceptParams
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.teacher_content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.teacher_content_con {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.tacher_conten_foot {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image_list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
flex-direction: column;
|
||||||
|
/* justify-content: space-evenly; */
|
||||||
|
}
|
||||||
|
/* .el-dialog__body{
|
||||||
|
padding: 0!important;
|
||||||
|
height: 100%;
|
||||||
|
} */
|
||||||
|
.file-read-dialog {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
/* margin-bottom: 20px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-circle {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: pink;
|
||||||
|
color: red;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-circle.active {
|
||||||
|
background-color: red;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,616 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="classWorkAnalysis.open"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
class="clwk_dialog"
|
||||||
|
style="width: 90%; height: 85%"
|
||||||
|
:show-close="false"
|
||||||
|
top="8vh"
|
||||||
|
append-to-body
|
||||||
|
destory-on-close
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<div style="font-size: 18px; display: flex; flex-wrap: nowrap">
|
||||||
|
<div style="flex: 1">
|
||||||
|
{{ classWorkAnalysis.title }}答题情况
|
||||||
|
<el-tag :type="classWorkAnalysis.workclass" size="large" style="height: 25px">{{
|
||||||
|
classWorkAnalysis.worktype
|
||||||
|
}}</el-tag>
|
||||||
|
</div>
|
||||||
|
<!-- classWorkAnalysis.entpcourseworklistarray 当前学习任务所包含的试题ID -->
|
||||||
|
<el-row
|
||||||
|
v-if="classWorkAnalysis.entpcourseworklistarray.length > 0"
|
||||||
|
style="margin: 0 auto; flex: 1"
|
||||||
|
>
|
||||||
|
<el-button-group style="margin-bottom: 10px">
|
||||||
|
<el-button
|
||||||
|
:type="classWorkAnalysis.view == 'studentview' ? 'success' : ''"
|
||||||
|
@click="classWorkAnalysis.view = 'studentview'"
|
||||||
|
>作业批阅</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||||
|
:type="classWorkAnalysis.view == 'quizStats' ? 'success' : ''"
|
||||||
|
@click="workHandle('quizStats')"
|
||||||
|
>作业概况</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||||
|
:type="classWorkAnalysis.view == 'report' ? 'success' : ''"
|
||||||
|
@click="handleClassOverviewOpen('report')"
|
||||||
|
>作业报告</el-button
|
||||||
|
>
|
||||||
|
</el-button-group>
|
||||||
|
</el-row>
|
||||||
|
<div style="flex: 1">
|
||||||
|
<div
|
||||||
|
style="float: right; padding: 0 10px; cursor: pointer"
|
||||||
|
icon="el-icon-close"
|
||||||
|
@click="classWorkAnalysis.open = false"
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 如果当前学习没有试题 -->
|
||||||
|
<div
|
||||||
|
v-if="classWorkAnalysis.view == 'studentview'"
|
||||||
|
style="width: 100%"
|
||||||
|
class="clwk_dialog_view"
|
||||||
|
:height="mainHeight"
|
||||||
|
>
|
||||||
|
<div class="view_table">
|
||||||
|
<el-radio-group
|
||||||
|
v-model="tableRadio.value"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
@change="tableRadioChange"
|
||||||
|
>
|
||||||
|
<el-radio-button :value="1" :label="'已交' + '(' + tableRadio.num1 + ')'" />
|
||||||
|
<el-radio-button :value="0" :label="'未交' + '(' + tableRadio.num0 + ')'" />
|
||||||
|
</el-radio-group>
|
||||||
|
<!-- 学生列表:classWorkAnalysis.classworkdata; 已交未交:tableRadio.list -->
|
||||||
|
<el-table
|
||||||
|
v-loading="loading_dt_table"
|
||||||
|
:data="tableRadio.list"
|
||||||
|
row-key="id"
|
||||||
|
highlight-current-row
|
||||||
|
@row-click="getStudentClassWorkDataDetail"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" label="序号" width="52" reserve-selection align="center" />
|
||||||
|
<el-table-column label="姓名" prop="studentname" width="100" align="center" />
|
||||||
|
<el-table-column label="提交时间" prop="updatedate" width="170" align="center" />
|
||||||
|
<el-table-column label="批阅状态" prop="teacherRating" align="center" width="120" sortable>
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="scope.row.teacherRating == 0"
|
||||||
|
><span style="color: #2196f3">待批阅</span></template
|
||||||
|
>
|
||||||
|
<!-- 1-优 2-优减 3-良 4-良减 5-差 -->
|
||||||
|
<template v-if="scope.row.teacherRating == 1"
|
||||||
|
><el-tag type="danger">优</el-tag></template
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.teacherRating == 2"
|
||||||
|
><el-tag type="danger">优-</el-tag></template
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.teacherRating == 3"
|
||||||
|
><el-tag type="warning">良</el-tag></template
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.teacherRating == 4"
|
||||||
|
><el-tag type="info">良-</el-tag></template
|
||||||
|
>
|
||||||
|
<template v-if="scope.row.teacherRating == 5"
|
||||||
|
><el-tag type="info">差</el-tag></template
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="view_teachrting">
|
||||||
|
<div class="classwork-score">
|
||||||
|
<div v-if="classWorkAnalysis.activeStudentQuizlist.length == 0">
|
||||||
|
<el-empty
|
||||||
|
description="点击左侧表格学生信息可查看批阅详情"
|
||||||
|
style="width: 100%; height: 500px"
|
||||||
|
></el-empty>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div v-if="isopen_dtwk_table">
|
||||||
|
<div v-show="classWorkAnalysis.activeStudentQuizlist.length > 0">
|
||||||
|
<item-dialog-score
|
||||||
|
ref="classWorkAnalysisScoreDialogRef"
|
||||||
|
@class_work_score_submit="onClassWorkScoreSubmit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<el-empty
|
||||||
|
description="点击左侧表格学生信息可查看批阅详情"
|
||||||
|
style="width: 100%; height: 500px"
|
||||||
|
></el-empty>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 作业概况 -->
|
||||||
|
<div v-else-if="classWorkAnalysis.view == 'quizStats'">
|
||||||
|
<!-- <quiz-stats :active-data="classWorkActiveData" /> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 作业报告-->
|
||||||
|
<div v-else-if="classWorkAnalysis.view == 'report'" style="overflow-y: scroll">
|
||||||
|
<!-- <ClassOverview :table-list="overviewData" :eval-id="courseObj.evalid"></ClassOverview> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="classWorkAnalysis.open=false">关 闭</el-button>
|
||||||
|
</div>
|
||||||
|
</template> -->
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { ref, defineExpose, onMounted, reactive, computed, watch, nextTick, getCurrentInstance } from 'vue'
|
||||||
|
import { addSmartClassReserv, updateSmartClassReserv, listClassmain } from '@/api/classManage'
|
||||||
|
import { listClassworkdata, listEntpcoursework, listClassworkeval } from '@/api/classTask'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { getCurrentTime, getAfterMinutes } from '@/utils/date'
|
||||||
|
import { processList } from '@/hooks/useProcessList'
|
||||||
|
import ItemDialogScore from '@/views/classTask/container/item-dialog-score.vue'
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emit = defineEmits(['addSuccess'])
|
||||||
|
const props = defineProps({
|
||||||
|
bookId: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const mainHeight = ref(document.documentElement.clientHeight - 110)
|
||||||
|
const classWorkAnalysis = reactive({
|
||||||
|
open: false
|
||||||
|
})
|
||||||
|
const tableRadio = reactive({
|
||||||
|
value: '1', // 已交
|
||||||
|
list: [], // 已交list
|
||||||
|
num1: 0, // 已交人数
|
||||||
|
num0: 0 // 未交人数
|
||||||
|
}) // 批阅 是否已交
|
||||||
|
const loading_dt_table = ref(false)
|
||||||
|
const isopen_dtwk_table = ref(false)
|
||||||
|
|
||||||
|
// zdg: 作业概况
|
||||||
|
const classWorkActiveData = reactive({
|
||||||
|
quizlist: [], // 当前习题列表
|
||||||
|
studentList: [], // 当前课程-所有学生
|
||||||
|
workFeedList: [], // 当前课程-所有学生反馈数据
|
||||||
|
timerId: 0 // 定时器id
|
||||||
|
})
|
||||||
|
//所选学生题目- 答题题目分析与评价
|
||||||
|
const classWorkAnalysisScore = reactive({
|
||||||
|
studentObj: {}, // 当前学生的作业题型等信息
|
||||||
|
studentQuizAllList: [], // 选择学生的回答list
|
||||||
|
quizlist: [] // 选择学生的题目list
|
||||||
|
})
|
||||||
|
|
||||||
|
// watch(
|
||||||
|
// // () => props.currentNode,
|
||||||
|
// (newValue, oldValue) => {
|
||||||
|
// form.name = newValue.label
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
const openDialog = (data) => {
|
||||||
|
console.log(data, '点击的item答题情况')
|
||||||
|
|
||||||
|
classWorkAnalysis.title = data.uniquekey ? data.uniquekey + '--' : ''
|
||||||
|
classWorkAnalysis.worktype = data.worktype
|
||||||
|
classWorkAnalysis.workclass = data.workclass
|
||||||
|
// 重置学生列表
|
||||||
|
tableRadio.list = []
|
||||||
|
tableRadio.value = '1'
|
||||||
|
tableRadio.num0 = 0
|
||||||
|
tableRadio.num1 = 0
|
||||||
|
|
||||||
|
classWorkAnalysis.open = true
|
||||||
|
// 默认显示是学生作业反馈
|
||||||
|
classWorkAnalysis.view = 'studentview'
|
||||||
|
// 当前学习任务所包含的试题ID
|
||||||
|
classWorkAnalysis.entpcourseworklistarray = data.entpcourseworklistarray
|
||||||
|
// 默认选中的学生
|
||||||
|
classWorkAnalysis.activeStudentQuizlist = []
|
||||||
|
// 默认选中的试题
|
||||||
|
classWorkAnalysis.activeQuizAnalysisData = []
|
||||||
|
|
||||||
|
classWorkAnalysis.row = data
|
||||||
|
window.test = this
|
||||||
|
// zdg: 学生列表
|
||||||
|
const studentArr = data.classworkdatastudentids
|
||||||
|
? JSON.parse(`[${data.classworkdatastudentids}]`)
|
||||||
|
: []
|
||||||
|
classWorkActiveData.studentList = studentArr
|
||||||
|
/** 学生完成情况分析--获取作业学生list数据 */
|
||||||
|
getClassWorkStudentList(data.id)
|
||||||
|
|
||||||
|
// 课程列表idlist
|
||||||
|
var ids = []
|
||||||
|
for (var i = 0; i < data.entpcourseworklistarray.length; i++) {
|
||||||
|
ids.push(data.entpcourseworklistarray[i].id)
|
||||||
|
}
|
||||||
|
// 课程作业列表
|
||||||
|
listEntpcoursework({ ids: ids.join(','), pageSize: 500 }).then((idres) => {
|
||||||
|
for (var i = 0; i < idres.rows.length; i++) {
|
||||||
|
// //新增了 复合题、主观题(背景+小题目) 题目标题优化一下 .replace(/!@#\$%/g,'')
|
||||||
|
idres.rows[i].titletext = idres.rows[i].title.replace(/!@#\$%/g, '')
|
||||||
|
}
|
||||||
|
classWorkAnalysis.quizlist = idres.rows
|
||||||
|
classWorkActiveData.quizlist = idres.rows // zdg: 作业概览组件使用
|
||||||
|
|
||||||
|
// 统计每个题目的正误率
|
||||||
|
// 这个学习任务所有题目+所有学生的答题数据 , pageSize: 100
|
||||||
|
listClassworkeval({ workid: data.id, pageSize: 1000 }).then((wevalres) => {
|
||||||
|
for (var i = 0; i < classWorkAnalysis.quizlist.length; i++) {
|
||||||
|
// 分析每一道题目
|
||||||
|
var scoingCount = 0
|
||||||
|
var feedcount = 0
|
||||||
|
// 全部人数
|
||||||
|
var evalCount = 0
|
||||||
|
for (var w = 0; w < wevalres.rows.length; w++) {
|
||||||
|
if (wevalres.rows[w].entpcourseworkid == classWorkAnalysis.quizlist[i].id) {
|
||||||
|
evalCount++
|
||||||
|
|
||||||
|
// 只统计有回答的题目
|
||||||
|
if (wevalres.rows[w].feedcontent != '') {
|
||||||
|
// 已经作答的人数
|
||||||
|
feedcount++
|
||||||
|
// 简单判断正误
|
||||||
|
if (wevalres.rows[w].feedcontent == wevalres.rows[w].rightanswer) {
|
||||||
|
wevalres.rows[w].scoingStatus = true
|
||||||
|
scoingCount++
|
||||||
|
// 学生回答与参考答案一样,则:得分=分值
|
||||||
|
wevalres.rows[w].teacherRating = wevalres.rows[w].score
|
||||||
|
} else {
|
||||||
|
wevalres.rows[w].scoingStatus = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classWorkAnalysis.quizlist[i].evalCount = evalCount
|
||||||
|
// 作答人数
|
||||||
|
classWorkAnalysis.quizlist[i].feedcount = feedcount
|
||||||
|
// 得分率 这里优化一下(没回答会是NaN%) scoingRate
|
||||||
|
if (scoingCount == 0 && feedcount == 0) {
|
||||||
|
classWorkAnalysis.quizlist[i].scoingRate = '0%'
|
||||||
|
} else {
|
||||||
|
classWorkAnalysis.quizlist[i].scoingRate =
|
||||||
|
((scoingCount / feedcount) * 100).toFixed(0) + '%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// zdg: 所有反馈数据
|
||||||
|
const getStudentid = (workdataid) => {
|
||||||
|
// 获取学生id
|
||||||
|
const classworkdata = (classWorkAnalysis.classworkdata || []).find(
|
||||||
|
(o) => o.id === workdataid
|
||||||
|
)
|
||||||
|
return classworkdata ? classworkdata.studentid : ''
|
||||||
|
}
|
||||||
|
wevalres.rows.forEach((o) => {
|
||||||
|
o.studentid = getStudentid(o.workdataid)
|
||||||
|
})
|
||||||
|
classWorkActiveData.workFeedList = wevalres.rows
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(classWorkAnalysis, '点击进度后获得的数据')
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 学生完成情况分析
|
||||||
|
/** 1、获取作业学生列表 */
|
||||||
|
const getClassWorkStudentList = (rowId) => {
|
||||||
|
// 本地保存这个rowid,老师批改后续中使用
|
||||||
|
localStorage.setItem('activeClassWorkRowId', rowId)
|
||||||
|
// 先清空表格中的数据
|
||||||
|
classWorkAnalysis.classworkdata = []
|
||||||
|
// 加载中_
|
||||||
|
loading_dt_table.value = true
|
||||||
|
// 找当前学习任务的classworkdata数据
|
||||||
|
listClassworkdata({ classworkid: rowId, pageSize: 100 })
|
||||||
|
.then((response) => {
|
||||||
|
for (var i = 0; i < response.rows.length; i++) {
|
||||||
|
if (response.rows[i].entpcourseworklist != '') {
|
||||||
|
response.rows[i].entpcourseworkarray = JSON.parse(
|
||||||
|
'[' + response.rows[i].entpcourseworklist + ']'
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
response.rows[i].entpcourseworkarray = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 老师批阅状态 默认0 未批改
|
||||||
|
response.rows[i].teacherRating = 0
|
||||||
|
|
||||||
|
// 计算每个学生的得分率
|
||||||
|
if (
|
||||||
|
response.rows[i].classworkevallist != '' &&
|
||||||
|
response.rows[i].classworkevallist != null &&
|
||||||
|
response.rows[i].classworkevallist != 'null'
|
||||||
|
) {
|
||||||
|
// 将标签中双引号改为转义, 测试数据: "{\"id\":172910, \"feedcontent\":\"毛泽东,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\", \"score\":4, \"rightanswer\":\"毛泽东重,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\"},{\"id\":172911, \"rating\":0, \"teacherRating\":0, \"entpcourseworkid\":363100, \"feedcontent\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\", \"score\":4, \"rightanswer\":\"毛泽东重游橘子洲,面对如画的秋色和大好的革命形势,回忆过去战斗的岁月,不禁心潮起伏,<bdo class=\"mathjye-underpoint2\">浮想联翩</bdo>。\"}"
|
||||||
|
// 常规作业(去除【】前后引号).replace(/"(\[.*\])"/g, '$1'); :eg: "feedcontent\":\"[{\"name\":\"Bliss.jpg\",\"url\":\"https://wzyzoss.3b8daa474.jpg\"}]\",
|
||||||
|
// json转换会报错; .replace(/""/g, '"') eg: ""宇宙环境安全""
|
||||||
|
response.rows[i].classworkevallist = escapeHtmlQuotes(response.rows[i].classworkevallist)
|
||||||
|
console.log('学生完成情况分析classworkevallist', response.rows[i].classworkevallist)
|
||||||
|
const evalarray = JSON.parse('[' + response.rows[i].classworkevallist + ']')
|
||||||
|
var scoingCount = 0
|
||||||
|
var feedcount = 0
|
||||||
|
for (var e = 0; e < evalarray.length; e++) {
|
||||||
|
if (evalarray[e].feedcontent != '') {
|
||||||
|
feedcount++
|
||||||
|
// 与答案对比正误。注意注意,这里仅限单选题
|
||||||
|
if (evalarray[e].feedcontent == evalarray[e].rightanswer) {
|
||||||
|
scoingCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(evalarray, 'evalarray------------------------------------')
|
||||||
|
if (feedcount > 0) {
|
||||||
|
// 多个题目的总得分率: 正确题数/(题目数*100)
|
||||||
|
response.rows[i].scoingRate = ((scoingCount / feedcount) * 100).toFixed(0) + '%'
|
||||||
|
} else {
|
||||||
|
response.rows[i].scoingRate = '0%'
|
||||||
|
}
|
||||||
|
// 批阅状态 优良类 :注意:这里题目中的评价都是一样的,所以取第一个
|
||||||
|
if (evalarray[0].rating != '') {
|
||||||
|
response.rows[i].teacherRating = evalarray[0].rating
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.rows[i].scoingRate = '0%'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classWorkAnalysis.classworkdata = response.rows
|
||||||
|
loading_dt_table.value = false
|
||||||
|
|
||||||
|
// 默认获取已交的学生列表
|
||||||
|
tableRadio.list =
|
||||||
|
classWorkAnalysis.classworkdata &&
|
||||||
|
classWorkAnalysis.classworkdata.filter((item) => item.resultcount > 0)
|
||||||
|
tableRadio.value = '1'
|
||||||
|
tableRadio.num0 = classWorkAnalysis.classworkdata.length - tableRadio.list.length
|
||||||
|
tableRadio.num1 = tableRadio.list.length
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading_dt_table.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** 2、查看某一个学生的学习任务完成详情*/
|
||||||
|
const getStudentClassWorkDataDetail = (row) => {
|
||||||
|
// 这里取出的是学生完成情况
|
||||||
|
// 具体的题目数据在this.classWorkAnalysis.quizlist里
|
||||||
|
console.log(row, '点击了左侧学生')
|
||||||
|
//更新到待批改的学生信息中
|
||||||
|
classWorkAnalysisScore.studentObj = row
|
||||||
|
listClassworkeval({ workdataid: row.id, pageSize: 100 })
|
||||||
|
.then((wevalres) => {
|
||||||
|
for (var i = 0; i < classWorkAnalysis.quizlist.length; i++) {
|
||||||
|
// 分析每一道题目
|
||||||
|
for (var w = 0; w < wevalres.rows.length; w++) {
|
||||||
|
if (wevalres.rows[w].entpcourseworkid == classWorkAnalysis.quizlist[i].id) {
|
||||||
|
wevalres.rows[w].quiztitle = classWorkAnalysis.quizlist[i].title
|
||||||
|
wevalres.rows[w].quiztitletext = classWorkAnalysis.quizlist[i].title.replace(
|
||||||
|
/<[^>]*>/g,
|
||||||
|
''
|
||||||
|
)
|
||||||
|
wevalres.rows[w].score = wevalres.rows[w].score ? wevalres.rows[w].score : 0
|
||||||
|
|
||||||
|
// 参考答案 去除下html标签
|
||||||
|
wevalres.rows[w].rightanswer =
|
||||||
|
wevalres.rows[w].rightanswer != '' && wevalres.rows[w].rightanswer != null
|
||||||
|
? wevalres.rows[w].rightanswer.replace(/<[^>]+>/g, '')
|
||||||
|
: wevalres.rows[w].rightanswer
|
||||||
|
// 学生回答 去除下html标签
|
||||||
|
wevalres.rows[w].feedcontent =
|
||||||
|
wevalres.rows[w].feedcontent != '' && wevalres.rows[w].feedcontent != null
|
||||||
|
? wevalres.rows[w].feedcontent.replace(/<[^>]+>/g, '')
|
||||||
|
: wevalres.rows[w].feedcontent
|
||||||
|
|
||||||
|
if (classWorkAnalysis.row.worktype == '常规作业') {
|
||||||
|
wevalres.rows[w].feedcontent = JSON.parse(wevalres.rows[w].feedcontent)
|
||||||
|
}
|
||||||
|
if (wevalres.rows[w].feedcontent != '') {
|
||||||
|
if (wevalres.rows[w].feedcontent == wevalres.rows[w].rightanswer) {
|
||||||
|
wevalres.rows[w].scoingStatus = true
|
||||||
|
// 学生回答与参考答案一样,则:得分=分值
|
||||||
|
wevalres.rows[w].teacherRating = wevalres.rows[w].score
|
||||||
|
} else {
|
||||||
|
wevalres.rows[w].scoingStatus = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wevalres.rows[w].scoingStatus = ''
|
||||||
|
}
|
||||||
|
// 计算得分
|
||||||
|
}
|
||||||
|
// "回答" prop="feedcontent" width="200" align="center"></el-table-column>
|
||||||
|
// <el-table-column label="参考答案" prop="rightanswer"
|
||||||
|
//新增了 复合题、主观题(背景+小题目) 题目标题优化一下
|
||||||
|
wevalres.rows[w].worktitle = wevalres.rows[w].worktitle.replace(/!@#\$%/g, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classWorkAnalysis.activeStudentQuizlist = wevalres.rows
|
||||||
|
// 加载右边表格
|
||||||
|
isopen_dtwk_table.value = true
|
||||||
|
// 加载右边评语区域
|
||||||
|
if (wevalres.rows.length > 0) {
|
||||||
|
handleClassWorkAnalysissScoreOpen(row)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'warning',
|
||||||
|
message: '未获取到答题信息,请稍后再看,或者联系管理员查看情况!'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log('获取答题情况失败')
|
||||||
|
ElMessage({
|
||||||
|
type: 'warning',
|
||||||
|
message: '未获取到答题信息!'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** 3、教师批改后返回的方法*/
|
||||||
|
const onClassWorkScoreSubmit = () => {
|
||||||
|
console.log('批改后返回的方法')
|
||||||
|
loading_dt_table.value = true
|
||||||
|
isopen_dtwk_table.value = false
|
||||||
|
// 1、清空答题情况的两个table数据,- 左侧学生列表:classWorkAnalysis.classworkdata;- 右侧学生回答题目列表:classWorkAnalysis.activeStudentQuizlist
|
||||||
|
// - 左侧学生列表
|
||||||
|
classWorkAnalysis.classworkdata = []
|
||||||
|
classWorkAnalysis.activeStudentQuizlist = []
|
||||||
|
// 2、刷新左侧学生列表数据,更新批改状态
|
||||||
|
const rowid = localStorage.getItem('activeClassWorkRowId')
|
||||||
|
getClassWorkStudentList(rowid)
|
||||||
|
}
|
||||||
|
// 查看并批改一个学生的题目作答(答题题目分析与评价)
|
||||||
|
const handleClassWorkAnalysissScoreOpen = (row) => {
|
||||||
|
console.log(row, '所选点击的信息')
|
||||||
|
|
||||||
|
// 当前学生的回答list
|
||||||
|
classWorkAnalysisScore.studentQuizAllList = classWorkAnalysis.activeStudentQuizlist
|
||||||
|
// 当前学生的所有题目list
|
||||||
|
classWorkAnalysisScore.quizlist = classWorkAnalysis.quizlist
|
||||||
|
// 格式化试题格式信息
|
||||||
|
processList(classWorkAnalysisScore.quizlist)
|
||||||
|
// 屏幕高度
|
||||||
|
classWorkAnalysisScore.maxheight = mainHeight.value - 100
|
||||||
|
|
||||||
|
// 防止组件未渲染完成 调用里面方法报错
|
||||||
|
nextTick(() => {
|
||||||
|
proxy.$refs.classWorkAnalysisScoreDialogRef.acceptParams(classWorkAnalysisScore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
// 将标签中的双引号增加转义
|
||||||
|
const escapeHtmlQuotes = (str) => {
|
||||||
|
// 后端已replace双引号, 故前端不用在处理
|
||||||
|
return str
|
||||||
|
|
||||||
|
// 只对双引号进行转义
|
||||||
|
// return str.replace(/(<[^>]+>)/g, function (match) {
|
||||||
|
// return match.replace(/"/g, '\\"')
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
openDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// :deep(.reserv-date-pick) {
|
||||||
|
// width: 140px;
|
||||||
|
// }
|
||||||
|
// :deep(.reserv-time-pick) {
|
||||||
|
// width: 240px;
|
||||||
|
// }
|
||||||
|
.clwk_dialog {
|
||||||
|
.clwk_dialog_view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
// align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.view_table {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.view_teachrting {
|
||||||
|
flex: 2;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.clwk_dialog {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog {
|
||||||
|
margin: 0 auto !important;
|
||||||
|
height: 85%!important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__header {
|
||||||
|
/* position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0; */
|
||||||
|
width: 100%!important;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__body {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 15px;
|
||||||
|
bottom: 1px;
|
||||||
|
right:0;
|
||||||
|
padding:5px;
|
||||||
|
z-index:1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
/* overflow:hidden;
|
||||||
|
overflow-y: auto; */
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__footer{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.clwk_dialog .classwork-score{
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.clwk_dialog {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog {
|
||||||
|
margin: 0 auto !important;
|
||||||
|
height: 85%!important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__header {
|
||||||
|
/* position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0; */
|
||||||
|
width: 100%!important;
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__body {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 15px;
|
||||||
|
bottom: 1px;
|
||||||
|
right:0;
|
||||||
|
padding:5px;
|
||||||
|
z-index:1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
/* overflow:hidden;
|
||||||
|
overflow-y: auto; */
|
||||||
|
}
|
||||||
|
.clwk_dialog .el-dialog__footer{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.clwk_dialog .classwork-score{
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,143 @@
|
||||||
|
<template>
|
||||||
|
<div class="class-reserv-item">
|
||||||
|
<div class="class-reserv-item-body">
|
||||||
|
<div class="class-reserv-item-title1">
|
||||||
|
<el-tag style="margin-left: 5px" :type="item.workclass"> {{ item.worktype }}</el-tag>
|
||||||
|
<label style="margin-left: 10px">{{ item.uniquekey }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="class-reserv-item-title3">
|
||||||
|
<!-- <span v-for="(tag, index) in item.classItemList" :key="index" style="margin-left: 5px">
|
||||||
|
{{ index === 0 ? tag.name : '、' + tag.name }}
|
||||||
|
</span> -->
|
||||||
|
<span>{{ item.classcaption }}</span>
|
||||||
|
| 截止时间:{{ item.deaddate }} | {{ tabactive }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-switch v-model="value1" active-text="云同步"> </el-switch>
|
||||||
|
<div class="class-reserv-item-tool">
|
||||||
|
<span><span style="color: #000fff; font-weight: 900; font-size: 15px">{{ item.workdataresultcount }}</span>/{{ item.workdatacount }}</span>
|
||||||
|
<span>已交</span>
|
||||||
|
</div>
|
||||||
|
<div class="class-reserv-item-tool">
|
||||||
|
<span style="color: #ff7f00; font-weight: 900; font-size: 15px">2</span>
|
||||||
|
<span>待批阅</span>
|
||||||
|
</div>
|
||||||
|
<div class="class-reserv-item-tool">
|
||||||
|
<span><span style="color: #007fff; font-weight: 900; font-size: 15px">{{ item.averagetime?item.averagetime:0 }}</span>分钟 </span>
|
||||||
|
<span>平均用时</span>
|
||||||
|
</div>
|
||||||
|
<div class="class-reserv-item-tool">
|
||||||
|
<span style="color: #ff6ec7; font-weight: 900; font-size: 15px">{{ item.scoingRate }}</span>
|
||||||
|
<span>得分率</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { useToolState } from '@/store/modules/tool'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { createWindow } from '@/utils/tool'
|
||||||
|
import { deleteSmartReserv, startClass, endClass } from '@/api/classManage'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { listEntpcourse } from '@/api/teaching/classwork'
|
||||||
|
const emit = defineEmits(['openEdit', 'deleteReserv'])
|
||||||
|
const props = defineProps({
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
tabactive: {
|
||||||
|
type: String,
|
||||||
|
default: () => ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
const value1 = ref(true);
|
||||||
|
const basePath = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
||||||
|
const toolStore = useToolState() // 获取状态管理-tool
|
||||||
|
const openEdit = () => {
|
||||||
|
emit('openEdit', props.item)
|
||||||
|
}
|
||||||
|
const deleteReserv = () => {
|
||||||
|
deleteSmartReserv([props.item.id]).then((res) => {
|
||||||
|
if (res.data === true) {
|
||||||
|
ElMessage({
|
||||||
|
message: '删除成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
emit('deleteReserv', props.item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const startClassR = (item) => {
|
||||||
|
// startClass(item.id).then((res) => {
|
||||||
|
// if (res.data === true) {
|
||||||
|
// item.status = '上课中'
|
||||||
|
// openLesson()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
item.status = '上课中'
|
||||||
|
openLesson()
|
||||||
|
}
|
||||||
|
// const toolStore = useToolState()
|
||||||
|
let wins = null;
|
||||||
|
// 上课-工具类悬浮
|
||||||
|
const openLesson = () => {
|
||||||
|
// startClass(props.item.id)
|
||||||
|
listEntpcourse({
|
||||||
|
evalid: props.item.ex2,
|
||||||
|
edituserid: useUserStore().user.userId,
|
||||||
|
pageSize: 500
|
||||||
|
}).then(async res=>{
|
||||||
|
if (res.rows[0].id) {
|
||||||
|
wins = await createWindow('tool-sphere', { url: '/tool/sphere?entpcourseid=' + res.rows[0].id + "&reservId=" + props.item.id })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const endClassR = (item) => {
|
||||||
|
endClass(item.id).then((res) => {
|
||||||
|
if (res.data === true) {
|
||||||
|
ElMessage({
|
||||||
|
message: '下课成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
item.status = '已结束'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.class-reserv-item {
|
||||||
|
display: flex;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.class-reserv-item-body {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
.class-reserv-item-title1 {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
label {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.class-reserv-item-tool {
|
||||||
|
margin-left: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue