forked from integrated_whb/integrated_whb_vue
班级管理/课程
parent
e803f8bf41
commit
ea9800791a
|
@ -46,3 +46,21 @@ export const getClassManagementStudentExamRecordsList = (params) =>
|
|||
post("/stageexam/list", params); // 班级管理学员考试记录列表
|
||||
export const getClassManagementStudentExamRecordsView = (params) =>
|
||||
post("/stageexam/findExam", params); // 班级管理学员考试记录查看
|
||||
export const getClassManagementCurriculumList = (params) =>
|
||||
post("/classCurriculum/list", params); // 班级管理课程列表
|
||||
export const setClassManagementCurriculumDelete = (params) =>
|
||||
post("/classCurriculum/delete", params); // 班级管理课程删除
|
||||
export const setClassManagementCurriculumAdd = (params) =>
|
||||
post("/classCurriculum/addClassCurriculum", params); // 班级管理课程新增
|
||||
export const getClassManagementCurriculumView = (params) =>
|
||||
post("/classCurriculum/goEdit", params); // 班级管理课程查看
|
||||
export const getClassManagementInvolvedInTrainingList = (params) =>
|
||||
post("/curriculumpost/listClassCurPost", params); // 班级管理获取涉及培训岗位
|
||||
export const getClassManagementInvolvedInTrainingDepartmentList = (params) =>
|
||||
post("/classpost/listDepByClass", params); // 班级管理获取涉及培训岗位部门列表
|
||||
export const getClassManagementInvolvedInTrainingPostList = (params) =>
|
||||
post("/classpost/listPostByClassDep", params); // 班级管理获取涉及培训岗位岗位列表
|
||||
export const setClassManagementInvolvedInTrainingAdd = (params) =>
|
||||
post("/curriculumpost/saveClassCurPost", params); // 班级管理涉及培训岗位保存
|
||||
export const getClassManagementExamPaperList = (params) =>
|
||||
post("/classpost/listClassPost", params); // 班级管理试卷列表
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
<template>
|
||||
<layout-card>
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="16">
|
||||
<el-form
|
||||
:model="searchForm"
|
||||
label-width="100px"
|
||||
@submit.prevent="fnResetPagination"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="课程名称" prop="KEYWORDS">
|
||||
<el-input v-model="searchForm.KEYWORDS" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="培训类型" prop="TRAINTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="searchForm.TRAINTYPE"
|
||||
type="trainingType"
|
||||
@update:model-value="
|
||||
searchForm.POSTTYPE = '';
|
||||
searchForm.TRAINLEVEL = '';
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="行业类型" prop="INDUSTRY_END_ID">
|
||||
<layout-learning-train-type
|
||||
v-model="searchForm.INDUSTRY_END_ID"
|
||||
type="industryType"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="岗位类型" prop="POSTTYPE">
|
||||
<layout-learning-train-type
|
||||
v-model="searchForm.POSTTYPE"
|
||||
type="postType"
|
||||
:search-value="searchForm.TRAINTYPE"
|
||||
@update:model-value="searchForm.TRAINLEVEL = ''"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="培训级别" prop="TRAINLEVEL">
|
||||
<layout-learning-train-type
|
||||
v-model="searchForm.TRAINLEVEL"
|
||||
type="trainingLevel"
|
||||
:search-value="searchForm.POSTTYPE"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label-width="10px">
|
||||
<el-button type="primary" native-type="submit">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button native-type="reset" @click="fnResetPagination">
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<layout-table
|
||||
v-model:pagination="pagination"
|
||||
:data="list"
|
||||
@get-data="fnGetData"
|
||||
>
|
||||
<el-table-column label="序号" width="60">
|
||||
<template #default="{ $index }">
|
||||
{{ serialNumber(pagination, $index) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="CURRICULUMNAME"
|
||||
label="课程名称"
|
||||
/>
|
||||
<el-table-column prop="CLASSHOUR" label="学时" width="100" />
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="TRAININGTYPE_NAME"
|
||||
label="培训类型"
|
||||
/>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="INDUSTRY_ALL_NAME"
|
||||
label="行业类型"
|
||||
/>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="POSTTYPE_NAME"
|
||||
label="岗位类型"
|
||||
/>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="TRAINLEVEL_NAME"
|
||||
label="培训等级"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="60" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.ISUSE === '1'">已使用</span>
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="fnApply(row.CURRICULUM_ID)"
|
||||
>
|
||||
使用
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</layout-table>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<template v-if="data.chapterList.length > 0">
|
||||
<el-divider content-position="left">总学时</el-divider>
|
||||
<el-row style="font-size: 14px">
|
||||
<el-col :span="8">
|
||||
所选课件总学时:
|
||||
<span>
|
||||
{{
|
||||
data.countClassHour === 0
|
||||
? data.countClassHour
|
||||
: data.countClassHour.toFixed(1)
|
||||
}}
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
所选课件视频总时长:
|
||||
<span>
|
||||
{{ secondConversion(data.countVideoTime) }}
|
||||
</span>
|
||||
</el-col>
|
||||
<el-col :span="8" class="mt-10">
|
||||
课程总学时:
|
||||
<span>{{ data.info.CLASSHOUR }}</span>
|
||||
</el-col>
|
||||
<el-col :span="16" class="mt-10">
|
||||
课程视频总时长:
|
||||
<span>{{ secondConversion(data.info.VIDEOTIME) }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="left">章节编排</el-divider>
|
||||
<div class="mb-5">
|
||||
<el-button @click="fnSwitchSelectAll">
|
||||
{{ data.isSelectAll ? "全不选" : "全选" }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-scrollbar style="height: 310px">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="data.chapterList"
|
||||
:props="{ children: 'nodes', label: 'COURSEWARENAME' }"
|
||||
class="directory_style"
|
||||
default-expand-all
|
||||
node-key="CHAPTER_ID"
|
||||
show-checkbox
|
||||
@check-change="fnCheckChange"
|
||||
>
|
||||
<template #default="{ data: item }">
|
||||
<div class="directory_row">
|
||||
<el-icon
|
||||
v-if="item.COURSEWARENAME"
|
||||
class="el-icon-video-camera"
|
||||
size="18"
|
||||
>
|
||||
<video-camera />
|
||||
</el-icon>
|
||||
<span class="directory_name line-1">
|
||||
{{ item.NAME || item.COURSEWARENAME }}
|
||||
</span>
|
||||
<span v-if="item.COURSEWARENAME" class="directory_type">
|
||||
课件时长:{{ secondConversion(item.VIDEOTIME) }}
|
||||
</span>
|
||||
<el-button
|
||||
v-if="item.COURSEWARENAME"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="fnPreview(item)"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
<div v-else class="tc mt-50">暂未选择课程,请点击左侧使用</div>
|
||||
<layout-video
|
||||
v-model:visible="data.videoDialog.visible"
|
||||
:src="data.videoDialog.src"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="tc mt-10">
|
||||
<el-button type="primary" @click="fnSubmit">保存</el-button>
|
||||
</div>
|
||||
</layout-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LayoutLearningTrainType from "@/components/learning_train_type/index.vue";
|
||||
import { secondConversion, serialNumber } from "@/assets/js/utils.js";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import {
|
||||
getCourseManagementList,
|
||||
getCourseManagementView,
|
||||
getPreviewingVideo,
|
||||
} from "@/request/training_resource_management.js";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { VideoCamera } from "@element-plus/icons-vue";
|
||||
import LayoutVideo from "@/components/video/index.vue";
|
||||
import { reactive, ref } from "vue";
|
||||
import { sumBy } from "lodash-es";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { setClassManagementCurriculumAdd } from "@/request/training_process_management.js";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { CLASS_ID } = route.query;
|
||||
const { list, searchForm, pagination, fnGetData, fnResetPagination } =
|
||||
useListData(getCourseManagementList, {
|
||||
otherParams: { ISSELL: "1", CLASS_ID },
|
||||
});
|
||||
let checkedList = [];
|
||||
const treeRef = ref(null);
|
||||
const data = reactive({
|
||||
chapterList: [],
|
||||
countClassHour: 0,
|
||||
countVideoTime: 0,
|
||||
isSelectAll: false,
|
||||
info: {},
|
||||
videoDialog: {
|
||||
visible: false,
|
||||
src: "",
|
||||
},
|
||||
});
|
||||
const fnApply = async (CURRICULUM_ID) => {
|
||||
const resData = await getCourseManagementView({ CURRICULUM_ID });
|
||||
data.chapterList = resData.chapterList;
|
||||
data.info = resData.pd;
|
||||
data.countClassHour = 0;
|
||||
data.countVideoTime = 0;
|
||||
data.isSelectAll = false;
|
||||
checkedList = [];
|
||||
};
|
||||
const fnSwitchSelectAll = () => {
|
||||
data.isSelectAll = !data.isSelectAll;
|
||||
treeRef.value.setCheckedNodes(data.isSelectAll ? data.chapterList : []);
|
||||
};
|
||||
const fnCheckChange = (row, checked) => {
|
||||
if (row.disabled) {
|
||||
treeRef.value.setChecked(row, false, false);
|
||||
return;
|
||||
}
|
||||
if (row.VIDEOCOURSEWARE_ID) {
|
||||
if (checked) {
|
||||
checkedList.push(row);
|
||||
} else {
|
||||
const index = checkedList.findIndex(
|
||||
(item) => item.VIDEOCOURSEWARE_ID === row.VIDEOCOURSEWARE_ID
|
||||
);
|
||||
checkedList.splice(index, 1);
|
||||
}
|
||||
data.countClassHour = sumBy(checkedList, (item) => +item.CLASSHOUR);
|
||||
data.countVideoTime = sumBy(checkedList, (item) => +item.VIDEOTIME);
|
||||
}
|
||||
};
|
||||
const fnPreview = async ({ VIDEOCOURSEWARE_ID, VIDEOFILES, CURRICULUM_ID }) => {
|
||||
const resData = await getPreviewingVideo({
|
||||
VIDEOCOURSEWARE_ID,
|
||||
VIDEOFILES,
|
||||
CURRICULUM_ID,
|
||||
});
|
||||
data.videoDialog.src = JSON.stringify(resData.urlList);
|
||||
data.videoDialog.visible = true;
|
||||
};
|
||||
const fnSubmit = debounce(
|
||||
1000,
|
||||
async () => {
|
||||
const chapterList = [
|
||||
...treeRef.value.getCheckedKeys(),
|
||||
...treeRef.value.getHalfCheckedKeys(),
|
||||
];
|
||||
if (chapterList.length === 0) {
|
||||
ElMessage.warning("请选择课程");
|
||||
return;
|
||||
}
|
||||
await setClassManagementCurriculumAdd({
|
||||
CLASS_ID,
|
||||
CURRICULUM_ID: data.info.CURRICULUM_ID,
|
||||
chapterList: chapterList.join(","),
|
||||
});
|
||||
ElMessage.success("保存成功");
|
||||
router.back();
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.directory_style {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.el-icon-video-camera {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.directory_row {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
|
||||
.directory_name {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.directory_type {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep {
|
||||
.el-tree-node__content {
|
||||
margin-bottom: 10px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -185,17 +185,17 @@
|
|||
<el-col :span="12">
|
||||
<el-form-item label="是否人脸识别" prop="ISFACE">
|
||||
<el-radio-group v-model="data.form.ISFACE" :disabled="isEdit">
|
||||
<el-radio label="1">是</el-radio>
|
||||
<el-radio label="0">否</el-radio>
|
||||
<el-radio value="1">是</el-radio>
|
||||
<el-radio value="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="data.form.EXAMINATION === 1" :span="12">
|
||||
<el-form-item label="是否效果评估" prop="ISSTRENGTHEN">
|
||||
<el-radio-group v-model="data.form.ISSTRENGTHEN" :disabled="isEdit">
|
||||
<el-radio label="2">强制</el-radio>
|
||||
<el-radio label="1">是</el-radio>
|
||||
<el-radio label="0">否</el-radio>
|
||||
<el-radio value="2">强制</el-radio>
|
||||
<el-radio value="1">是</el-radio>
|
||||
<el-radio value="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
@ -351,7 +351,6 @@ const fnSubmit = debounce(
|
|||
query: {
|
||||
...route.query,
|
||||
CLASS_ID: !CLASS_ID ? resData.CLASS_ID : CLASS_ID,
|
||||
TRAINTYPE: data.form.TRAINTYPE,
|
||||
EXAMINATION: data.form.EXAMINATION,
|
||||
ISSTRENGTHEN: data.form.ISSTRENGTHEN,
|
||||
},
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="配置试卷" width="60%">
|
||||
<layout-table
|
||||
ref="tableRef"
|
||||
v-model:pagination="pagination"
|
||||
:data="list"
|
||||
row-key="STAGEEXAMPAPERINPUT_ID"
|
||||
@get-data="fnGetData"
|
||||
>
|
||||
<el-table-column reserve-selection type="selection" width="55" />
|
||||
<el-table-column label="序号" width="60">
|
||||
<template #default="{ $index }">
|
||||
{{ serialNumber(pagination, $index) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="DEPARTMENT_NAME"
|
||||
label="部门"
|
||||
/>
|
||||
<el-table-column show-overflow-tooltip prop="POST_NAME" label="岗位" />
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="CURRICULUMNAME"
|
||||
label="涉及课程"
|
||||
/>
|
||||
<el-table-column label="试卷类型" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ row.PAPERSELECTTYPE === "1" ? "平台试卷" : "" }}
|
||||
{{ row.PAPERSELECTTYPE === "2" ? "自动生成试卷" : "" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="
|
||||
fnTestPaperType(
|
||||
row.PAPERSELECTTYPE ? 'edit' : 'add',
|
||||
row.CLASSPOST_ID,
|
||||
row.PAPERSELECTTYPE ? row.POSTPAPER_ID : '',
|
||||
row.CURRICULUM_IDS
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ row.PAPERSELECTTYPE ? "编辑试卷" : "新增试卷" }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="!row.PAPERSELECTTYPE"
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="fnView(row.STAGEEXAMPAPERINPUT_ID)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #button>
|
||||
<el-button type="primary"> 批量添加试卷 </el-button>
|
||||
</template>
|
||||
</layout-table>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<exam-paper-details
|
||||
v-model:visible="data.viewDialog.visible"
|
||||
:info="data.viewDialog.info"
|
||||
/>
|
||||
<test-paper-type
|
||||
v-model:visible="data.testPaperTypeDialog.visible"
|
||||
:type="data.testPaperTypeDialog.type"
|
||||
:class-post-id="data.testPaperTypeDialog.CLASSPOST_ID"
|
||||
:post-paper-id="data.testPaperTypeDialog.POSTPAPER_ID"
|
||||
:curriculum-ids="data.testPaperTypeDialog.CURRICULUM_IDS"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { useRoute } from "vue-router";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import { getClassManagementExamPaperList } from "@/request/training_process_management.js";
|
||||
import { serialNumber } from "@/assets/js/utils.js";
|
||||
import {
|
||||
getExamPaperManagementTestQuestions,
|
||||
getExamPaperManagementView,
|
||||
} from "@/request/training_resource_management.js";
|
||||
import { reactive, watchEffect } from "vue";
|
||||
import ExamPaperDetails from "./exam_paper_details.vue";
|
||||
import TestPaperType from "./test_paper_type.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const { CLASS_ID } = route.query;
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible"]);
|
||||
const visible = useVModel(props, "visible", emits);
|
||||
const { list, pagination, fnGetData, fnResetPagination, tableRef } =
|
||||
useListData(getClassManagementExamPaperList, {
|
||||
otherParams: { CLASS_ID },
|
||||
immediate: false,
|
||||
});
|
||||
const data = reactive({
|
||||
viewDialog: {
|
||||
visible: false,
|
||||
info: {},
|
||||
},
|
||||
testPaperTypeDialog: {
|
||||
visible: false,
|
||||
type: "",
|
||||
CLASSPOST_ID: "",
|
||||
POSTPAPER_ID: "",
|
||||
CURRICULUM_IDS: "",
|
||||
},
|
||||
});
|
||||
watchEffect(() => {
|
||||
if (visible.value) fnResetPagination();
|
||||
});
|
||||
const fnView = async (STAGEEXAMPAPERINPUT_ID) => {
|
||||
const { pd } = await getExamPaperManagementView({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
});
|
||||
data.viewDialog.info = pd;
|
||||
const { varList } = await getExamPaperManagementTestQuestions({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
});
|
||||
data.viewDialog.info.testPaper = varList;
|
||||
data.viewDialog.visible = true;
|
||||
};
|
||||
const fnTestPaperType = (type, CLASSPOST_ID, POSTPAPER_ID, CURRICULUM_IDS) => {
|
||||
data.testPaperTypeDialog.type = type;
|
||||
data.testPaperTypeDialog.CLASSPOST_ID = CLASSPOST_ID;
|
||||
data.testPaperTypeDialog.POSTPAPER_ID = POSTPAPER_ID;
|
||||
data.testPaperTypeDialog.CURRICULUM_IDS = CURRICULUM_IDS;
|
||||
data.testPaperTypeDialog.visible = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -1,5 +1,94 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="mb-10">
|
||||
<el-button
|
||||
v-if="!isEdit"
|
||||
type="primary"
|
||||
@click="
|
||||
router.push({
|
||||
path: '/training_process_management/class_management/curriculum/add',
|
||||
query: { CLASS_ID },
|
||||
})
|
||||
"
|
||||
>
|
||||
新增课程
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isEdit && EXAMINATION === '1'"
|
||||
type="primary"
|
||||
@click="data.configurationTestPaperDialogVisible = true"
|
||||
>
|
||||
配置试卷
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="isEdit && EXAMINATION === '1'"
|
||||
type="primary"
|
||||
@click="data.examPaperRecordsDialogVisible = true"
|
||||
>
|
||||
试卷详情
|
||||
</el-button>
|
||||
</div>
|
||||
<layout-table
|
||||
v-model:pagination="pagination"
|
||||
:data="list"
|
||||
@get-data="fnGetData"
|
||||
>
|
||||
<el-table-column label="序号" width="60">
|
||||
<template #default="{ $index }">
|
||||
{{ serialNumber(pagination, $index) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="CURRICULUMNAME"
|
||||
label="课程名称"
|
||||
/>
|
||||
<el-table-column prop="ALL_DEPARTMENT_NAME" label="部门" />
|
||||
<el-table-column prop="ALL_POST_NAME" label="岗位" />
|
||||
<el-table-column prop="CLASSHOUR" label="要求完成总学时" width="150" />
|
||||
<el-table-column label="视频累计时长" width="150">
|
||||
<template #default="{ row }">
|
||||
{{ secondConversion(row.VIDEOTIME) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="start_sum" label="上课学员数" width="150" />
|
||||
<el-table-column prop="finsh_num" label="已完成学员数" width="150" />
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="
|
||||
router.push({
|
||||
path: '/training_process_management/class_management/curriculum/view',
|
||||
query: { CLASSCURRICULUM_ID: row.CLASSCURRICULUM_ID },
|
||||
})
|
||||
"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isEdit"
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="fnInvolvedInTraining(row.CLASSCURRICULUM_ID)"
|
||||
>
|
||||
涉及培训岗位
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isEdit"
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="fnDelete(row.CLASSCURRICULUM_ID)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</layout-table>
|
||||
<div v-if="!isEdit" class="mt-10 tc">
|
||||
<el-button
|
||||
@click="
|
||||
|
@ -13,16 +102,74 @@
|
|||
</el-button>
|
||||
<el-button type="primary"> 完成 </el-button>
|
||||
</div>
|
||||
<involved-in-training
|
||||
:id="data.involvedInTrainingDialog.CLASSCURRICULUM_ID"
|
||||
v-model:visible="data.involvedInTrainingDialog.visible"
|
||||
v-model:form="data.involvedInTrainingDialog.form"
|
||||
@get-data="fnResetPagination"
|
||||
/>
|
||||
<exam-paper-records v-model:visible="data.examPaperRecordsDialogVisible" />
|
||||
<configuration-test-paper
|
||||
v-model:visible="data.configurationTestPaperDialogVisible"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { secondConversion, serialNumber } from "@/assets/js/utils.js";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import {
|
||||
getClassManagementCurriculumList,
|
||||
getClassManagementInvolvedInTrainingList,
|
||||
setClassManagementCurriculumDelete,
|
||||
} from "@/request/training_process_management.js";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { reactive } from "vue";
|
||||
import InvolvedInTraining from "./involved_in_training.vue";
|
||||
import ExamPaperRecords from "./exam_paper_records.vue";
|
||||
import ConfigurationTestPaper from "./configuration_test_paper.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { STATE } = route.query;
|
||||
const { STATE, CLASS_ID, EXAMINATION } = route.query;
|
||||
const isEdit = STATE && STATE !== "1";
|
||||
const { list, pagination, fnGetData, fnResetPagination } = useListData(
|
||||
getClassManagementCurriculumList,
|
||||
{
|
||||
otherParams: { CLASS_ID },
|
||||
}
|
||||
);
|
||||
const data = reactive({
|
||||
involvedInTrainingDialog: {
|
||||
visible: false,
|
||||
CLASSCURRICULUM_ID: "",
|
||||
form: { list: [] },
|
||||
},
|
||||
examPaperRecordsDialogVisible: false,
|
||||
configurationTestPaperDialogVisible: false,
|
||||
});
|
||||
const fnInvolvedInTraining = async (CLASSCURRICULUM_ID) => {
|
||||
const resData = await getClassManagementInvolvedInTrainingList({
|
||||
CLASSCURRICULUM_ID,
|
||||
});
|
||||
data.involvedInTrainingDialog.CLASSCURRICULUM_ID = CLASSCURRICULUM_ID;
|
||||
data.involvedInTrainingDialog.form.list = resData.varList;
|
||||
data.involvedInTrainingDialog.visible = true;
|
||||
};
|
||||
const fnDelete = debounce(
|
||||
1000,
|
||||
async (CLASSCURRICULUM_ID) => {
|
||||
await ElMessageBox.confirm("你确定要删除该课程吗?", {
|
||||
type: "warning",
|
||||
});
|
||||
await setClassManagementCurriculumDelete({ CLASSCURRICULUM_ID });
|
||||
ElMessage.success("删除成功");
|
||||
fnResetPagination();
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
|
@ -1,18 +1,32 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="考试详情" width="70%">
|
||||
<el-divider content-position="left">考试学员信息</el-divider>
|
||||
<div style="display: flex; justify-content: space-around">
|
||||
<div>学员名字:{{ info.USERNAME }}</div>
|
||||
<div>考试时间:{{ info.EXAMTIMEBEGIN + "至" + info.EXAMTIMEEND }}</div>
|
||||
<div>得分:{{ info.EXAMSCORE }}</div>
|
||||
</div>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="学员名字">
|
||||
{{ info.USERNAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="考试时间">
|
||||
{{ info.EXAMTIMEBEGIN + "至" + info.EXAMTIMEEND }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="得分">
|
||||
{{ info.EXAMSCORE }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">试卷基本信息</el-divider>
|
||||
<div style="display: flex; justify-content: space-around">
|
||||
<div>试卷名称:{{ info.EXAMNAME }}</div>
|
||||
<div>试卷总分:{{ info.PAPEREXAMSCORE }}</div>
|
||||
<div>考试时长:{{ info.ANSWERSHEETTIME }}分钟</div>
|
||||
<div>通过分数:{{ info.PASSSCORE }}</div>
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="试卷名称">
|
||||
{{ info.EXAMNAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="试卷总分">
|
||||
{{ info.PAPEREXAMSCORE }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="考试时长">
|
||||
{{ info.ANSWERSHEETTIME }}分钟
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通过分数">
|
||||
{{ info.PASSSCORE }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">试卷内容信息</el-divider>
|
||||
<div class="items mt-20 p-20">
|
||||
<div
|
||||
|
@ -34,28 +48,28 @@
|
|||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio label="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio label="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio value="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio value="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group
|
||||
v-if="item.QUESTIONTYPE === '2'"
|
||||
disabled
|
||||
:model-value="item.ANSWER?.split('')"
|
||||
>
|
||||
<el-checkbox label="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox label="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox label="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox label="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
<el-checkbox value="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox value="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox value="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox value="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '3'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="mt-10">答案:{{ item.ANSWER }}</div>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="试卷详情" width="70%">
|
||||
<view-info :info="info" />
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import ViewInfo from "@/views/training_resource_management/exam_paper_management/components/view.vue";
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible"]);
|
||||
const visible = useVModel(props, "visible", emits);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="试卷记录" width="60%">
|
||||
<layout-table
|
||||
v-model:pagination="pagination"
|
||||
:data="list"
|
||||
@get-data="fnGetData"
|
||||
>
|
||||
<el-table-column label="序号" width="60">
|
||||
<template #default="{ $index }">
|
||||
{{ serialNumber(pagination, $index) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="DEPARTMENT_NAME"
|
||||
label="部门"
|
||||
/>
|
||||
<el-table-column show-overflow-tooltip prop="POST_NAME" label="岗位" />
|
||||
<el-table-column
|
||||
show-overflow-tooltip
|
||||
prop="CURRICULUMNAME"
|
||||
label="涉及课程"
|
||||
/>
|
||||
<el-table-column label="试卷类型" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ row.PAPERSELECTTYPE === "1" ? "平台试卷" : "" }}
|
||||
{{ row.PAPERSELECTTYPE === "2" ? "自动生成试卷" : "" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
link
|
||||
@click="fnView(row.STAGEEXAMPAPERINPUT_ID)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</layout-table>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<exam-paper-details
|
||||
v-model:visible="data.viewDialog.visible"
|
||||
:info="data.viewDialog.info"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { useRoute } from "vue-router";
|
||||
import useListData from "@/assets/js/useListData.js";
|
||||
import { getClassManagementExamPaperList } from "@/request/training_process_management.js";
|
||||
import { serialNumber } from "@/assets/js/utils.js";
|
||||
import {
|
||||
getExamPaperManagementTestQuestions,
|
||||
getExamPaperManagementView,
|
||||
} from "@/request/training_resource_management.js";
|
||||
import { reactive, watchEffect } from "vue";
|
||||
import ExamPaperDetails from "./exam_paper_details.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const { CLASS_ID } = route.query;
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible"]);
|
||||
const visible = useVModel(props, "visible", emits);
|
||||
const { list, pagination, fnGetData, fnResetPagination } = useListData(
|
||||
getClassManagementExamPaperList,
|
||||
{
|
||||
otherParams: { CLASS_ID },
|
||||
immediate: false,
|
||||
}
|
||||
);
|
||||
const data = reactive({
|
||||
viewDialog: {
|
||||
visible: false,
|
||||
info: {},
|
||||
},
|
||||
});
|
||||
watchEffect(() => {
|
||||
if (visible.value) fnResetPagination();
|
||||
});
|
||||
const fnView = async (STAGEEXAMPAPERINPUT_ID) => {
|
||||
const { pd } = await getExamPaperManagementView({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
});
|
||||
data.viewDialog.info = pd;
|
||||
const { varList } = await getExamPaperManagementTestQuestions({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
});
|
||||
data.viewDialog.info.testPaper = varList;
|
||||
data.viewDialog.visible = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -0,0 +1,222 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="涉及培训岗位" :on-close="fnClose">
|
||||
<el-form ref="formRef" :model="form" label-width="70px">
|
||||
<el-row class="mb-10">
|
||||
<el-col class="tr">
|
||||
<el-button v-if="!isEdit" type="primary" @click="fnAdd">
|
||||
添加
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-for="(item, index) in form.list" :key="item.id">
|
||||
<el-col :span="9">
|
||||
<el-form-item
|
||||
:prop="'list.' + index + '.DEPARTMENT_ID'"
|
||||
:label="'部门' + (index + 1)"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '部门不能为空',
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
:disabled="isEdit"
|
||||
:model-value="item.DEPARTMENT_ID"
|
||||
filterable
|
||||
@change="fnPostChange($event, index)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item1 in departmentList"
|
||||
:key="item1.DEPARTMENT_ID"
|
||||
:value="item1.DEPARTMENT_ID"
|
||||
:label="item1.NAME"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="9">
|
||||
<el-form-item
|
||||
:prop="'list.' + index + '.POST_ID'"
|
||||
:label="'岗位' + (index + 1)"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '岗位不能为空',
|
||||
trigger: 'change',
|
||||
}"
|
||||
>
|
||||
<el-select
|
||||
v-model="item.POST_ID"
|
||||
:disabled="isEdit"
|
||||
filterable
|
||||
multiple
|
||||
>
|
||||
<el-option
|
||||
v-for="item1 in item.postList"
|
||||
:key="item1.POST_ID"
|
||||
:value="item1.POST_ID"
|
||||
:label="item1.NAME"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="!isEdit" :span="6">
|
||||
<el-form-item label-width="10px">
|
||||
<el-button type="primary" @click="fnSelectAll(index)">
|
||||
岗位{{
|
||||
!form.list[index].DEPARTMENT_ID
|
||||
? "全选"
|
||||
: form.list[index].POST_ID.length !==
|
||||
form.list[index].postList.length
|
||||
? "全选"
|
||||
: "取消全选"
|
||||
}}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="index !== 0"
|
||||
type="danger"
|
||||
@click="form.list.splice(index, 1)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fnClose">关闭</el-button>
|
||||
<el-button v-if="!isEdit" type="primary" @click="fnSubmit">
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModels } from "@vueuse/core";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, watch } from "vue";
|
||||
import {
|
||||
getClassManagementInvolvedInTrainingDepartmentList,
|
||||
getClassManagementInvolvedInTrainingPostList,
|
||||
setClassManagementInvolvedInTrainingAdd,
|
||||
} from "@/request/training_process_management.js";
|
||||
import { verifyDuplicateSelection } from "@/assets/js/utils.js";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
|
||||
const route = useRoute();
|
||||
const { STATE, CLASS_ID } = route.query;
|
||||
const isEdit = STATE && STATE !== "1";
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible", "update:form", "get-data"]);
|
||||
const { visible, form } = useVModels(props, emits);
|
||||
const departmentList = ref([]);
|
||||
const formRef = ref(null);
|
||||
const fnAdd = () => {
|
||||
if (form.value.list.length >= departmentList.value.length) {
|
||||
ElMessage.warning("无法添加新的培训岗位");
|
||||
return;
|
||||
}
|
||||
form.value.list.push({
|
||||
id: Math.random(),
|
||||
DEPARTMENT_ID: "",
|
||||
POST_ID: [],
|
||||
postList: [],
|
||||
});
|
||||
};
|
||||
const getDepartmentList = async () => {
|
||||
const resData = await getClassManagementInvolvedInTrainingDepartmentList({
|
||||
CLASS_ID,
|
||||
});
|
||||
departmentList.value = resData.varList;
|
||||
};
|
||||
getDepartmentList();
|
||||
const fnPostChange = async (value, index) => {
|
||||
await verifyDuplicateSelection(
|
||||
form.value.list,
|
||||
index,
|
||||
"DEPARTMENT_ID",
|
||||
value
|
||||
);
|
||||
form.value.list[index].POST_ID = [];
|
||||
form.value.list[index].postList = [];
|
||||
await fnGetPostList(value, index);
|
||||
};
|
||||
const fnGetPostList = async (DEPARTMENT_ID, index) => {
|
||||
const resData = await getClassManagementInvolvedInTrainingPostList({
|
||||
DEPARTMENT_ID,
|
||||
CLASS_ID,
|
||||
});
|
||||
form.value.list[index].postList = resData.postList;
|
||||
};
|
||||
watch(
|
||||
() => visible.value,
|
||||
() => {
|
||||
if (visible.value) {
|
||||
if (form.value.list.length === 0) fnAdd();
|
||||
else {
|
||||
for (let i = 0; i < form.value.list.length; i++) {
|
||||
form.value.list[i].id = Math.random();
|
||||
form.value.list[i].postList = [];
|
||||
fnGetPostList(form.value.list[i].DEPARTMENT_ID, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
const fnSelectAll = (index) => {
|
||||
if (!form.value.list[index].DEPARTMENT_ID) {
|
||||
ElMessage.warning("请先选择部门");
|
||||
return;
|
||||
}
|
||||
if (form.value.list[index].postList.length === 0) {
|
||||
ElMessage.warning("当前部门下没有岗位");
|
||||
return;
|
||||
}
|
||||
if (
|
||||
form.value.list[index].POST_ID.length !==
|
||||
form.value.list[index].postList.length
|
||||
) {
|
||||
form.value.list[index].POST_ID = form.value.list[index].postList.map(
|
||||
(item) => item.POST_ID
|
||||
);
|
||||
} else form.value.list[index].POST_ID = [];
|
||||
};
|
||||
const fnClose = () => {
|
||||
formRef.value.resetFields();
|
||||
visible.value = false;
|
||||
};
|
||||
const fnSubmit = debounce(
|
||||
1000,
|
||||
async () => {
|
||||
await useFormValidate(formRef);
|
||||
await setClassManagementInvolvedInTrainingAdd({
|
||||
CLASSCURRICULUM_ID: props.id,
|
||||
deptPostList: JSON.stringify(form.value.list),
|
||||
});
|
||||
ElMessage.success("保存成功");
|
||||
fnClose();
|
||||
emits("get-data");
|
||||
},
|
||||
{ atBegin: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<el-dialog v-model="visible" title="试卷类型" :on-close="fnClose">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="试卷类型" prop="PAPERSELECTTYPE">
|
||||
<el-select v-model="form.PAPERSELECTTYPE">
|
||||
<el-option value="1" label="平台试卷" />
|
||||
<el-option value="2" label="自动生成试卷" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fnClose">关闭</el-button>
|
||||
<el-button type="primary" @click="fnSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useVModel } from "@vueuse/core";
|
||||
import { ref } from "vue";
|
||||
import useFormValidate from "@/assets/js/useFormValidate.js";
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
classPostId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
postPaperId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
curriculumIds: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(["update:visible"]);
|
||||
const visible = useVModel(props, "visible", emits);
|
||||
const formRef = ref(null);
|
||||
const form = ref({ PAPERSELECTTYPE: "" });
|
||||
const rules = {
|
||||
PAPERSELECTTYPE: {
|
||||
required: true,
|
||||
message: "请选择试卷类型",
|
||||
trigger: "change",
|
||||
},
|
||||
};
|
||||
const fnClose = () => {
|
||||
formRef.value.resetFields();
|
||||
visible.value = false;
|
||||
};
|
||||
const fnSubmit = async () => {
|
||||
await useFormValidate(formRef);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
|
@ -175,7 +175,6 @@
|
|||
CLASS_ID: row.CLASS_ID,
|
||||
EXAMINATION: row.EXAMINATION,
|
||||
ISSTRENGTHEN: row.ISSTRENGTHEN,
|
||||
TRAINTYPE: row.TRAINTYPE,
|
||||
type: row.STATE === '1' ? 'edit' : 'view',
|
||||
},
|
||||
})
|
||||
|
@ -195,7 +194,6 @@
|
|||
CLASS_ID: row.CLASS_ID,
|
||||
EXAMINATION: row.EXAMINATION,
|
||||
ISSTRENGTHEN: row.ISSTRENGTHEN,
|
||||
TRAINTYPE: row.TRAINTYPE,
|
||||
type: 'edit',
|
||||
},
|
||||
})
|
||||
|
@ -215,7 +213,6 @@
|
|||
CLASS_ID: row.CLASS_ID,
|
||||
EXAMINATION: row.EXAMINATION,
|
||||
ISSTRENGTHEN: row.ISSTRENGTHEN,
|
||||
TRAINTYPE: row.TRAINTYPE,
|
||||
type: 'edit',
|
||||
},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
<template>
|
||||
<layout-card>
|
||||
<el-divider content-position="left">课程基本信息</el-divider>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="课程名称">
|
||||
{{ data.info.CURRICULUMNAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="培训类型">
|
||||
{{ data.info.TYPENAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="课程描述">
|
||||
{{ data.info.CURRICULUMINTRODUCE }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="课程封面">
|
||||
<img
|
||||
v-viewer
|
||||
:src="VITE_FILE_URL + data.info.COVERPATH"
|
||||
alt=""
|
||||
width="100"
|
||||
height="100"
|
||||
/>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">总学时</el-divider>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="所选课件总学时">
|
||||
{{
|
||||
data.selectClassHour === 0
|
||||
? data.selectClassHour
|
||||
: data.selectClassHour.toFixed(1)
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所选课件视频总时长">
|
||||
{{ secondConversion(data.selectVideoTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="课程总学时">
|
||||
{{ data.info.CLASSHOUR }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="课程视频总时长">
|
||||
{{ secondConversion(data.info.VIDEOTIME) }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">课程目录</el-divider>
|
||||
<el-tree
|
||||
:data="data.chapterList"
|
||||
:props="{ children: 'nodes', label: 'COURSEWARENAME' }"
|
||||
class="directory_style"
|
||||
default-expand-all
|
||||
>
|
||||
<template #default="{ data: item }">
|
||||
<div class="directory_row">
|
||||
<el-icon
|
||||
v-if="item.COURSEWARENAME"
|
||||
class="el-icon-video-camera"
|
||||
size="18"
|
||||
>
|
||||
<video-camera />
|
||||
</el-icon>
|
||||
<span class="directory_name line-1">
|
||||
{{ item.NAME || item.COURSEWARENAME }}
|
||||
</span>
|
||||
<span v-if="item.COURSEWARENAME" class="directory_type">
|
||||
课件时长:{{ secondConversion(item.VIDEOTIME) }}
|
||||
</span>
|
||||
<el-button
|
||||
v-if="item.COURSEWARENAME"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="fnPreview(item)"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
<layout-video
|
||||
v-model:visible="data.videoDialog.visible"
|
||||
:src="data.videoDialog.src"
|
||||
/>
|
||||
</layout-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRoute } from "vue-router";
|
||||
import { getPreviewingVideo } from "@/request/training_resource_management.js";
|
||||
import { reactive } from "vue";
|
||||
import { secondConversion } from "@/assets/js/utils.js";
|
||||
import { VideoCamera } from "@element-plus/icons-vue";
|
||||
import LayoutVideo from "@/components/video/index.vue";
|
||||
import { getClassManagementCurriculumView } from "@/request/training_process_management.js";
|
||||
|
||||
const route = useRoute();
|
||||
const { CLASSCURRICULUM_ID } = route.query;
|
||||
const VITE_FILE_URL = import.meta.env.VITE_FILE_URL;
|
||||
const data = reactive({
|
||||
info: {},
|
||||
chapterList: [],
|
||||
selectClassHour: 0,
|
||||
selectVideoTime: 0,
|
||||
videoDialog: {
|
||||
visible: false,
|
||||
src: "",
|
||||
},
|
||||
});
|
||||
const fnGetData = async () => {
|
||||
const resData = await getClassManagementCurriculumView({
|
||||
CLASSCURRICULUM_ID,
|
||||
});
|
||||
data.info = resData.pd;
|
||||
data.chapterList = resData.chapterList;
|
||||
fnSumSelectTime(data.chapterList);
|
||||
};
|
||||
fnGetData();
|
||||
const fnSumSelectTime = (list) => {
|
||||
list.forEach((item) => {
|
||||
data.selectClassHour += Number(item.CLASSHOUR || 0);
|
||||
data.selectVideoTime += Number(item.VIDEOTIME || 0);
|
||||
if (item.nodes && item.nodes.length > 0) {
|
||||
fnSumSelectTime(item.nodes);
|
||||
}
|
||||
});
|
||||
};
|
||||
const fnPreview = async ({ VIDEOCOURSEWARE_ID, VIDEOFILES, CURRICULUM_ID }) => {
|
||||
const resData = await getPreviewingVideo({
|
||||
VIDEOCOURSEWARE_ID,
|
||||
VIDEOFILES,
|
||||
CURRICULUM_ID,
|
||||
});
|
||||
data.videoDialog.src = JSON.stringify(resData.urlList);
|
||||
data.videoDialog.visible = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.directory_style {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.el-icon-video-camera {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.directory_row {
|
||||
flex-basis: 600px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
|
||||
.directory_name {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.directory_type {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep {
|
||||
.el-tree-node__content {
|
||||
margin-bottom: 10px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -112,28 +112,28 @@
|
|||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio label="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio label="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio value="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio value="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group
|
||||
v-if="item.QUESTIONTYPE === '2'"
|
||||
disabled
|
||||
:model-value="item.ANSWER?.split('')"
|
||||
>
|
||||
<el-checkbox label="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox label="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox label="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox label="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
<el-checkbox value="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox value="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox value="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox value="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '3'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="flex">
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
>
|
||||
<video-camera />
|
||||
</el-icon>
|
||||
<span class="directory_name">
|
||||
<span class="directory_name line-1">
|
||||
{{ item.NAME || item.COURSEWARENAME }}
|
||||
</span>
|
||||
<span v-if="item.COURSEWARENAME" class="directory_type">
|
||||
|
@ -106,28 +106,26 @@ const fnPreview = async (VIDEOCOURSEWARE_ID, VIDEOFILES) => {
|
|||
margin-bottom: 20px;
|
||||
|
||||
.el-icon-video-camera {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.directory_row {
|
||||
flex-basis: 600px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
|
||||
.directory_name {
|
||||
width: 260px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.directory_type {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep {
|
||||
.el-tree-node__content {
|
||||
margin-bottom: 10px;
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<template>
|
||||
<el-divider content-position="left">试卷基本信息</el-divider>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="试卷名称" :span="2">
|
||||
{{ info.EXAMNAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合格分数">
|
||||
{{ info.PASSSCORE }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总分数">
|
||||
{{ info.EXAMSCORE }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">试卷题目信息</el-divider>
|
||||
<div class="items mt-20 p-20">
|
||||
<div
|
||||
v-for="(item, index) in info.testPaper"
|
||||
:key="item.PAPER_QUESTION_ID"
|
||||
class="item ptb-20"
|
||||
>
|
||||
<div class="mt-10">
|
||||
{{ index + 1 }}.
|
||||
<span v-if="item.QUESTIONTYPE === '1'"> (单选题) </span>
|
||||
<span v-if="item.QUESTIONTYPE === '2'"> (多选题) </span>
|
||||
<span v-if="item.QUESTIONTYPE === '3'"> (判断题) </span>
|
||||
{{ item.QUESTIONDRY }}
|
||||
<span class="ml-10">(题目分值:{{ item.SCORE }})</span>
|
||||
</div>
|
||||
<div class="mt-10 ml-30">
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '1'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio value="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio value="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group
|
||||
v-if="item.QUESTIONTYPE === '2'"
|
||||
disabled
|
||||
:model-value="item.ANSWER?.split('')"
|
||||
>
|
||||
<el-checkbox value="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox value="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox value="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox value="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '3'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio value="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio value="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="mt-10">答案:{{ item.ANSWER }}</div>
|
||||
<div class="mt-10">答案解析:{{ item.DESCR }}</div>
|
||||
<div class="mt-10">关联课件名称:{{ item.COURSEWARENAME }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
info: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.items {
|
||||
border: 1px solid var(--el-border-color);
|
||||
|
||||
.item {
|
||||
border-bottom: 1px dashed #ebeef5;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,67 +1,6 @@
|
|||
<template>
|
||||
<layout-card>
|
||||
<el-divider content-position="left">试卷基本信息</el-divider>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="试卷名称" :span="2">
|
||||
{{ info.EXAMNAME }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合格分数">
|
||||
{{ info.PASSSCORE }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总分数">
|
||||
{{ info.EXAMSCORE }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">试卷题目信息</el-divider>
|
||||
<div class="items mt-20 p-20">
|
||||
<div
|
||||
v-for="(item, index) in testPaper"
|
||||
:key="item.PAPER_QUESTION_ID"
|
||||
class="item ptb-20"
|
||||
>
|
||||
<div class="mt-10">
|
||||
{{ index + 1 }}.
|
||||
<span v-if="item.QUESTIONTYPE === '1'"> (单选题) </span>
|
||||
<span v-if="item.QUESTIONTYPE === '2'"> (多选题) </span>
|
||||
<span v-if="item.QUESTIONTYPE === '3'"> (判断题) </span>
|
||||
{{ item.QUESTIONDRY }}
|
||||
<span class="ml-10">(题目分值:{{ item.SCORE }})</span>
|
||||
</div>
|
||||
<div class="mt-10 ml-30">
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '1'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
<el-radio label="C">C.{{ item.OPTIONC }}</el-radio>
|
||||
<el-radio label="D">D.{{ item.OPTIOND }}</el-radio>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group
|
||||
v-if="item.QUESTIONTYPE === '2'"
|
||||
disabled
|
||||
:model-value="item.ANSWER?.split('')"
|
||||
>
|
||||
<el-checkbox label="A">A.{{ item.OPTIONA }}</el-checkbox>
|
||||
<el-checkbox label="B">B.{{ item.OPTIONB }}</el-checkbox>
|
||||
<el-checkbox label="C">C.{{ item.OPTIONC }}</el-checkbox>
|
||||
<el-checkbox label="D">D.{{ item.OPTIOND }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-radio-group
|
||||
v-if="item.QUESTIONTYPE === '3'"
|
||||
disabled
|
||||
:model-value="item.ANSWER"
|
||||
>
|
||||
<el-radio label="A">A.{{ item.OPTIONA }}</el-radio>
|
||||
<el-radio label="B">B.{{ item.OPTIONB }}</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="mt-10">答案:{{ item.ANSWER }}</div>
|
||||
<div class="mt-10">答案解析:{{ item.DESCR }}</div>
|
||||
<div class="mt-10">关联课件名称:{{ item.COURSEWARENAME }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<view-info :info="info" />
|
||||
</layout-card>
|
||||
</template>
|
||||
|
||||
|
@ -72,11 +11,11 @@ import {
|
|||
getExamPaperManagementView,
|
||||
} from "@/request/training_resource_management.js";
|
||||
import { useRoute } from "vue-router";
|
||||
import ViewInfo from "./components/view.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const { STAGEEXAMPAPERINPUT_ID } = route.query;
|
||||
const info = ref({});
|
||||
const testPaper = ref([]);
|
||||
const fnGetData = async () => {
|
||||
const { pd } = await getExamPaperManagementView({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
|
@ -85,25 +24,9 @@ const fnGetData = async () => {
|
|||
const { varList } = await getExamPaperManagementTestQuestions({
|
||||
STAGEEXAMPAPERINPUT_ID,
|
||||
});
|
||||
testPaper.value = varList;
|
||||
info.value.testPaper = varList;
|
||||
};
|
||||
fnGetData();
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.items {
|
||||
border: 1px solid var(--el-border-color);
|
||||
|
||||
.item {
|
||||
border-bottom: 1px dashed #ebeef5;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
Loading…
Reference in New Issue