<template> <section class="content add-paper-select"> <div> <LinkTitlesCustom :current-paths="['题库管理 ', '卷库管理', '抽题模板管理']" /> </div> <div class="box-body"> <div class="top"> <div class="flex items-center"> <p>课程名称:{{ $route.query.courseName }}</p> <p style="margin-left: 100px"> 课程代码:{{ $route.query.courseNo }} </p> </div> <el-button type="primary" size="small" @click="save">保存</el-button> </div> <div class="form"> <el-form ref="form" :rules="rules" :model="form" label-position="left" label-width="120px" > <el-form-item label="组卷模板名称:" prop="name"> <el-input v-model="form.name" style="width: 300px"></el-input> </el-form-item> <el-form-item label="选择组卷模式:" required> <el-radio-group v-model="form.paperStructType" @change="paperStructTypeChange" > <el-radio label="EXACT">精确结构</el-radio> <el-radio label="BLUEPRINT">蓝图结构</el-radio> </el-radio-group> </el-form-item> <el-form-item label="选择组卷结构:" prop="paperStructId"> <el-select v-model="form.paperStructId"> <el-option v-for="item in options1" :key="item.id" :label="item.name" :value="item.id" ></el-option> </el-select> <p style="display: inline-block; margin-left: 40px"> 难度:<span style="color: #409eff; font-weight: bold">{{ curStruct?.difficulty }}</span> </p> </el-form-item> <el-table v-loading="tableLoading1" :data="tableData1" border style="margin-top: 10px; margin-bottom: 20px; width: 700px" > <el-table-column v-for="(item, index) in tableColumns1" :key="index" :label="item.label" :prop="item.prop" :min-width="item.minWidth" > <template slot-scope="scope"> <span v-if=" !['hardInfo', 'mediumInfo', 'easyInfo'].includes(item.prop) " >{{ scope.row[item.prop] }}</span > <span v-else>{{ scope.row[item.prop]?.count }}</span> </template> </el-table-column> </el-table> <div class="flex" style="margin-top: 30px"> <div style="width: 40%"> <el-form-item label="选择题源范围:" style="margin-bottom: 0"> <el-select v-model="form.paperType" placeholder="题源选择" style="width: 120px" @change="changePaperType" > <el-option label="题库来源" value="IMPORT"></el-option> <el-option label="卷库来源" value="GENERATE"></el-option> </el-select> <span v-if="checked && !multipleSelection.length" class="red" style="font-size: 12px; font-weight: bold; margin-left: 10px" >请选择数据</span > </el-form-item> <el-table ref="table2" :data="tableData2" border @selection-change="handleSelectionChange" > <el-table-column type="selection" width="55" :selectable="canSelect" > </el-table-column> <el-table-column v-for="(item, index) in tableColumns2" :key="index" :label="item.label" :prop="item.prop" :width="item.width" > </el-table-column> </el-table> </div> <div style="width: 60%; padding-left: 20px"> <div style="color: #606266; font-size: 14px; line-height: 32px"> <span>选中范围预览:</span> <span v-if="hasError()" class="red" style="font-size: 12px; font-weight: bold" >不满足最低要求</span > </div> <el-table v-loading="tableLoading3" :data="tableData3" border style="margin-top: 8px" > <el-table-column v-for="(item, index) in tableColumns3" :key="index" :label="item.label" :prop="item.prop" > <template slot-scope="scope"> <span v-if=" !['hardInfo', 'mediumInfo', 'easyInfo'].includes( item.prop ) " :class="{ red: hasNumError(scope.row, item.prop) }" >{{ scope.row[item.prop] }}</span > <span v-else :class="{ red: hasNumError(scope.row, item.prop) }" >{{ scope.row[item.prop]?.count }}</span > </template> </el-table-column> </el-table> </div> </div> </el-form> </div> </div> </section> </template> <script> import qs from "qs"; import { mapState } from "vuex"; export default { data() { return { form: { paperStructType: "BLUEPRINT", name: "", paperStructId: "", paperType: "IMPORT", paperIds: "", }, paperIdsArr: [], options1: [], tableData1: [], tableColumns1: [ { label: "题型", prop: "detailName", minWidth: "100" }, { label: "总分", prop: "totalScore", minWidth: "80" }, { label: "数量", prop: "totalCount", minWidth: "80" }, { label: "难", prop: "hardInfo", minWidth: "80" }, { label: "中", prop: "mediumInfo", minWidth: "80" }, { label: "易", prop: "easyInfo", minWidth: "80" }, ], tableData2: [], tableColumns2: [ { label: "名称", prop: "name" }, { label: "小题数量", prop: "unitCount", width: "100px" }, ], multipleSelection: [], tableData3: [], tableColumns3: [ { label: "题型", prop: "detailName", minWidth: "100" }, { label: "数量", prop: "totalCount", minWidth: "80" }, { label: "难", prop: "hardInfo", minWidth: "80" }, { label: "中", prop: "mediumInfo", minWidth: "80" }, { label: "易", prop: "easyInfo", minWidth: "80" }, ], lastRequestKey: "", tableLoading3: false, tableLoading1: false, checked: false, initSelectedRows: [], }; }, computed: { ...mapState({ user: (state) => state.user }), curStruct() { if (this.form.paperStructId) { return this.options1.find( (item) => item.id === this.form.paperStructId ); } else { return {}; } }, rules() { return { name: { required: true, message: "请输入模板名称", trigger: "change" }, paperStructId: { required: true, message: "请选择组卷结构", trigger: "change", }, }; }, }, watch: { "form.paperStructId"() { this.structChange(); }, // "form.paperStructType"() { // this.form.paperStructId = ""; // this.getStruct(); // this.tableData1 = []; // this.$refs.table2.clearSelection(); // }, multipleSelection(val) { this.form.paperIds = val.map((item) => item.id).join(","); }, }, async created() { let res = await this.getTplData(); if (res) { this.getStruct(); this.getTable2(true); } }, methods: { paperStructTypeChange() { this.form.paperStructId = ""; this.getStruct(); this.tableData1 = []; this.$refs.table2.clearSelection(); }, async getTplData() { const { id } = this.$route.params; if (id) { try { const data = await this.$http.post( "/api/ecs_ques/randompaper/info", null, { params: { id, }, } ); const tplData = data.data; this.paperIdsArr = tplData.paperIds || []; Object.assign(this.form, tplData || {}, { paperIds: (tplData.paperIds || []).join(","), }); return true; } catch (e) { return false; } } else { return true; } }, save() { this.checked = true; this.$refs.form.validate((valid) => { if (valid) { if (this.multipleSelection.length && !this.hasError()) { let params = { courseId: this.$route.query.courseId, ...this.form, rootOrgId: this.user.rootOrgId, }; if (this.$route.params.id) { params.id = this.$route.params.id; } this.$http .post("/api/ecs_ques/randompaper/save", qs.stringify(params)) .then(() => { this.$message.success("保存成功"); this.$router.back(); }); } } else { console.log("error submit!!"); return false; } }); }, canSelect() { return !!this.form.paperStructId; }, structChange() { this.tableLoading1 = true; this.$http .post("/api/ecs_ques/randompaper/struct/question/info", null, { params: { structId: this.form.paperStructId }, headers: { "content-type": "application/x-www-form-urlencoded" }, }) .then((res) => { this.tableData1 = res.data.structQuestionInfo || []; this.tableLoading1 = false; }); }, getStruct() { let apiUrl = "/api/ecs_ques/paperStruct/1/10000"; let params = this.form.paperStructType == "EXACT" ? { courseNo: "ALL", type: "EXACT" } : { type: "BLUEPRINT" }; this.$http.get(apiUrl, { params }).then((res) => { this.options1 = res.data.content; }); }, getTable2(bool) { let apiUrl = this.form.paperType === "IMPORT" ? "/api/ecs_ques/importPaper/huoge/1/10000" : "/api/ecs_ques/genPaper/huoge/1/10000"; this.$http .get(apiUrl, { params: { courseNo: this.$route.query.courseNo, ids: "" }, }) .then((res) => { this.tableData2 = res.data.content || []; if (bool) { this.tableData2.forEach((item) => { if (this.paperIdsArr.includes(item.id)) { this.initSelectedRows.push(item); } }); setTimeout(() => { this.initSelectedRows.forEach((item) => { this.$refs.table2.toggleRowSelection(item, true); }); }, 0); } }); }, changePaperType() { this.tableData2 = []; this.multipleSelection = []; this.getTable2(); }, getTable3() { let paperIds = this.multipleSelection.map((item) => item.id); if (!paperIds.length) { this.tableData3 = []; this.tableLoading3 = false; return false; } this.tableLoading3 = true; let str = new Date().getTime() + ""; this.lastRequestKey = str; this.$http .post( "/api/ecs_ques/randompaper/struct/question/view/info", qs.stringify({ paperIds: paperIds.join(","), structId: this.form.paperStructId, }), { headers: { "content-type": "application/x-www-form-urlencoded" }, } ) .then((res) => { if (this.lastRequestKey === str) { this.tableData3 = res.data.structQuestionInfo || []; this.tableLoading3 = false; } }); }, handleSelectionChange(val) { this.multipleSelection = val; this.getTable3(); }, hasNumError(row, prop) { if (prop === "detailName") { return false; } else { let targetName = row.detailName; let find = this.tableData1.find( (item) => item.detailName === targetName ); if (!find) { return false; } else { if (prop === "totalCount") { return row[prop] < find[prop]; } else { return row[prop].count < find[prop].count; } } } }, hasError() { return ( this.tableData1.length && this.tableData3.length && this.tableData3.every((item) => { return ( this.hasNumError(item, "totalCount") || this.hasNumError(item, "hardInfo") || this.hasNumError(item, "mediumInfo") || this.hasNumError(item, "easyInfo") ); }) ); }, }, }; </script> <style lang="scss" scoped> .add-paper-select { * { box-sizing: border-box; } .el-form .el-form-item { margin-bottom: 18px; } ::v-deep .red { color: #f56c6c; } p { margin: 0; } .top { display: flex; align-items: center; justify-content: space-between; padding-bottom: 15px; border-bottom: 1px solid #eee; p { font-size: 14px; } } .box-body { background-color: #fff; border-radius: 6px; padding: 15px 10px; .form { margin-top: 15px; } } } </style>