Merge branch 'main' into qinqing_dev
This commit is contained in:
commit
f72b2f8341
|
@ -15,3 +15,5 @@ VITE_APP_UPLOAD_API = 'https://file.ysaix.com:7868/prod-api'
|
|||
VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktxt/'
|
||||
|
||||
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
||||
|
||||
VITE_SHOW_DEV_TOOLS = 'true'
|
||||
|
|
|
@ -17,3 +17,5 @@ VITE_BUILD_COMPRESS = gzip
|
|||
VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/'
|
||||
|
||||
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
||||
|
||||
VITE_SHOW_DEV_TOOLS = 'true'
|
||||
|
|
|
@ -73,8 +73,7 @@ function createLoginWindow() {
|
|||
loginWindow.loadFile(join(__dirname, '../renderer/index.html'), { hash: 'login' })
|
||||
updateInit(loginWindow)
|
||||
}
|
||||
|
||||
loginWindow.webContents.openDevTools()
|
||||
if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') loginWindow.webContents.openDevTools()
|
||||
loginWindow.once('ready-to-show', () => {
|
||||
loginWindow.show()
|
||||
})
|
||||
|
@ -96,7 +95,6 @@ function createMainWindow() {
|
|||
frame: false, // 无边框
|
||||
autoHideMenuBar: true,
|
||||
maximizable: false,
|
||||
fullscreen: true,
|
||||
icon: join(__dirname, '../../resources/logo2.ico'),
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
|
@ -129,7 +127,7 @@ function createMainWindow() {
|
|||
shell.openExternal(details.url)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
mainWindow.webContents.openDevTools()
|
||||
if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') mainWindow.webContents.openDevTools()
|
||||
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||||
|
@ -139,6 +137,7 @@ function createMainWindow() {
|
|||
|
||||
// mainWindow.setAlwaysOnTop(true, "screen-saver") // 将窗口设置为顶层窗口
|
||||
// mainWindow.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见
|
||||
mainWindow.maximize();
|
||||
// 第三步: 开启remote服务
|
||||
remote.enable(mainWindow.webContents)
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ export const editListItem = (row, courseObj) => {
|
|||
chooseWorkLists: [],// 设计中的框架梳理list
|
||||
fileHomeworkList: [],// 设计中的常规作业list
|
||||
whiteboardObj: '',// 设计中的课堂展示对象
|
||||
question: '', // 设计中的[课堂展示]的问题
|
||||
};
|
||||
console.log('编辑的行', row);
|
||||
|
||||
|
@ -99,7 +100,7 @@ export const editListItem = (row, courseObj) => {
|
|||
console.log('row.课堂展示', row.workcodes);
|
||||
const workcodes = JSON.parse(row.workcodes);
|
||||
classtaskObj.whiteboardObj = JSON.stringify(workcodes.json);
|
||||
//
|
||||
classtaskObj.question = row.worktag;
|
||||
// console.log('课堂展示', classtaskObj);
|
||||
return resolve(classtaskObj);
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ export const createWindow = async (type, data) => {
|
|||
wins_tool.setIgnoreMouseEvents(true, {forward: true}) // 忽略鼠标事件但是事件继续传递给窗口
|
||||
wins_tool.setAlwaysOnTop(true,'screen-saver') // 将窗口设置为顶层窗口
|
||||
wins_tool.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见
|
||||
wins_tool.webContents.openDevTools() // 打开调试工具
|
||||
if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') wins_tool.webContents.openDevTools() // 打开调试工具
|
||||
eventHandles(type, wins_tool) // 事件监听处理
|
||||
return wins_tool
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ export const createWindow = async (type, data) => {
|
|||
win.type = type // 唯一标识
|
||||
win.show()
|
||||
win.setFullScreen(true) // 设置窗口为全屏
|
||||
win.webContents.openDevTools() // 打开调试工具
|
||||
if (import.meta.env.VITE_SHOW_DEV_TOOLS === 'true') win.webContents.openDevTools() // 打开调试工具
|
||||
eventHandles(type, win) // 事件监听处理
|
||||
winPdf=win
|
||||
break
|
||||
|
|
|
@ -880,18 +880,20 @@ watch(() => courseObj.node, (newVal,oldVal) => {
|
|||
|
||||
</script>
|
||||
|
||||
<!--
|
||||
<style>
|
||||
.el-table .hidden-row {
|
||||
display: none !important;
|
||||
/* color: #ccc !important; */
|
||||
}
|
||||
.el-table .father-row {
|
||||
--el-table-tr-bg-color: #fff;
|
||||
--el-table-tr-bg-color: #fff;
|
||||
}
|
||||
.el-table .son-row {
|
||||
--el-table-tr-bg-color: #f0f0f08a;
|
||||
--el-table-tr-bg-color: #f0f0f08a;
|
||||
}
|
||||
</style>
|
||||
-->
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-classTaskAssign {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="common-layout" style="width: 100%; height: 73vh;">
|
||||
<div class="common-layout" style="width: 100%">
|
||||
<el-container>
|
||||
<el-container>
|
||||
<el-header style="height: auto">
|
||||
|
@ -7,7 +7,7 @@
|
|||
<el-card>
|
||||
<template #header>
|
||||
<div style="font-size: 20px;font-weight: bold">
|
||||
学情分布
|
||||
等级分布
|
||||
</div>
|
||||
</template>
|
||||
<Distribution></Distribution>
|
||||
|
@ -18,7 +18,7 @@
|
|||
<el-card>
|
||||
<template #header>
|
||||
<div style="font-size: 20px;font-weight: bold">
|
||||
时长分析
|
||||
用时分析
|
||||
</div>
|
||||
</template>
|
||||
<TimeAnalyse></TimeAnalyse>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<el-card>
|
||||
<template #header>
|
||||
<div style="font-size: 20px;font-weight: bold">
|
||||
知识点概览
|
||||
价值透析
|
||||
</div>
|
||||
</template>
|
||||
<Konwledge></Konwledge>
|
||||
|
@ -43,12 +43,12 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import Distribution from '@/views/classTask/container/classOverview/distribution.vue'
|
||||
import Konwledge from '@/views/classTask/container/classOverview/knowledge.vue'
|
||||
import TimeAnalyse from '@/views/classTask/container/classOverview/timeAnalyse.vue'
|
||||
import {ref,watchEffect,provide } from 'vue'
|
||||
import Distribution from './classOverview/distribution.vue'
|
||||
import Konwledge from './classOverview/knowledge.vue'
|
||||
import TimeAnalyse from './classOverview/timeAnalyse.vue'
|
||||
import {defineProps,watch} from 'vue'
|
||||
import overviewStore from "@/store/modules/overview";
|
||||
// import {getBindlist} from "@/api/education/knowledgePoint";
|
||||
const useOverview = overviewStore()
|
||||
const props = defineProps({
|
||||
tableList: {
|
||||
|
@ -57,12 +57,185 @@ const props = defineProps({
|
|||
return []
|
||||
}
|
||||
},
|
||||
// evalId:{
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// }
|
||||
evalId:{
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
activeData: { // 数据
|
||||
type: Object,
|
||||
// required: true, // 必传
|
||||
default: () => ({
|
||||
quizlist: [], // 当前习题列表
|
||||
studentList: [], // 当前课程-所有学生
|
||||
workFeedList: [] // 当前课程-所有学生反馈数据
|
||||
})
|
||||
},
|
||||
})
|
||||
let studentList = ref([]) // 学生数据
|
||||
const stuHasAnswers = ref([]) // 已经答过题的学生不管对错
|
||||
|
||||
// 初始-数据处理
|
||||
const initData = () => {
|
||||
console.log('xxx', props)
|
||||
// window.test = activeCourse
|
||||
studentList.value = props.activeData.studentList || []
|
||||
const activeWorkFeedList = props.activeData.workFeedList || []
|
||||
const quizlist = props.activeData.quizlist || []
|
||||
// 习题特殊处理
|
||||
let data = quizlist.map(o => {
|
||||
// 解析题选项
|
||||
const workdesc = o.workdesc || ''
|
||||
let accSum = 0 // 该题总人数
|
||||
let activeIds = [] // 已做答学生
|
||||
let rightIds = [] // 正确学生
|
||||
let hasAnswers= [] // 答过题的学生
|
||||
let timeAnalyse = [] // 平均时长和编号
|
||||
const quizFeedList = activeWorkFeedList.filter(f => f.entpcourseworkid == o.id) // 做该题的列表
|
||||
let children = []
|
||||
const allStudents = [];
|
||||
if (o.worktype == '单选题') { // '单选题','多选题'
|
||||
const list = workdesc.includes('#&') ? workdesc.split('#&') : isJson(workdesc)?JSON.parse(workdesc):[];
|
||||
children = list.map((v,i) => {
|
||||
const code = toCode(i) // 转换 A-Z
|
||||
const isOk = (isJson(workdesc)?JSON.parse(o.workanswer):o.workanswer||'').includes(i+'') // 是否(包含)正确答案
|
||||
// 改选项的学生id
|
||||
const studentIds = quizFeedList.filter(f => f.feedcontent==v&&f.finishtimelength!='0').map(f => f.studentid)||[];
|
||||
accSum += studentIds.length;
|
||||
if (isOk) {
|
||||
activeIds.push(...studentIds)
|
||||
}
|
||||
hasAnswers.push(...studentIds)
|
||||
return { def: v, code, isOk, studentIds }
|
||||
})
|
||||
}
|
||||
else if (o.worktype == '多选题') {
|
||||
// 多选题的正确率单独处理
|
||||
rightIds = quizFeedList.filter(f => {
|
||||
const workanswer = (isJson(o.workanswer)) ? JSON.parse(o.workanswer) : o.workanswer || [];
|
||||
const res = isSame((f.feedcontent||'').split(','), workanswer);
|
||||
return f.entpcourseworkid == o.id && f.finishtimelength!='0' && res;
|
||||
});
|
||||
|
||||
const list = workdesc.includes('#&') ? workdesc.split('#&') : isJson(workdesc)?JSON.parse(workdesc):[];
|
||||
children = list.map((v,i) => {
|
||||
const isOne = o.worktype == '单选题'
|
||||
const code = toCode(i) // 转换 A-Z
|
||||
// const isOk = isOne ? i == o.workanswer : o.workanswer.includes(i) // 是否(包含)正确答案
|
||||
const isOk = (isJson(workdesc)?JSON.parse(o.workanswer):o.workanswer||'').includes(i+'') // 是否(包含)正确答案
|
||||
// 改选项的学生id
|
||||
const studentIds = quizFeedList.filter(f => f.feedcontent.includes(i)&&f.finishtimelength!='0').map(f => f.studentid)||[];
|
||||
accSum += studentIds.length;
|
||||
if (studentIds.length>0) {
|
||||
allStudents.push(...studentIds);
|
||||
}
|
||||
if(isOk) {
|
||||
activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重
|
||||
}
|
||||
hasAnswers=[...new Set(hasAnswers.concat(studentIds))]
|
||||
return { def: v, code, isOk, studentIds }
|
||||
})
|
||||
}
|
||||
else if (o.worktype == '填空题') { // 填空题
|
||||
const regex = /<!--BA-->(.*?)<!--EA-->/g // 定义正则表达式,匹配 <!--BA-->xxx<!--EA--> 格式的内容
|
||||
children = (o.title||'').match(regex).map((v,i) => {
|
||||
const def = `填空项 ${i+1}`
|
||||
//const code = '( )'
|
||||
const code = '(略)', txt=v
|
||||
// 改选项的学生id
|
||||
const studentIds = quizFeedList.filter(f => !!(f.feedcontent||'').replace(/#$/,'').split('#')[i] && f.finishtimelength!='0').map(f => f.studentid)||[]
|
||||
activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重
|
||||
hasAnswers=[...new Set(hasAnswers.concat(studentIds))]
|
||||
accSum = activeIds.length
|
||||
return { def, code, txt, isOk:true, studentIds }
|
||||
})
|
||||
} else if (o.worktype == '判断题') { // 判断题
|
||||
const list = ['正确', '错误'];
|
||||
children = list.map((v,i) => {
|
||||
const workanswer = o.workanswer
|
||||
.replace('×', '0')
|
||||
.replace('√', '1')
|
||||
.replace('错误', '0')
|
||||
.replace('正确', '1')
|
||||
.replace('正确。', '1')
|
||||
.replace('F', '0')
|
||||
.replace('T', '1')
|
||||
.replace('错', '0')
|
||||
.replace('对', '1');
|
||||
const workanswerFormat = isJson(workanswer) ? JSON.parse(workanswer) : workanswer||''
|
||||
const code = v=='正确' ? '1' : '0'
|
||||
let isOk = (workanswerFormat).includes(code)
|
||||
// warn: 看是否需要转为回答正常的显示, 当前为学生实际回答字面的正确和错误
|
||||
// if (workanswerFormat == '0') {
|
||||
// isOk = !isOk;
|
||||
// }
|
||||
// 改选项的学生id
|
||||
const studentIds = quizFeedList.filter(f => {
|
||||
const feedcontent = f.feedcontent
|
||||
.replace('×', '0')
|
||||
.replace('√', '1')
|
||||
.replace('错误', '0')
|
||||
.replace('正确', '1')
|
||||
.replace('正确。', '1')
|
||||
.replace('F', '0')
|
||||
.replace('T', '1')
|
||||
.replace('错', '0')
|
||||
.replace('对', '1');
|
||||
if(feedcontent == code&&f.finishtimelength!='0'){
|
||||
return f
|
||||
}
|
||||
}).map(f => f.studentid)||[];
|
||||
accSum += studentIds.length;
|
||||
if(isOk) activeIds.push(...studentIds)
|
||||
hasAnswers.push(...studentIds)
|
||||
return { def: v, code: v, isOk, studentIds }
|
||||
})
|
||||
} else { // 论述题
|
||||
// code = '( )'
|
||||
const code = '(略)', def = '解答内容'
|
||||
const studentIds = quizFeedList.filter(f => !!(f.feedcontent||'').replace(/#$/,'')&&f.finishtimelength!='0').map(f => f.studentid)||[]
|
||||
activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重
|
||||
hasAnswers=[...new Set(hasAnswers.concat(studentIds))]
|
||||
accSum = activeIds.length
|
||||
children = [{ def, code, isOk:true, studentIds }]
|
||||
}
|
||||
|
||||
const studentSum = studentList.value.length || 0 // 当前推送答题人数
|
||||
let points = percent((activeIds.length / (studentSum||1)).toFixed(2)) // 计算得分率
|
||||
let rightSum = activeIds.length; // 回答正确人数
|
||||
|
||||
// 多选题单独处理
|
||||
if (o.worktype == '多选题') {
|
||||
// 单独重新处理人数问题
|
||||
const uniqueTmpStuents = [...new Set(allStudents)];
|
||||
accSum = uniqueTmpStuents.length;
|
||||
// 单独处理得分率
|
||||
points = percent((rightIds.length / (studentSum||1)).toFixed(2)) // 计算得分率
|
||||
// 回答正确人数
|
||||
rightSum = rightIds.length;
|
||||
}
|
||||
|
||||
// def: 原始题数据 type 类型 active: 选中 points: 得分率, accSum 题解答人数
|
||||
return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, rightSum, children,hasAnswers }
|
||||
})
|
||||
console.log('获取数据: ', data)
|
||||
stuHasAnswers.value = [...data[0].hasAnswers]
|
||||
provide('hasAnswer', stuHasAnswers.value)
|
||||
}
|
||||
// 百分比现在 0-100
|
||||
const percent = v => v > 1 ? 1 : v < 0 ? 0 : Math.round(v * 100)
|
||||
// Unicode 转 字符 差值65
|
||||
const toCode = (v, b) => b ? v.charCodeAt() - 65 : String.fromCharCode(v + 65)
|
||||
// 判断是否为json字符串
|
||||
const isJson = str => {if(typeof str == 'string'){
|
||||
try {
|
||||
const res = JSON.parse(str)
|
||||
if(typeof res == 'object' && res) return true
|
||||
} catch (error) {}}return false
|
||||
}
|
||||
|
||||
watch(() => props.tableList,() => {
|
||||
useOverview.getTableList(props.tableList)
|
||||
},{deep:true})
|
||||
// === 监听器 ===
|
||||
watchEffect(() => { initData() })
|
||||
</script>
|
||||
|
|
|
@ -1,32 +1,40 @@
|
|||
<template>
|
||||
<div className="chart-container">
|
||||
<div ref="chartRef" className="chart"></div>
|
||||
<div class="chart-container">
|
||||
<div ref="chartRef" class="chart"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref,nextTick,watch} from 'vue';
|
||||
import { ref, nextTick, watch, inject,watchEffect } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
import overviewStore from '@/store/modules/overview'
|
||||
const useOverview = overviewStore()
|
||||
import overviewStore from '@/store/modules/overview';
|
||||
const useOverview = overviewStore();
|
||||
|
||||
// 获取图表容器的引用
|
||||
const chartRef = ref(null);
|
||||
|
||||
// 数据源
|
||||
const dataList = ref([
|
||||
{name: '完美', value: 0,rating:1,max:100,min:100,},
|
||||
{name: '优秀', value: 0,rating:2,max:99,min:80,},
|
||||
{name: '良好', value: 0,rating:3,max:79,min:70,},
|
||||
{name: '及格', value: 0,rating:4,max:69,min:60,},
|
||||
{name: '不及格', value: 0,rating:5,max:59,min:0,},
|
||||
{ name: '完美', value: 0, rating: 1, max: 100, min: 100 },
|
||||
{ name: '优秀', value: 0, rating: 2, max: 99, min: 80 },
|
||||
{ name: '良好', value: 0, rating: 3, max: 79, min: 70 },
|
||||
{ name: '及格', value: 0, rating: 4, max: 69, min: 60 },
|
||||
{ name: '不及格', value: 0, rating: 5, max: 59, min: 0 },
|
||||
]);
|
||||
// 答过题的学生才进行统计
|
||||
const hasAnswersData = ref([]);
|
||||
const hasStudents = ref([])
|
||||
|
||||
// 根据数据生成不同的颜色
|
||||
function getColor(index) {
|
||||
// 这里可以根据值生成不同的颜色
|
||||
const colors = ['#d14a61','#675bba', '#e89110','#008c8c','#5793f3'];
|
||||
return colors[index];
|
||||
function getColor(name) {
|
||||
const colorMap = {
|
||||
'完美': '#d14a61',
|
||||
'优秀': '#675bba',
|
||||
'良好': '#e89110',
|
||||
'及格': '#008c8c',
|
||||
'不及格': '#5793f3'
|
||||
};
|
||||
return colorMap[name];
|
||||
}
|
||||
|
||||
// 初始化图表
|
||||
|
@ -34,75 +42,81 @@ function initChart() {
|
|||
const myChart = echarts.init(chartRef.value);
|
||||
const total = dataList.value.reduce((acc, cur) => acc + cur.value, 0); // 计算总数
|
||||
|
||||
// 过滤掉值为0的数据项
|
||||
const filteredData = dataList.value.filter(item => item.value > 0);
|
||||
|
||||
const options = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
trigger: 'item',
|
||||
formatter: params => {
|
||||
const value = params.value;
|
||||
const percentage = value ? ((value / total) * 100).toFixed(2) : 0; // 计算百分比并保留两位小数
|
||||
return `${params.name}: ${value}人 (${percentage}%)`; // 显示为百分比形式
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: dataList.value.map(item => item.name),
|
||||
axisTick: {
|
||||
alignWithLabel: true
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [{
|
||||
name: '数据',
|
||||
type: 'bar',
|
||||
barWidth: '30%',
|
||||
data: dataList.value.map(item => item.value),
|
||||
type: 'pie',
|
||||
radius: '50%', // 设置饼图的半径为实心
|
||||
data: filteredData.map(item => ({
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
itemStyle: {
|
||||
color: function (params) {
|
||||
// 确保这里返回正确的颜色
|
||||
return getColor(params.dataIndex);
|
||||
color: getColor(item.name)
|
||||
}
|
||||
},
|
||||
// 显示柱子顶部的值
|
||||
})),
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
position: 'inside', // 将标签显示在饼图内部
|
||||
formatter: params => {
|
||||
const value = dataList.value[params.dataIndex].value;
|
||||
const percentage = value ? ((value / total) * 100).toFixed() : 0; // 计算百分比并保留两位小数
|
||||
return `${value}人 ${percentage}%`; // 显示为百分比形式
|
||||
const value = params.value;
|
||||
const percentage = value ? ((value / total) * 100).toFixed(2) : 0; // 计算百分比并保留两位小数
|
||||
return `${params.name}\n${value}人 (${percentage}%)`; // 显示为百分比形式,换行显示
|
||||
},
|
||||
color: '#333',
|
||||
fontSize: 12
|
||||
},
|
||||
labelLine: {
|
||||
show: false // 不显示标签线
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
myChart.setOption(options);
|
||||
}
|
||||
|
||||
// 获取表的数据
|
||||
const showEcharts = () => {
|
||||
useOverview.tableList.forEach((item,index) => {
|
||||
if(item.rating === 0) return // 没批改不计数
|
||||
hasStudents.value.forEach((item, index) => {
|
||||
if (item.rating === 0) {
|
||||
dataList.value.forEach((item1, index1) => {
|
||||
if (item1.min <= Number(item.scoingRate) && Number(item.scoingRate) <= item1.max) {
|
||||
item1.value ++
|
||||
item1.value++;
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
} else {
|
||||
dataList.value.forEach((item1, index1) => {
|
||||
if (item1.rating === item.rating) {
|
||||
item1.value++;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
//执行
|
||||
watch(() => useOverview.tableList, () => {
|
||||
showEcharts()
|
||||
hasStudents.value = useOverview.tableList.filter(item => hasAnswersData.value.includes(item.studentid)).map(item => item);
|
||||
showEcharts();
|
||||
nextTick(() => {
|
||||
initChart();
|
||||
})
|
||||
})
|
||||
|
||||
});
|
||||
},{deep: true})
|
||||
//监听
|
||||
watchEffect(() => {
|
||||
const stus = inject('hasAnswer');
|
||||
if (!stus) return;
|
||||
hasAnswersData.value = [...stus]
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import {nextTick, ref, watch} from 'vue'
|
||||
import {nextTick, ref, watch,inject,watchEffect} from 'vue'
|
||||
import overviewStore from '@/store/modules/overview'
|
||||
|
||||
const useOverview = overviewStore()
|
||||
const tabPosition = ref('left')
|
||||
//答过题的学生才进行统计
|
||||
const hasAnswersData = ref([])
|
||||
const hasStudents = ref([])
|
||||
const leftList = ref([
|
||||
{
|
||||
label:'完美',
|
||||
|
@ -65,16 +68,26 @@ const handelChange = (item) => {
|
|||
}
|
||||
//取区域的学生
|
||||
const showStudents = (index) => {
|
||||
leftList.value[index].stuList = useOverview.tableList.filter(item => {
|
||||
if(item.rating > 0){
|
||||
leftList.value[index].stuList = hasStudents.value.filter(item => {
|
||||
if(item.rating === 0){
|
||||
if(leftList.value[index].min <= Number(item.scoingRate || 0) && Number(item.scoingRate || 0) <= leftList.value[index].max ){
|
||||
return item
|
||||
}
|
||||
}else{
|
||||
if(item.rating == leftList.value[index].rating){
|
||||
return item
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
watch(() => useOverview.tableList, () => {
|
||||
hasStudents.value = useOverview.tableList.filter(item => hasAnswersData.value.includes(item.studentid)).map(item => item);
|
||||
showStudents(0)
|
||||
},{deep: true})
|
||||
watchEffect(() => {
|
||||
const stus = inject('hasAnswer')
|
||||
if(!stus) return
|
||||
hasAnswersData.value = [...stus]
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -318,6 +318,7 @@
|
|||
<div
|
||||
v-for="(score, index) in teacherRatingList"
|
||||
:key="index"
|
||||
style="white-space: nowrap;"
|
||||
:class="[
|
||||
'score-circle',
|
||||
{ active: classWorkFormScore.rating == score.ratingKey }
|
||||
|
@ -501,11 +502,11 @@ const classWorkFormScore = reactive({
|
|||
teacherremark: '' //评分说明
|
||||
})
|
||||
const teacherRatingList = ref([
|
||||
{ ratingKey: '1', ratingValue: '优' },
|
||||
{ ratingKey: '2', ratingValue: '优-' },
|
||||
{ ratingKey: '3', ratingValue: '良' },
|
||||
{ ratingKey: '4', ratingValue: '良-' },
|
||||
{ ratingKey: '5', ratingValue: '差' }
|
||||
{ ratingKey: '1', ratingValue: '完美' },
|
||||
{ ratingKey: '2', ratingValue: '优秀' },
|
||||
{ ratingKey: '3', ratingValue: '良好' },
|
||||
{ ratingKey: '4', ratingValue: '及格' },
|
||||
{ ratingKey: '5', ratingValue: '不及格' }
|
||||
])
|
||||
// 确定的线上图片数据
|
||||
//#region 文件内容相关
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||
:type="classWorkAnalysis.view == 'quizStats' ? 'success' : ''"
|
||||
@click="workHandle('quizStats')"
|
||||
>逐题分析</el-button
|
||||
>逐题讲评</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||
|
@ -94,19 +94,19 @@
|
|||
</template>
|
||||
<!-- 1-优 2-优减 3-良 4-良减 5-差 -->
|
||||
<template v-if="scope.row.teacherRating == 1"
|
||||
><el-tag type="danger">优</el-tag></template
|
||||
><el-tag type="danger">完美</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 2"
|
||||
><el-tag type="danger">优-</el-tag></template
|
||||
><el-tag type="danger">优秀</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 3"
|
||||
><el-tag type="warning">良</el-tag></template
|
||||
><el-tag type="warning">良好</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 4"
|
||||
><el-tag type="info">良-</el-tag></template
|
||||
><el-tag type="info">及格</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 5"
|
||||
><el-tag type="info">差</el-tag></template
|
||||
><el-tag type="info">不及格</el-tag></template
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -141,7 +141,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 逐题分析 -->
|
||||
<!-- 逐题讲评 -->
|
||||
<div v-else-if="classWorkAnalysis.view == 'quizStats'">
|
||||
<quiz-stats :active-data="classWorkActiveData" />
|
||||
</div>
|
||||
|
@ -193,7 +193,7 @@ const tableRadio = reactive({
|
|||
const loading_dt_table = ref(false)
|
||||
const isopen_dtwk_table = ref(false)
|
||||
|
||||
// zdg: 逐题分析
|
||||
// zdg: 逐题讲评
|
||||
const classWorkActiveData = reactive({
|
||||
quizlist: [], // 当前习题列表
|
||||
studentList: [], // 当前课程-所有学生
|
||||
|
@ -536,7 +536,7 @@ const escapeHtmlQuotes = (str) => {
|
|||
return result;
|
||||
}
|
||||
|
||||
//#region 逐题分析
|
||||
//#region 逐题讲评
|
||||
// 查看学生-作业概览
|
||||
const workHandle = (type) => {
|
||||
// 关闭右侧批阅ui
|
||||
|
@ -643,12 +643,12 @@ const closeDialog = () => {
|
|||
watch(classWorkAnalysis, (newVal, oldVal) => {
|
||||
if(newVal.view != 'quizStats'){
|
||||
console.log('关闭zdg: 定时执行')
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题分析的
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题讲评的
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题分析的
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题讲评的
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
|
@ -656,8 +656,6 @@ defineExpose({
|
|||
})
|
||||
</script>
|
||||
|
||||
<style src="@/assets/styles/JYStyle.css"></style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/*:deep(.reserv-date-pick) {
|
||||
width: 140px;
|
||||
|
@ -765,3 +763,4 @@ defineExpose({
|
|||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
<style src="@/assets/styles/JYStyle.css"></style>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<div v-if="classWorkForm.worktype == '课堂展示'" style="height: 100%; display: flex; flex-direction: column;">
|
||||
<div style="flex: 0 0 auto;">
|
||||
<el-form-item label="问题">
|
||||
<el-input v-model="classWorkForm.title" type="text" placeholder="请输入问题" />
|
||||
<el-input v-model="classWorkForm.question" type="text" placeholder="请输入问题" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-loading="boardLoading" class="board-wrap" style="height: 100%; flex: 1; overflow: hidden;">
|
||||
|
@ -349,6 +349,7 @@ let classWorkForm = reactive({
|
|||
chooseWorkLists: props.propsformobj.chooseWorkLists?cloneDeep(props.propsformobj.chooseWorkLists):[], // 作业框架梳理list
|
||||
fileHomeworkList: props.propsformobj.fileHomeworkList?cloneDeep(props.propsformobj.fileHomeworkList):[], // 常规作业文件列表
|
||||
whiteboardObj: props.propsformobj.whiteboardObj?cloneDeep(props.propsformobj.whiteboardObj):'', // 作业资源 - 课堂展示 白板
|
||||
question: props.propsformobj.question?cloneDeep(props.propsformobj.question):'', // 作业资源 - 课堂展示 输入的问题
|
||||
}); // 提交的作业内容
|
||||
// ---------------------------------------------------
|
||||
// const listWorkType = ref(['习题训练', '框架梳理', '课堂展示', '常规作业']); //作业类型
|
||||
|
@ -638,6 +639,7 @@ const handleClassWorkSave = async () => {
|
|||
let canvasJson = proxy.$refs.boardref.getCanvasJson()
|
||||
let canvasBase64 = await proxy.$refs.boardref.getCanvasBase64()
|
||||
// 课堂展示提交内容
|
||||
cform.worktag = classWorkForm.question;
|
||||
cform.title = classWorkForm.title;
|
||||
cform.workcodes = JSON.stringify({json: canvasJson, base64: canvasBase64});
|
||||
cform.entpcourseworklist = JSON.stringify([{'id':-1, 'score': '10'}]);
|
||||
|
@ -648,6 +650,7 @@ const handleClassWorkSave = async () => {
|
|||
classWorkForm.worktype = "课堂展示";
|
||||
classWorkForm.uniquekey = props.propsformobj.uniquekey, // 作业唯一标识 作业名称
|
||||
classWorkForm.title = "";
|
||||
classWorkForm.question = "";
|
||||
classWorkForm.quizlist = [], // 作业习题列表内容
|
||||
|
||||
// 情况选择的资源缓存
|
||||
|
@ -839,6 +842,7 @@ const editWork = async (cform) =>{
|
|||
let canvasJson = proxy.$refs.boardref.getCanvasJson()
|
||||
let canvasBase64 = await proxy.$refs.boardref.getCanvasBase64()
|
||||
cform.workcodes = JSON.stringify({json: canvasJson, base64: canvasBase64});
|
||||
cform.worktag = classWorkForm.question;
|
||||
}
|
||||
else if (classWorkForm.worktype=='常规作业') {
|
||||
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
||||
|
|
|
@ -69,6 +69,7 @@ const classWorkForm = reactive({
|
|||
chooseWorkLists: classtaskObj? JSON.parse(classtaskObj).chooseWorkLists : [],// 设计中的框架梳理list
|
||||
fileHomeworkList: classtaskObj? JSON.parse(classtaskObj).fileHomeworkList : [],// 设计中的常规文件作业list
|
||||
whiteboardObj: classtaskObj? JSON.parse(classtaskObj).whiteboardObj : '',// 设计中的 课堂展示 板书作业
|
||||
question: classtaskObj? JSON.parse(classtaskObj).question : '',// 设计中的 课堂展示 输入的问题
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||
:type="classWorkAnalysis.view == 'quizStats' ? 'success' : ''"
|
||||
@click="workHandle('quizStats')"
|
||||
>逐题分析</el-button
|
||||
>逐题讲评</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="classWorkAnalysis.row.worktype == '习题训练'"
|
||||
|
@ -84,19 +84,19 @@
|
|||
</template>
|
||||
<!-- 1-优 2-优减 3-良 4-良减 5-差 -->
|
||||
<template v-if="scope.row.teacherRating == 1"
|
||||
><el-tag type="danger">优</el-tag></template
|
||||
><el-tag type="danger">完美</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 2"
|
||||
><el-tag type="danger">优-</el-tag></template
|
||||
><el-tag type="danger">优秀</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 3"
|
||||
><el-tag type="warning">良</el-tag></template
|
||||
><el-tag type="warning">良好</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 4"
|
||||
><el-tag type="info">良-</el-tag></template
|
||||
><el-tag type="info">及格</el-tag></template
|
||||
>
|
||||
<template v-if="scope.row.teacherRating == 5"
|
||||
><el-tag type="info">差</el-tag></template
|
||||
><el-tag type="info">不及格</el-tag></template
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -131,7 +131,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 逐题分析 -->
|
||||
<!-- 逐题讲评 -->
|
||||
<div v-else-if="classWorkAnalysis.view == 'quizStats'" style="width: 100%;">
|
||||
<quiz-stats :active-data="classWorkActiveData" style="width: 100%;height: 100%;"/>
|
||||
</div>
|
||||
|
@ -139,7 +139,7 @@
|
|||
<!-- 训练报告-->
|
||||
<div v-else-if="classWorkAnalysis.view == 'report'" style="width: 100%;overflow-y: scroll">
|
||||
<!-- <ClassOverview :table-list="overviewData" :eval-id="courseObj.evalid"></ClassOverview> -->
|
||||
<ClassOverview :table-list="overviewData" style="width: 100%;"></ClassOverview>
|
||||
<ClassOverview :active-data="classWorkActiveData" :table-list="overviewData" style="width: 100%;"></ClassOverview>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -180,7 +180,7 @@ const tableRadio = reactive({
|
|||
const loading_dt_table = ref(false)
|
||||
const isopen_dtwk_table = ref(false)
|
||||
|
||||
// zdg: 逐题分析
|
||||
// zdg: 逐题讲评
|
||||
const classWorkActiveData = reactive({
|
||||
quizlist: [], // 当前习题列表
|
||||
studentList: [], // 当前课程-所有学生
|
||||
|
@ -528,7 +528,7 @@ const escapeHtmlQuotes = (str) => {
|
|||
return result;
|
||||
}
|
||||
|
||||
//#region 逐题分析
|
||||
//#region 逐题讲评
|
||||
// 查看学生-作业概览
|
||||
const workHandle = (type) => {
|
||||
// 关闭右侧批阅ui
|
||||
|
@ -646,20 +646,18 @@ onMounted(() => {
|
|||
watch(classWorkAnalysis, (newVal, oldVal) => {
|
||||
if(newVal.view != 'quizStats'){
|
||||
console.log('关闭zdg: 定时执行')
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题分析的
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题讲评的
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题分析的
|
||||
clearInterval(classWorkActiveData.timerId) // 关闭定时器 逐题讲评的
|
||||
})
|
||||
|
||||
// defineExpose({
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style src="@/assets/styles/JYStyle.css"></style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.teachClassTask{
|
||||
height: 100%;
|
||||
|
@ -705,94 +703,6 @@ onUnmounted(() => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// .clwk_dialog {
|
||||
|
||||
// }
|
||||
|
||||
// .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>
|
||||
<style src="@/assets/styles/JYStyle.css"></style>
|
||||
|
|
|
@ -98,7 +98,7 @@ import FileImage from '@/components/file-image/index.vue'
|
|||
import { asyncLocalFile } from '@/utils/talkFile'
|
||||
import { toTimeText } from '@/utils/date'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { deleteSmarttalk, updateSmarttalk, getPrepareById } from '@/api/file'
|
||||
import { deleteSmarttalk, updateSmarttalk, getPrepareById, getSmarttalkPage } from '@/api/file'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import outLink from '@/utils/linkConfig'
|
||||
import { sessionStore } from '@/utils/store'
|
||||
|
@ -208,6 +208,7 @@ export default {
|
|||
}
|
||||
if (action === 'cancel'){
|
||||
// 继续上课
|
||||
console.log(obj.bookImg)
|
||||
if (obj.bookImg) {
|
||||
//PPT
|
||||
listEntpcourse({
|
||||
|
@ -241,9 +242,20 @@ export default {
|
|||
}
|
||||
})
|
||||
}else {
|
||||
console.log(obj)
|
||||
getSmarttalkPage({fileId: obj.entpcoursefileid}).then(res2=>{
|
||||
console.log(res2)
|
||||
//APT
|
||||
this.$emit('on-start-class', item, obj)
|
||||
if (res2&&res2.rows.length>0) {
|
||||
this.$emit('on-start-class', res2.rows[0], obj)
|
||||
}else {
|
||||
ElMessage({
|
||||
message: '该文件未关联PPT,无法打开!',
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
done()
|
||||
})
|
||||
}
|
||||
}
|
||||
if (action === 'close') {
|
||||
|
|
|
@ -291,6 +291,7 @@ export default {
|
|||
methods: {
|
||||
addAiPPT(item) {
|
||||
this.currentFileList.unshift(item.resData)
|
||||
KjListItem.methods.openFileWin(item.resData);
|
||||
this.pptDialog = false
|
||||
},
|
||||
// test() {
|
||||
|
|
Loading…
Reference in New Issue