<template> <section class="org-property"> <div class="org-header"> <div class="part-box-header"> <h1 class="part-box-title">{{ rootOrgName }}</h1> <div> <el-button type="primary" @click="save">保存</el-button> <el-button type="danger" plain @click="back">返回</el-button> </div> </div> <div class="part-tabs"> <div v-for="menu in menus" :key="menu.val" :class="['part-tabs-item', { 'is-active': activeName === menu.val }]" @click="activeName = menu.val" > <div class="part-tabs-name"> {{ menu.name }} </div> </div> </div> </div> <div class="org-body part-box"> <!-- 题型设置 --> <!-- <el-form v-if="activeName === 'tab1'" label-width="160px"> <h3 class="org-body-title">可用题型</h3> <el-form-item label="基础题型" prop="properties.ROOT_ORG_QUESTION_TYPES1" > <el-checkbox-group v-model="form.properties.ROOT_ORG_QUESTION_TYPES1"> <el-checkbox label="SINGLE_ANSWER_QUESTION" class="checkbox_length" >单选</el-checkbox > <el-checkbox label="MULTIPLE_ANSWER_QUESTION" class="checkbox_length" >多选</el-checkbox > <el-checkbox label="BOOL_ANSWER_QUESTION" class="checkbox_length" >判断</el-checkbox > <el-checkbox label="FILL_BLANK_QUESTION" class="checkbox_length" >填空</el-checkbox > <el-checkbox label="TEXT_ANSWER_QUESTION" class="checkbox_length" >问答</el-checkbox > </el-checkbox-group> </el-form-item> <el-form-item label="组合题型" prop="properties.ROOT_ORG_QUESTION_TYPES2" > <el-checkbox-group v-model="form.properties.ROOT_ORG_QUESTION_TYPES2"> <el-checkbox label="READING_COMPREHENSION" class="checkbox_length" >阅读理解</el-checkbox > <el-checkbox label="CLOZE" class="checkbox_length" >完形填空</el-checkbox > <el-checkbox label="PARAGRAPH_MATCHING" class="checkbox_length" >段落匹配</el-checkbox > <el-checkbox label="BANKED_CLOZE" class="checkbox_length" >选词填空</el-checkbox > </el-checkbox-group> </el-form-item> <el-form-item label="特殊题型" prop="properties.ROOT_ORG_QUESTION_TYPES3" > <el-checkbox-group v-model="form.properties.ROOT_ORG_QUESTION_TYPES3"> <el-checkbox label="LISTENING_QUESTION" class="checkbox_length" >听力</el-checkbox > </el-checkbox-group> </el-form-item> <h3 class="org-body-title">成卷配置</h3> <el-form-item label="特殊设置"> <el-checkbox-group v-model="form.properties.QUESTION_TYPE_SPECIAL_SET" class="pull_length" > <el-checkbox label="AUTONOMY_QUESTION" class="checkbox_length" >选做题设置</el-checkbox > </el-checkbox-group> </el-form-item> </el-form> --> <!-- 审核配置 --> <el-form v-if="activeName === 'tab2'" label-width="160px"> <el-form-item class="label-title" label="题库审核" label-width="90px"> <el-radio-group v-model="form.properties.PAPER_AUDIT"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group> </el-form-item> <template v-if="form.properties.PAPER_AUDIT == 'true'"> <el-form-item label="初级审核"> <el-radio-group v-model="form.properties.PAPER_FIRST_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> <el-form-item label="中级审核"> <el-radio-group v-model="form.properties.PAPER_SECOND_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> <el-form-item label="高级审核"> <el-radio-group v-model="form.properties.PAPER_THIRD_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> </template> <el-form-item class="label-title" label="卷库审核" label-width="90px"> <el-radio-group v-model="form.properties.EXAM_PAPER_AUDIT"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group> </el-form-item> <template v-if="form.properties.EXAM_PAPER_AUDIT == 'true'"> <el-form-item label="初级审核"> <el-radio-group v-model="form.properties.EXAM_PAPER_FIRST_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> <el-form-item label="中级审核"> <el-radio-group v-model="form.properties.EXAM_PAPER_SECOND_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> <el-form-item label="高级审核"> <el-radio-group v-model="form.properties.EXAM_PAPER_THIRD_AUDIT"> <el-radio label="true">正常流程</el-radio> <el-radio label="false">免审流程</el-radio> </el-radio-group> </el-form-item> </template> </el-form> <!-- 查重配置 --> <el-form v-if="activeName === 'tab3'" label-width="120px"> <el-form-item label="选项查重"> <el-radio-group v-model="form.properties.CHECK_OPTION_DUPLICATE_THRESHOLD" > <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group></el-form-item > <template v-if="form.properties.CHECK_OPTION_DUPLICATE_THRESHOLD == 'true'" > <el-form-item label="选项重复阀值"> <el-input-number v-model="form.properties.OPTION_DUPLICATE_THRESHOLD" :precision="1" :min="0" :max="100" ></el-input-number> <span class="tips-info margin-left-10" >*大于等于所设阈值,判定为重复</span > </el-form-item> </template> <el-form-item label="试题查重"> <el-radio-group v-model="form.properties.CHECK_DUPLICATE"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group></el-form-item > <template v-if="form.properties.CHECK_DUPLICATE == 'true'"> <el-form-item label="试题重复阀值"> <el-input-number v-model="form.properties.CHECK_DUPLICATE_THRESHOLD" :precision="1" :min="0" :max="100" ></el-input-number> <span class="tips-info margin-left-10" >*大于等于所设阈值,判定为重复</span > </el-form-item> <el-form-item label="试题陈列数量"> <el-input-number v-model="form.properties.CHECK_DUPLICATE_COUNT" :precision="0" :min="1" :max="10" ></el-input-number> <span class="tips-info margin-left-10" >*选取超过阈值的试题在查重页面显示</span > </el-form-item> <el-form-item label="试题字数数量"> <el-input-number v-model="form.properties.CHECK_LIMIT_CHAR_COUNT" :precision="0" :min="0" :max="1000" ></el-input-number> <span class="tips-info margin-left-10" >*低于所设字数,不进行查重计算</span > </el-form-item> </template> </el-form> <!-- 组卷配置 --> <!-- <el-form v-if="activeName === 'tab4'" label-width="120px"> <el-form-item label="综合组卷"> <el-radio-group v-model="form.properties.PAPER_BUILD_SYNTHESIS"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group> <div class="tips-info"> *开启跨课程组卷模式,支持将多个课程试题组到一份试卷下 </div> </el-form-item> </el-form> --> <div v-show="activeName === 'tab4'"> <el-form label-width="60px" inline> <el-form-item label="角色"> <el-select v-model="roleCode" placeholder="请选择"> <el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.code" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="searchTree"> 查询 </el-button> </el-form-item> </el-form> <div class="part-box tree-box"> <el-tree ref="authTree" :data="treeData" show-checkbox node-key="code" :props="defaultTreeProps" @check-change="treeCheckChange" @check="tab4Entered = true" default-expand-all :filter-node-method="filterTree" > <span class="custom-tree-node" slot-scope="{ node, data }"> <span>{{ node.label }}</span> <span v-if="data.privilegeType == 'BUTTON'" class="is-btn"> 按钮 </span> </span> </el-tree> </div> </div> <!-- AI命题 --> <el-form v-if="activeName === 'tab5'" size="small" label-width="120px"> <el-form-item label="AI命题"> <el-radio-group v-model="form.properties.USE_AI_QUESTION"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group></el-form-item > <el-form-item label="剩余题数"> {{ leftCount }} </el-form-item> <!-- <el-form-item label="累计出题数"> {{ permitCount }} </el-form-item> --> <el-form-item label=""> <el-button type="primary" @click="updateAiNums">更新数量</el-button> </el-form-item> <!-- <el-form-item label="购买出题数据包"> <el-radio-group v-model="trade"> <el-radio-button v-for="item in tradeOptions" :key="item" :label="item" >{{ item + "道" }}</el-radio-button > </el-radio-group> <el-button type="primary" class="margin-left-10" :disabled="!trade" :loading="loading" @click="toBuy" >购买</el-button > </el-form-item> <el-form-item label="剩余出题数量">{{ form.properties.AI_QUESTION_REMAINDER }}</el-form-item> <el-form-item label="已购记录"> <el-table :data="tradeList" border class="trade-table"> <el-table-column type="index" label="序号" width="70" /> <el-table-column prop="questionCount" label="购买出题数量" /> <el-table-column prop="creationTime" width="170" label="购买时间" /> </el-table> </el-form-item> --> </el-form> <el-form v-if="activeName === 'tab6'" size="small" label-width="120px"> <el-form-item label="组卷配置"> <el-radio-group v-model="form.properties.GEN_PAPER_QUESTION_ENABLE"> <el-radio label="true">开启</el-radio> <el-radio label="false">关闭</el-radio> </el-radio-group> (开启后,则必须在指定时间段内该课程新增试题数量满足条件才允许组卷,否则提示试题数量不够不允许组卷) </el-form-item> <template v-if="form.properties.GEN_PAPER_QUESTION_ENABLE == 'true'"> <el-form-item label="试题创建时间"> <el-date-picker v-model="timeRange" type="daterange" range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" value-format="yyyy-MM-dd" align="right" unlink-panels > </el-date-picker> </el-form-item> <el-form-item label="新增试题数量"> <!-- <el-input-number style="width: 80px" v-model="form.properties.GEN_PAPER_QUESTION_COUNT" :step="1" :controls="false" ></el-input-number> --> <el-input style="width: 80px" maxLength="7" v-model="form.properties.GEN_PAPER_QUESTION_COUNT" ></el-input> </el-form-item> </template> </el-form> </div> </section> </template> <script> import { mapState } from "vuex"; import { QUESTION_API } from "@/constants/constants.js"; import { orgAiTransactionSaveApi, orgAiTransactionListApi } from "../api"; import { getAiNums, updateAiNums } from "../../question/api"; export default { name: "OrgProperty", data() { return { leftCount: "", permitCount: "", tab4Entered: false, treeCheckedCodes: [], style: { label_width_tab1: "120px", label_width_tab2: "120px", label_width_tab3: "120px", }, menus: [ // { // name: "题型设置", // val: "tab1", // }, { name: "审核配置", val: "tab2", }, { name: "查重配置", val: "tab3", }, // { // name: "组卷配置", // val: "tab4", // }, { name: "角色管理", val: "tab4", }, { name: "AI命题", val: "tab5", }, { name: "组卷配置", val: "tab6" }, ], activeName: "tab2", rootOrgName: "", form: { orgId: null, properties: { // ROOT_ORG_QUESTION_TYPES: [], // ROOT_ORG_QUESTION_TYPES1: [], // ROOT_ORG_QUESTION_TYPES2: [], // ROOT_ORG_QUESTION_TYPES3: [], // QUESTION_TYPE_SPECIAL_SET: [], PAPER_AUDIT: "false", PAPER_FIRST_AUDIT: "false", PAPER_SECOND_AUDIT: "false", PAPER_THIRD_AUDIT: "false", EXAM_PAPER_AUDIT: "false", EXAM_PAPER_FIRST_AUDIT: "false", EXAM_PAPER_SECOND_AUDIT: "false", EXAM_PAPER_THIRD_AUDIT: "false", CHECK_DUPLICATE: "false", CHECK_OPTION_DUPLICATE_THRESHOLD: "false", CHECK_DUPLICATE_THRESHOLD: 80, OPTION_DUPLICATE_THRESHOLD: 94, CHECK_LIMIT_CHAR_COUNT: 0, CHECK_DUPLICATE_COUNT: 5, // 综合组卷 // PAPER_BUILD_SYNTHESIS: "false", // AI命题 AI_QUESTION_REMAINDER: 0, USE_AI_QUESTION: "false", GEN_PAPER_QUESTION_ENABLE: "true", GEN_PAPER_QUESTION_COUNT: "", GEN_PAPER_QUESTION_START: "", GEN_PAPER_QUESTION_END: "", }, }, timeRange: [], roleCode: "", roleList: [], rules: { // code: [{ required: true, validator: validateCode, trigger: "blur" }], }, // AI命题 trade: 10000, tradeOptions: [10000, 20000, 50000], tradeList: [], loading: false, defaultTreeProps: { label: "name", children: "subRolePrivilege", }, treeData: [], }; }, computed: { ...mapState({ user: (state) => state.user }), }, created() { this.form.orgId = this.$route.query.rootOrgId; this.rootOrgName = this.$route.query.rootOrgName + "(" + this.$route.query.rootOrgCode + ")"; if (!this.form.orgId) { this.form.orgId = sessionStorage.getItem("org_prop_info_org_id"); this.rootOrgName = sessionStorage.getItem("org_prop_info_org_name"); } else { sessionStorage.setItem("org_prop_info_org_id", this.form.orgId); sessionStorage.setItem("org_prop_info_org_name", this.rootOrgName); } this.init(); this.getTradeList(); this.initAiNums(); }, mounted() { setTimeout(() => { this.$store.commit("UPDATE_CURRENT_PATHS", [ "系统管理", "顶级机构管理", "机构设置", ]); }, 200); }, methods: { initAiNums(msg) { getAiNums({ rootOrgId: this.$route.query.rootOrgId, }).then((res) => { if (res.data) { this.leftCount = res.data?.leftCount; this.permitCount = res.data?.permitCount; if (msg) { this.$message.success(msg); } } }); }, updateAiNums() { updateAiNums({ rootOrgId: this.$route.query.rootOrgId, }).then(() => { this.initAiNums("更新成功"); }); }, init() { var url = QUESTION_API + "/org/allProperties/" + this.form.orgId; this.$httpWithMsg.get(url).then((response) => { if (response.data) { // if (response.data.ROOT_ORG_QUESTION_TYPES1) { // this.form.properties.ROOT_ORG_QUESTION_TYPES1 = JSON.parse( // response.data.ROOT_ORG_QUESTION_TYPES1 // ); // } // if (response.data.ROOT_ORG_QUESTION_TYPES2) { // this.form.properties.ROOT_ORG_QUESTION_TYPES2 = JSON.parse( // response.data.ROOT_ORG_QUESTION_TYPES2 // ); // } // if (response.data.ROOT_ORG_QUESTION_TYPES3) { // this.form.properties.ROOT_ORG_QUESTION_TYPES3 = JSON.parse( // response.data.ROOT_ORG_QUESTION_TYPES3 // ); // } // if (response.data.QUESTION_TYPE_SPECIAL_SET) { // this.form.properties.QUESTION_TYPE_SPECIAL_SET = JSON.parse( // response.data.QUESTION_TYPE_SPECIAL_SET // ); // } this.form.properties = this.$objAssign( this.form.properties, response.data ); this.timeRange = [ response.data.GEN_PAPER_QUESTION_START || "", response.data.GEN_PAPER_QUESTION_END || "", ]; } }); }, getRoleList() { this.$httpWithMsg .post(QUESTION_API + "/rolePrivilege/getRoles") .then((res) => { this.roleList = res.data; if (res.data?.length) { this.roleCode = res.data[0].code; } }); }, searchTree() {}, setParams() { for (let i of this.form.properties.ROOT_ORG_QUESTION_TYPES1) { this.form.properties.ROOT_ORG_QUESTION_TYPES.push(i); } for (let i of this.form.properties.ROOT_ORG_QUESTION_TYPES2) { this.form.properties.ROOT_ORG_QUESTION_TYPES.push(i); } for (let i of this.form.properties.ROOT_ORG_QUESTION_TYPES3) { this.form.properties.ROOT_ORG_QUESTION_TYPES.push(i); } this.form.properties.ROOT_ORG_QUESTION_TYPES = JSON.stringify( this.form.properties.ROOT_ORG_QUESTION_TYPES ); if (this.form.properties.ROOT_ORG_QUESTION_TYPES1) { this.form.properties.ROOT_ORG_QUESTION_TYPES1 = JSON.stringify( this.form.properties.ROOT_ORG_QUESTION_TYPES1 ); } if (this.form.properties.ROOT_ORG_QUESTION_TYPES2) { this.form.properties.ROOT_ORG_QUESTION_TYPES2 = JSON.stringify( this.form.properties.ROOT_ORG_QUESTION_TYPES2 ); } if (this.form.properties.ROOT_ORG_QUESTION_TYPES3) { this.form.properties.ROOT_ORG_QUESTION_TYPES3 = JSON.stringify( this.form.properties.ROOT_ORG_QUESTION_TYPES3 ); } if (this.form.properties.QUESTION_TYPE_SPECIAL_SET) { this.form.properties.QUESTION_TYPE_SPECIAL_SET = JSON.stringify( this.form.properties.QUESTION_TYPE_SPECIAL_SET ); } }, async save() { // this.setParams(); let url = QUESTION_API + "/org/saveOrgProperties"; if (this.form.properties.GEN_PAPER_QUESTION_ENABLE == "false") { this.timeRange = []; this.form.properties.GEN_PAPER_QUESTION_COUNT = ""; } let GEN_PAPER_QUESTION_START = this.timeRange?.[0] || ""; let GEN_PAPER_QUESTION_END = this.timeRange?.[1] || ""; let params = { orgId: this.form.orgId, properties: { ...this.form.properties, GEN_PAPER_QUESTION_START, GEN_PAPER_QUESTION_END, }, }; // 调试 // params.properties.CHECK_LIMIT_CHAR_COUNT = undefined; let res = await this.$httpWithMsg.put(url, params).catch(() => {}); if (!res) return; if (this.tab4Entered) { let res2 = await this.$httpWithMsg .post(QUESTION_API + "/rolePrivilege/savePrivilege", { privileges: this.treeCheckedCodes, rootOrgId: this.form.orgId, role: this.roleCode, }) .catch(() => {}); if (!res2) return; } this.$notify({ type: "success", message: "保存成功!", }); // this.back(); }, async getTradeList() { const res = await orgAiTransactionListApi(this.form.orgId); this.tradeList = res.data || []; }, async toBuy() { if (!this.trade) return; const confirm = await this.$confirm( `确定要购买${this.trade}道吗?`, "提示", { type: "warning", } ).catch(() => {}); if (confirm !== "confirm") return; if (this.loading) return; this.loading = true; const res = await orgAiTransactionSaveApi({ rootOrgId: this.form.orgId, trade: this.trade, }).catch(() => {}); this.loading = false; if (!res) return; this.$message.success("购买成功!"); this.init(); this.getTradeList(); }, back() { this.$router.push({ path: "/questions/school" }); }, treeCheckChange(curNode, isChecked) { let keys = this.$refs.authTree.getCheckedKeys(true); if (curNode.privilegeType === "BUTTON" && isChecked) { keys = Array.from(new Set([...keys, curNode.mountPageCode])); this.$refs.authTree.setCheckedKeys(keys); } // this.treeCheckedCodes = [...keys].filter( // (key) => !key.endsWith("__page") // ); this.$nextTick(() => { let nodes = this.$refs.authTree.getCheckedNodes(false, true); this.treeCheckedCodes = nodes .map((item) => item.code) .filter((key) => !key.endsWith("__page")); }); }, filterTree(value, data) { return !data.originId; }, }, watch: { activeName(val) { if (val === "tab4" && !this.tab4Entered) { this.$nextTick(() => { this.getRoleList(); }); } }, roleCode(val) { this.$httpWithMsg .post( QUESTION_API + `/rolePrivilege/getRolePrivileges?roleCode=${val}&rootOrgId=${this.form.orgId}` ) .then((res) => { let checkedLeafCodes = []; res.data.forEach((level1) => { if (level1.subRolePrivilege?.length) { level1.subRolePrivilege = level1.subRolePrivilege.map( (level2) => { if (level2.subRolePrivilege?.length) { level2.subRolePrivilege = level2.subRolePrivilege.map( (v) => { v.mountPageCode = level2.code + "__page"; v.enable && checkedLeafCodes.push(v.code); return v; } ); level2.subRolePrivilege.unshift({ code: level2.code + "__page", enable: level2.enable, name: "页面", privilegeType: "PAGE", originId: level2.code, }); level2.enable && checkedLeafCodes.push(level2.code + "__page"); } else { level2.enable && checkedLeafCodes.push(level2.code); } return level2; } ); } else { level1.enable && checkedLeafCodes.push(level1.code); } }); this.treeData = res.data; //初始化选中状态,使用叶子节点的enable进行设置 this.$refs.authTree.setCheckedKeys(checkedLeafCodes); }); }, treeData() { this.$nextTick(() => { this.$refs.authTree?.filter(""); }); }, }, }; </script> <style lang="scss" scoped> .org-property { .tree-box { :deep(.custom-tree-node) { .is-page, .is-btn { padding: 3px 5px; font-size: 10px; border-radius: 4px; background: #67c23a; color: #fff; margin-left: 8px; vertical-align: middle; position: relative; top: -2px; } } } } </style>