Sfoglia il codice sorgente

reactor:调整考试培训得培训模板目录;

zhangchong 6 giorni fa
parent
commit
862e5f3e9b

+ 0 - 223
src/views/examTrain/train/template/components/Template-add.vue

@@ -1,223 +0,0 @@
-<template>
-	<el-dialog title="新增培训模板" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close" width="800px">
-		<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
-			<el-row :gutter="10">
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '请填写模板名称', trigger: 'blur' }]">
-						<el-input v-model="state.ruleForm.name" placeholder="请填写模板名称" clearable></el-input>
-					</el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="培训资料" prop="trainKnowladges" class="w100 tableFormItem" :rules="[{ required: true, message: '请选择培训资料', trigger: 'change' }]">
-                        <vxe-toolbar
-                            ref="toolbarRef"
-                            custom
-                        >
-                            <template #buttons>
-                                <el-button type="primary" @click="onAddKnowladgesTable">
-                                    <SvgIcon name="ele-Plus" class="mr10" />新增
-                                </el-button>
-                            </template>
-                        </vxe-toolbar>
-                        <vxe-table
-                            border
-                            :data="state.ruleForm.trainKnowladges"
-                            :column-config="{ resizable: true }"
-                            :row-config="{ height: 50, useKey: true }"
-                            ref="tableRef"
-                            height="300"
-                            auto-resize
-                            show-overflow
-                            :scrollY="{ enabled: true, gt: 100 }"
-                            id="knowladgesTable"
-                            :custom-config="{ storage: true }"
-                            showHeaderOverflow
-                        >
-                            <vxe-column field="title" title="知识标题" min-width="100"></vxe-column>
-                            <vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
-                                <template #default="{ row }">
-                                    <el-button link type="danger" @click="onRowDelKnowladgesTable(row)" title="删除">
-                                        删除
-                                    </el-button>
-                                </template>
-                            </vxe-column>
-                        </vxe-table>
-                    </el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="包含习题" prop="isContainsPractice" :rules="[{ required: true, message: '请选择是否包含习题', trigger: 'change' }]">
-						<el-radio-group v-model="state.ruleForm.isContainsPractice">
-							<el-radio :value="true">是</el-radio>
-							<el-radio :value="false">否</el-radio>
-						</el-radio-group>
-					</el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.isContainsPractice == true">
-					<el-form-item label="选择习题" prop="trainPracticeDtos" class="w100 tableFormItem" :rules="[{ required: true, message: '请选择习题', trigger: 'change' }]">
-                        <vxe-toolbar
-                            ref="toolbarRef"
-                            custom
-                        >
-                            <template #buttons>
-                                <el-button type="primary" @click="onAddQuestionsTable">
-                                    <SvgIcon name="ele-Plus" class="mr10" />新增
-                                </el-button>
-                            </template>
-                        </vxe-toolbar>
-                        <vxe-table
-                            border
-                            :data="state.ruleForm.trainPracticeDtos"
-                            :column-config="{ resizable: true }"
-                            :row-config="{ height: 50, useKey: true }"
-                            ref="tableRef"
-                            height="300"
-                            auto-resize
-                            show-overflow
-                            :scrollY="{ enabled: true, gt: 100 }"
-                            id="questionsTable"
-                            :custom-config="{ storage: true }"
-                            showHeaderOverflow
-                        >
-                            <vxe-column field="questionTypeDesc" title="题型" width="100"></vxe-column>
-                            <vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
-                            <vxe-column field="title" title="题干" min-width="100"></vxe-column>
-                            <vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
-                                <template #default="{ row }">
-                                    <el-button link type="danger" @click="onRowDelQuestionsTable(row)" title="删除">
-                                        删除
-                                    </el-button>
-                                </template>
-                            </vxe-column>
-                        </vxe-table>
-                    </el-form-item>
-				</el-col>
-				<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="排序" prop="weight" :rules="[{ required: true, message: '请填写排序', trigger: 'blur' }]">
-                        <el-input v-model="state.ruleForm.weight" placeholder="请填写排序" clearable></el-input>
-                    </el-form-item>
-				</el-col> -->
-			</el-row>
-		</el-form>
-		<template #footer>
-			<span class="dialog-footer">
-				<el-button @click="closeDialog" class="default-button">取 消</el-button>
-				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
-			</span>
-		</template>
-
-        <!-- 关联知识库 -->
-		<question-knowledge ref="QuestionKnowledgeRef" @choose="chooseKnowledge" />
-        <!-- 自选试题页面 -->
-		<template-optional ref="TemplateOptionalRef" @choose="chooseQuestion" />
-	</el-dialog>
-</template>
-
-<script setup lang="ts">
-import { reactive, ref, defineAsyncComponent } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import Other from '@/utils/other';
-import {addTrainTemplate} from '@/api/examTrain/trainTemplate';
-
-// 引入组件
-const QuestionKnowledge = defineAsyncComponent(() => import('@/views/examTrain/questionBank/components/Question-knowledge.vue')); // 关联知识
-const TemplateOptional = defineAsyncComponent(() => import('@/views/examTrain/train/template/components/Template-optional.vue')); // 自选试题页面
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗
-	ruleForm: {
-		name: '', // 模板名称
-		trainKnowladges : [], // 培训资料
-		isContainsPractice: null, // 是否包含习题
-		trainPracticeDtos: [], // 习题
-	},
-	loading: false, // 加载
-	tableLoading: false, // 表格加载
-});
-// 打开弹窗
-const ruleFormRef = ref<any>(); // 表单ref
-// 打开弹窗
-const openDialog = async () => {
-	state.dialogVisible = true;
-};
-const close = () => {
-	ruleFormRef.value?.clearValidate();
-	ruleFormRef.value?.resetFields();
-	state.ruleForm.trainKnowladges = [];
-	state.ruleForm.trainPracticeDtos = [];
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-	state.ruleForm.trainKnowladges = [];
-	state.ruleForm.trainPracticeDtos = [];
-};
-// 选择知识
-const QuestionKnowledgeRef = ref<RefType>();
-const onAddKnowladgesTable = () => {
-	QuestionKnowledgeRef.value.openDialog(state.ruleForm.trainKnowladges);
-};
-// 确定选择了知识库
-const chooseKnowledge = (data: any) => {
-    state.ruleForm.trainKnowladges = Other.deepClone(data);
-};
-// 删除知识
-const onRowDelKnowladgesTable = (row: any) => {
-	state.ruleForm.trainKnowladges = state.ruleForm.trainKnowladges.filter(it => it.knowladgeId !== row.knowladgeId );
-    ElMessage.success('删除成功');
-};
-// 选择试题新增
-const TemplateOptionalRef = ref<RefType>();
-const onAddQuestionsTable = () => {
-	if (state.ruleForm.trainKnowladges.length > 0){
-		TemplateOptionalRef.value.openDialog(state.ruleForm.trainKnowladges, state.ruleForm.trainPracticeDtos);
-	}else {
-		ElMessage.warning('请选择培训资料');
-	}
-};
-// 确定选择试题
-const chooseQuestion = (data: any) => {
-    state.ruleForm.trainPracticeDtos = Other.deepClone(data);
-};
-// 删除试题
-const onRowDelQuestionsTable = (row: any) => {
-	state.ruleForm.trainPracticeDtos = state.ruleForm.trainPracticeDtos.filter(it => it.questionId !== row.questionId );
-    ElMessage.success('删除成功');
-};
-// 新增
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		console.log(state.ruleForm);
-		const submitObj = Other.deepClone(state.ruleForm);
-		if (!submitObj.isContainsPractice){
-			submitObj.trainPracticeDtos = [];
-		}
-		addTrainTemplate(submitObj)
-			.then(() => {
-				emit('updateList');
-				closeDialog(); // 关闭弹窗
-				ElMessage.success('操作成功');
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>
-<style lang="scss">
-	.tableFormItem .el-form-item__content{
-		display: block;
-	}
-</style>

+ 0 - 230
src/views/examTrain/train/template/components/Template-edit.vue

@@ -1,230 +0,0 @@
-<template>
-	<el-dialog title="编辑培训模板" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close" width="800px">
-		<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
-			<el-row :gutter="10">
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '请填写模板名称', trigger: 'blur' }]">
-						<el-input v-model="state.ruleForm.name" placeholder="请填写模板名称" clearable></el-input>
-					</el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="培训资料" prop="trainKnowladges" class="w100 tableFormItem" :rules="[{ required: true, message: '请选择培训资料', trigger: 'change' }]">
-                        <vxe-toolbar
-                            ref="toolbarRef"
-                            custom
-                        >
-                            <template #buttons>
-                                <el-button type="primary" @click="onAddKnowladgesTable">
-                                    <SvgIcon name="ele-Plus" class="mr10" />新增
-                                </el-button>
-                            </template>
-                        </vxe-toolbar>
-                        <vxe-table
-                            border
-                            :data="state.ruleForm.trainKnowladges"
-                            :column-config="{ resizable: true }"
-                            :row-config="{ height: 50, useKey: true }"
-                            ref="tableRef"
-                            height="300"
-                            auto-resize
-                            show-overflow
-                            :scrollY="{ enabled: true, gt: 100 }"
-                            id="knowladgesTable"
-                            :custom-config="{ storage: true }"
-                            showHeaderOverflow
-                        >
-                            <vxe-column field="title" title="知识标题" min-width="100"></vxe-column>
-                            <vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
-                                <template #default="{ row }">
-                                    <el-button link type="danger" @click="onRowDelKnowladgesTable(row)" title="删除">
-                                        删除
-                                    </el-button>
-                                </template>
-                            </vxe-column>
-                        </vxe-table>
-                    </el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="包含习题" prop="isContainsPractice" :rules="[{ required: true, message: '请选择是否包含习题', trigger: 'change' }]">
-						<el-radio-group v-model="state.ruleForm.isContainsPractice">
-							<el-radio :value="true">是</el-radio>
-							<el-radio :value="false">否</el-radio>
-						</el-radio-group>
-					</el-form-item>
-				</el-col>
-				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.isContainsPractice == true">
-					<el-form-item label="选择习题" prop="trainPracticeDtos" class="w100 tableFormItem" :rules="[{ required: true, message: '请选择习题', trigger: 'change' }]">
-                        <vxe-toolbar
-                            ref="toolbarRef"
-                            custom
-                        >
-                            <template #buttons>
-                                <el-button type="primary" @click="onAddQuestionsTable">
-                                    <SvgIcon name="ele-Plus" class="mr10" />新增
-                                </el-button>
-                            </template>
-                        </vxe-toolbar>
-                        <vxe-table
-                            border
-                            :data="state.ruleForm.trainPracticeDtos"
-                            :column-config="{ resizable: true }"
-                            :row-config="{ height: 50, useKey: true }"
-                            ref="tableRef"
-                            height="300"
-                            auto-resize
-                            show-overflow
-                            :scrollY="{ enabled: true, gt: 100 }"
-                            id="questionsTable"
-                            :custom-config="{ storage: true }"
-                            showHeaderOverflow
-                        >
-                            <vxe-column field="questionTypeDesc" title="题型" width="100"></vxe-column>
-                            <vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
-                            <vxe-column field="title" title="题干" min-width="100"></vxe-column>
-                            <vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
-                                <template #default="{ row }">
-                                    <el-button link type="danger" @click="onRowDelQuestionsTable(row)" title="删除">
-                                        删除
-                                    </el-button>
-                                </template>
-                            </vxe-column>
-                        </vxe-table>
-                    </el-form-item>
-				</el-col>
-				<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-					<el-form-item label="排序" prop="weight" :rules="[{ required: true, message: '请填写排序', trigger: 'blur' }]">
-                        <el-input v-model="state.ruleForm.weight" placeholder="请填写排序" clearable></el-input>
-                    </el-form-item>
-				</el-col> -->
-			</el-row>
-		</el-form>
-		<template #footer>
-			<span class="dialog-footer">
-				<el-button @click="closeDialog" class="default-button">取 消</el-button>
-				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
-			</span>
-		</template>
-
-        <!-- 关联知识库 -->
-		<question-knowledge ref="QuestionKnowledgeRef" @choose="chooseKnowledge" />
-        <!-- 自选试题页面 -->
-		<template-optional ref="TemplateOptionalRef" @choose="chooseQuestion" />
-	</el-dialog>
-</template>
-
-<script setup lang="ts">
-import { reactive, ref, defineAsyncComponent } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import Other from '@/utils/other';
-import {getTrainTemplateDetail, editTrainTemplate} from '@/api/examTrain/trainTemplate';
-
-// 引入组件
-const QuestionKnowledge = defineAsyncComponent(() => import('@/views/examTrain/questionBank/components/Question-knowledge.vue')); // 关联知识
-const TemplateOptional = defineAsyncComponent(() => import('@/views/examTrain/train/template/components/Template-optional.vue')); // 自选试题页面
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗
-	ruleForm: {
-		name: '', // 模板名称
-		trainKnowladges : [], // 培训资料
-		isContainsPractice: null, // 是否包含习题
-		trainPracticeDtos: [], // 习题
-	},
-	loading: false, // 加载
-	tableLoading: false, // 表格加载
-});
-// 打开弹窗
-const ruleFormRef = ref<any>(); // 表单ref
-// 打开弹窗
-const openDialog = async (row: any) => {
-	state.dialogVisible = true;
-	try {
-		const { result } = await getTrainTemplateDetail(row.id);
-		state.ruleForm = result;
-	} catch (error) {
-		console.log(error);
-		state.loading = false;
-	}
-};
-const close = () => {
-	ruleFormRef.value?.clearValidate();
-	ruleFormRef.value?.resetFields();
-	state.ruleForm.trainKnowladges = [];
-	state.ruleForm.trainPracticeDtos = [];
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-	state.ruleForm.trainKnowladges = [];
-	state.ruleForm.trainPracticeDtos = [];
-};
-// 选择知识
-const QuestionKnowledgeRef = ref<RefType>();
-const onAddKnowladgesTable = () => {
-	QuestionKnowledgeRef.value.openDialog(state.ruleForm.trainKnowladges);
-};
-// 确定选择了知识库
-const chooseKnowledge = (data: any) => {
-    state.ruleForm.trainKnowladges = Other.deepClone(data);
-};
-// 删除知识
-const onRowDelKnowladgesTable = (row: any) => {
-	state.ruleForm.trainKnowladges = state.ruleForm.trainKnowladges.filter(it => it.knowladgeId !== row.knowladgeId );
-    ElMessage.success('删除成功');
-};
-// 选择试题新增
-const TemplateOptionalRef = ref<RefType>();
-const onAddQuestionsTable = () => {
-	if (state.ruleForm.trainKnowladges.length > 0){
-		TemplateOptionalRef.value.openDialog(state.ruleForm.trainKnowladges, state.ruleForm.trainPracticeDtos);
-	}else {
-		ElMessage.warning('请选择培训资料');
-	}
-};
-// 确定选择试题
-const chooseQuestion = (data: any) => {
-    state.ruleForm.trainPracticeDtos = Other.deepClone(data);
-};
-// 删除试题
-const onRowDelQuestionsTable = (row: any) => {
-	state.ruleForm.trainPracticeDtos = state.ruleForm.trainPracticeDtos.filter(it => it.questionId !== row.questionId );
-    ElMessage.success('删除成功');
-};
-// 新增
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-	    console.log(state.ruleForm);
-        const submitObj = Other.deepClone(state.ruleForm);
-		if (!submitObj.isContainsPractice){
-			submitObj.trainPracticeDtos = [];
-		}
-		editTrainTemplate(submitObj)
-			.then(() => {
-				emit('updateList');
-				closeDialog(); // 关闭弹窗
-				ElMessage.success('操作成功');
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>
-<style lang="scss">
-	.tableFormItem .el-form-item__content{
-		display: block;
-	}
-</style>

+ 0 - 218
src/views/examTrain/train/template/index.vue

@@ -1,218 +0,0 @@
-<template>
-	<div class="plan-index-container layout-padding">
-		<div class="layout-padding-auto layout-padding-view pd20">
-			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent :disabled="state.tableLoading">
-                <el-form-item label="模板编号" prop="code">
-                    <el-input v-model="state.queryParams.code" placeholder="请输入" clearable @keyup.enter="handleQuery" class="keyword-input" />
-                </el-form-item>
-                <el-form-item label="模板标题" prop="name">
-                    <el-input v-model="state.queryParams.name" placeholder="请输入" clearable @keyup.enter="handleQuery" class="keyword-input" />
-                </el-form-item>
-                <el-form-item label="包含习题" prop="isContainsPractice">
-                    <el-select v-model="state.queryParams.isContainsPractice" clearable placeholder="请选择" @change="handleQuery" :disabled="state.tableLoading">
-                        <el-option key='0' label="包含" :value="0" />
-                        <el-option key='1' label="不包含" :value="1" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item>
-                    <el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-                    <el-button @click="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
-                </el-form-item>
-            </el-form>
-            <vxe-toolbar
-                ref="toolbarRef"
-                :loading="state.tableLoading"
-                custom
-                :refresh="{
-                    queryMethod: handleQuery,
-                }"
-            >
-                <template #buttons>
-                    <el-button type="primary" @click="onOpenAdd" v-auth="'template:index:add'" :loading="state.tableLoading">
-                        <SvgIcon name="ele-Plus" class="mr10" />新增
-                    </el-button>
-                </template>
-            </vxe-toolbar>
-            <div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
-                <vxe-table
-                    border
-                    :loading="state.tableLoading"
-                    :data="state.tableData"
-                    :column-config="{ resizable: true }"
-                    :row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
-                    ref="tableRef"
-                    height="auto"
-                    auto-resize
-                    show-overflow
-                    :print-config="{}"
-                    :scrollY="{ enabled: true, gt: 100 }"
-                    id="examTrainTrainTemplate"
-                    :custom-config="{ storage: true }"
-                    showHeaderOverflow
-                >
-                    <vxe-column field="code" title="模板编号" width="200"></vxe-column>
-                    <vxe-column field="name" title="模板标题" min-width="200"></vxe-column>
-                    <vxe-column field="isContainsPracticeDes" title="是否包含习题" width="150"></vxe-column>
-                    <!-- <vxe-column field="status" title="状态" width="160">
-                        <template #default="{ row }">
-                            <el-switch v-model="row.status" />
-                        </template>
-                    </vxe-column> -->
-                    <vxe-column field="creatorName" title="创建人" width="150"></vxe-column>
-                    <vxe-column field="creatorOrgName" title="创建部门" width="150"></vxe-column>
-                    <vxe-column field="creationTime" title="创建时间" width="160">
-						<template #default="{ row }">
-							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</template>
-					</vxe-column>
-                    <vxe-column title="操作" fixed="right" width="120" align="center" :show-overflow="false">
-                        <template #default="{ row }">
-                            <el-button link type="primary" @click="onOpenEdit(row)" title="编辑" v-auth="'template:index:edit'">
-                                编辑
-                            </el-button>
-                            <el-button link type="danger" @click="onRowDel(row)" title="删除" v-auth="'template:index:delete'">
-                                删除
-                            </el-button>
-                        </template>
-                    </vxe-column>
-                </vxe-table>
-            </div>
-            <pagination
-                @pagination="queryList"
-                :total="state.total"
-                v-model:current-page="state.queryParams.PageIndex"
-                v-model:page-size="state.queryParams.PageSize"
-                :disabled="state.tableLoading"
-            />
-		</div>
-        <!--	更多查询	-->
-		<el-drawer v-model="drawer" title="更多查询" size="500px">
-			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
-                <el-form-item label="状态" prop="status">
-                    <el-select v-model="state.queryParams.status" clearable placeholder="请选择" @change="handleQuery" :disabled="state.tableLoading">
-                        <el-option key='0' label="停用" :value="0" />
-                        <el-option key='1' label="启用" :value="1" />
-                    </el-select>
-                </el-form-item>
-				<el-form-item label="创建人" prop="creatorName">
-                    <el-input v-model="state.queryParams.creatorName" placeholder="请输入" clearable class="keyword-input" />
-                </el-form-item>
-                <el-form-item label="创建时间>=" prop="minCreationTime">
-                    <el-date-picker v-model="state.queryParams.minCreationTime" type="datetime" class="w100" value-format="YYYY-MM-DD[T]HH:mm:ss"  placeholder="请选择" popper-class="no-atTheMoment" />
-                </el-form-item>
-                <el-form-item label="创建时间<=" prop="maxCreationTime">
-                    <el-date-picker v-model="state.queryParams.maxCreationTime" type="datetime" class="w100" value-format="YYYY-MM-DD[T]HH:mm:ss"  placeholder="请选择" popper-class="no-atTheMoment" />
-                </el-form-item>
-			</el-form>
-			<template #footer>
-				<el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-			</template>
-		</el-drawer>
-
-        <template-add ref="templateAddRef" @updateList="queryList" />
-		<template-edit ref="templateEditRef" @updateList="queryList" />
-	</div>
-</template>
-
-<script lang="tsx" setup name="examTrainTrainTemplate">
-import { ref, reactive, onMounted, defineAsyncComponent, computed } from 'vue';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import { useRouter } from 'vue-router';
-import type { FormInstance } from 'element-plus';
-import { formatDate } from '@/utils/formatTime';
-import 'splitpanes/dist/splitpanes.css';
-import Other from '@/utils/other';
-import { downloadFileByStream } from '@/utils/tools';
-import {deleteTrainTemplate, getTrainTemplateData} from '@/api/examTrain/trainTemplate';
-
-// 引入组件
-const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
-const TemplateAdd = defineAsyncComponent(() => import('@/views/examTrain/train/template/components/Template-add.vue')); // 新增组件
-const TemplateEdit = defineAsyncComponent(() => import('@/views/examTrain/train/template/components/Template-edit.vue')); // 修改组件
-
-const router = useRouter(); //路由
-
-// 定义变量内容
-const state = reactive<any>({
-	queryParams: {
-		PageIndex: 1, //页码
-		PageSize: 20, //每页条数
-        code: null, // 编号
-        name: null, // 名称
-		status: null, // 状态
-        isContainsPractice: null , //  是否包含习题
-        creatorName: null , // 创建人
-        minCreationTime: null , // 创建时间>=
-        maxCreationTime: null , // 创建时间<=
-	},
-	tableData: [], //表格数据
-	total: 0, //总条数
-	tableLoading: false, //表格loading
-});
-/** 搜索按钮操作 节流操作 */
-const handleQuery = () => {
-	state.queryParams.PageIndex = 1;
-	queryList();
-};
-/** 获取试题列表 */
-const requestParams = ref<EmptyObjectType>({});
-const queryList = () => {
-	state.tableLoading = true;
-    requestParams.value = Other.deepClone(state.queryParams);
-	getTrainTemplateData(requestParams.value)
-		.then((response: any) => {
-            console.log(response)
-			state.tableData = response?.result.items ?? [];
-			state.total = response?.result.pagination.totalCount ?? 0;
-			state.tableLoading = false;
-		})
-		.catch(() => {
-			state.tableLoading = false;
-		});
-};
-/** 重置按钮操作 */
-const drawerRuleFormRef = ref();
-const ruleFormRef = ref<RefType>(); // 表单ref
-const drawer = ref(false);
-const resetQuery = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	ruleFormRef.value?.resetFields();
-	handleQuery();
-};
-// 打开新增弹窗
-const templateAddRef = ref<RefType>(); // 新增ref
-const onOpenAdd = () => {
-	templateAddRef.value.openDialog();
-};
-// 打开编辑弹窗
-const templateEditRef = ref<RefType>(); // 修改ref
-const onOpenEdit = (row: any) => {
-	templateEditRef.value.openDialog(row, state.tableData);
-};
-// 删除当前行
-const onRowDel = (row: any) => {
-	ElMessageBox.confirm(`是否确认删除当前培训模板?删除后不可恢复`, '提示', {
-		confirmButtonText: '确定',
-		cancelButtonText: '取消',
-		type: 'warning',
-	})
-        .then(() => {
-			deleteTrainTemplate({id: row.id}).then(() => {
-				ElMessage.success('删除成功');
-				queryList();
-			});
-		})
-		.catch(() => {});
-};
-
-const tableRef = ref<RefType>();
-const toolbarRef = ref<RefType>();
-onMounted(() => {
-	queryList();
-	if (tableRef.value && toolbarRef.value) {
-		tableRef.value.connect(toolbarRef.value);
-	}
-});
-</script>

+ 218 - 0
src/views/examTrain/train/trainTemp/components/Train-temp-add.vue

@@ -0,0 +1,218 @@
+<template>
+	<el-dialog title="新增培训模板" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close" width="800px">
+		<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
+			<el-row :gutter="10">
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '请填写模板名称', trigger: 'blur' }]">
+						<el-input v-model="state.ruleForm.name" placeholder="请填写模板名称" clearable></el-input>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item
+						label="培训资料"
+						prop="trainKnowladges"
+						class="w100 tableFormItem"
+						:rules="[{ required: true, message: '请选择培训资料', trigger: 'change' }]"
+					>
+						<vxe-toolbar ref="toolbarRef">
+							<template #buttons>
+								<el-button type="primary" @click="onAddKnowladgesTable"> <SvgIcon name="ele-Plus" class="mr10" />新增 </el-button>
+							</template>
+						</vxe-toolbar>
+						<vxe-table
+							border
+							:data="state.ruleForm.trainKnowladges"
+							:column-config="{ resizable: true }"
+							:row-config="{ height: 30, useKey: true }"
+							ref="tableRef"
+							height="300"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 100 }"
+							id="knowladgesTable"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+						>
+							<vxe-column field="title" title="知识标题" min-width="100"></vxe-column>
+							<vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
+								<template #default="{ row }">
+									<el-button link type="danger" @click="onRowDelKnowladgesTable(row)" title="删除"> 删除 </el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="包含习题" prop="isContainsPractice" :rules="[{ required: true, message: '请选择是否包含习题', trigger: 'change' }]">
+						<el-radio-group v-model="state.ruleForm.isContainsPractice">
+							<el-radio :value="true">是</el-radio>
+							<el-radio :value="false">否</el-radio>
+						</el-radio-group>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.isContainsPractice == true">
+					<el-form-item
+						label="选择习题"
+						prop="trainPracticeDtos"
+						class="w100 tableFormItem"
+						:rules="[{ required: true, message: '请选择习题', trigger: 'change' }]"
+					>
+						<vxe-toolbar ref="toolbarRef">
+							<template #buttons>
+								<el-button type="primary" @click="onAddQuestionsTable"> <SvgIcon name="ele-Plus" class="mr10" />新增 </el-button>
+							</template>
+						</vxe-toolbar>
+						<vxe-table
+							border
+							:data="state.ruleForm.trainPracticeDtos"
+							:column-config="{ resizable: true }"
+							:row-config="{ height: 30, useKey: true }"
+							ref="tableRef"
+							height="300"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 100 }"
+							id="questionsTable"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+						>
+							<vxe-column field="questionTypeDesc" title="题型" width="100"></vxe-column>
+							<vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
+							<vxe-column field="title" title="题干" min-width="100"></vxe-column>
+							<vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
+								<template #default="{ row }">
+									<el-button link type="danger" @click="onRowDelQuestionsTable(row)" title="删除"> 删除 </el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</el-form-item>
+				</el-col>
+				<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="排序" prop="weight" :rules="[{ required: true, message: '请填写排序', trigger: 'blur' }]">
+                        <el-input v-model="state.ruleForm.weight" placeholder="请填写排序" clearable></el-input>
+                    </el-form-item>
+				</el-col> -->
+			</el-row>
+		</el-form>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="closeDialog" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
+			</span>
+		</template>
+	</el-dialog>
+	<!-- 关联知识库 -->
+	<question-knowledge ref="QuestionKnowledgeRef" @choose="chooseKnowledge" />
+	<!-- 自选试题页面 -->
+	<train-temp-optional ref="trainTemplateOptionalRef" @choose="chooseQuestion" />
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, defineAsyncComponent } from 'vue';
+import { ElMessage, FormInstance } from 'element-plus';
+import Other from '@/utils/other';
+import { addTrainTemplate } from '@/api/examTrain/trainTemplate';
+
+// 引入组件
+const QuestionKnowledge = defineAsyncComponent(() => import('@/views/examTrain/questionBank/components/Question-knowledge.vue')); // 关联知识
+const TrainTempOptional = defineAsyncComponent(() => import('@/views/examTrain/train/trainTemp/components/Train-temp-optional.vue')); // 自选试题页面
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['updateList']);
+
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 弹窗
+	ruleForm: {
+		name: '', // 模板名称
+		trainKnowladges: [], // 培训资料
+		isContainsPractice: null, // 是否包含习题
+		trainPracticeDtos: [], // 习题
+	},
+	loading: false, // 加载
+	tableLoading: false, // 表格加载
+});
+// 打开弹窗
+const ruleFormRef = ref<any>(); // 表单ref
+// 打开弹窗
+const openDialog = async () => {
+	state.dialogVisible = true;
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+	state.ruleForm.trainKnowladges = [];
+	state.ruleForm.trainPracticeDtos = [];
+};
+// 关闭弹窗
+const closeDialog = () => {
+	state.dialogVisible = false;
+	state.ruleForm.trainKnowladges = [];
+	state.ruleForm.trainPracticeDtos = [];
+};
+// 选择知识
+const QuestionKnowledgeRef = ref<RefType>();
+const onAddKnowladgesTable = () => {
+	QuestionKnowledgeRef.value.openDialog(state.ruleForm.trainKnowladges);
+};
+// 确定选择了知识库
+const chooseKnowledge = (data: any) => {
+	state.ruleForm.trainKnowladges = Other.deepClone(data);
+};
+// 删除知识
+const onRowDelKnowladgesTable = (row: any) => {
+	state.ruleForm.trainKnowladges = state.ruleForm.trainKnowladges.filter((it) => it.knowladgeId !== row.knowladgeId);
+	ElMessage.success('删除成功');
+};
+// 选择试题新增
+const trainTemplateOptionalRef = ref<RefType>();
+const onAddQuestionsTable = () => {
+	if (state.ruleForm.trainKnowladges.length > 0) {
+		trainTemplateOptionalRef.value.openDialog(state.ruleForm.trainKnowladges, state.ruleForm.trainPracticeDtos);
+	} else {
+		ElMessage.warning('请选择培训资料');
+	}
+};
+// 确定选择试题
+const chooseQuestion = (data: any) => {
+	state.ruleForm.trainPracticeDtos = Other.deepClone(data);
+};
+// 删除试题
+const onRowDelQuestionsTable = (row: any) => {
+	state.ruleForm.trainPracticeDtos = state.ruleForm.trainPracticeDtos.filter((it) => it.questionId !== row.questionId);
+	ElMessage.success('删除成功');
+};
+// 新增
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		console.log(state.ruleForm);
+		const submitObj = Other.deepClone(state.ruleForm);
+		if (!submitObj.isContainsPractice) {
+			submitObj.trainPracticeDtos = [];
+		}
+		addTrainTemplate(submitObj)
+			.then(() => {
+				emit('updateList');
+				closeDialog(); // 关闭弹窗
+				ElMessage.success('操作成功');
+				state.loading = false;
+			})
+			.catch(() => {
+				state.loading = false;
+			});
+	});
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>
+<style lang="scss">
+.tableFormItem .el-form-item__content {
+	display: block;
+}
+</style>

+ 225 - 0
src/views/examTrain/train/trainTemp/components/Train-temp-edit.vue

@@ -0,0 +1,225 @@
+<template>
+	<el-dialog title="编辑培训模板" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close" width="800px">
+		<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
+			<el-row :gutter="10">
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="模板名称" prop="name" :rules="[{ required: true, message: '请填写模板名称', trigger: 'blur' }]">
+						<el-input v-model="state.ruleForm.name" placeholder="请填写模板名称" clearable></el-input>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item
+						label="培训资料"
+						prop="trainKnowladges"
+						class="w100 tableFormItem"
+						:rules="[{ required: true, message: '请选择培训资料', trigger: 'change' }]"
+					>
+						<vxe-toolbar ref="toolbarRef">
+							<template #buttons>
+								<el-button type="primary" @click="onAddKnowladgesTable"> <SvgIcon name="ele-Plus" class="mr10" />新增 </el-button>
+							</template>
+						</vxe-toolbar>
+						<vxe-table
+							border
+							:data="state.ruleForm.trainKnowladges"
+							:column-config="{ resizable: true }"
+							:row-config="{ height: 30, useKey: true }"
+							ref="tableRef"
+							height="300"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 100 }"
+							id="knowladgesTable"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+						>
+							<vxe-column field="title" title="知识标题" min-width="100"></vxe-column>
+							<vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
+								<template #default="{ row }">
+									<el-button link type="danger" @click="onRowDelKnowladgesTable(row)" title="删除"> 删除 </el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="包含习题" prop="isContainsPractice" :rules="[{ required: true, message: '请选择是否包含习题', trigger: 'change' }]">
+						<el-radio-group v-model="state.ruleForm.isContainsPractice">
+							<el-radio :value="true">是</el-radio>
+							<el-radio :value="false">否</el-radio>
+						</el-radio-group>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.isContainsPractice == true">
+					<el-form-item
+						label="选择习题"
+						prop="trainPracticeDtos"
+						class="w100 tableFormItem"
+						:rules="[{ required: true, message: '请选择习题', trigger: 'change' }]"
+					>
+						<vxe-toolbar ref="toolbarRef">
+							<template #buttons>
+								<el-button type="primary" @click="onAddQuestionsTable"> <SvgIcon name="ele-Plus" class="mr10" />新增 </el-button>
+							</template>
+						</vxe-toolbar>
+						<vxe-table
+							border
+							:data="state.ruleForm.trainPracticeDtos"
+							:column-config="{ resizable: true }"
+							:row-config="{ height: 30, useKey: true }"
+							ref="tableRef"
+							height="300"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 100 }"
+							id="questionsTable"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+						>
+							<vxe-column field="questionTypeDesc" title="题型" width="100"></vxe-column>
+							<vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
+							<vxe-column field="title" title="题干" min-width="100"></vxe-column>
+							<vxe-column title="操作" fixed="right" width="80" align="center" :show-overflow="false">
+								<template #default="{ row }">
+									<el-button link type="danger" @click="onRowDelQuestionsTable(row)" title="删除"> 删除 </el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</el-form-item>
+				</el-col>
+				<!-- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="排序" prop="weight" :rules="[{ required: true, message: '请填写排序', trigger: 'blur' }]">
+                        <el-input v-model="state.ruleForm.weight" placeholder="请填写排序" clearable></el-input>
+                    </el-form-item>
+				</el-col> -->
+			</el-row>
+		</el-form>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="closeDialog" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
+			</span>
+		</template>
+	</el-dialog>
+	<!-- 关联知识库 -->
+	<question-knowledge ref="QuestionKnowledgeRef" @choose="chooseKnowledge" />
+	<!-- 自选试题页面 -->
+	<train-temp-optional ref="trainTemplateOptionalRef" @choose="chooseQuestion" />
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, defineAsyncComponent } from 'vue';
+import { ElMessage, FormInstance } from 'element-plus';
+import Other from '@/utils/other';
+import { getTrainTemplateDetail, editTrainTemplate } from '@/api/examTrain/trainTemplate';
+
+// 引入组件
+const QuestionKnowledge = defineAsyncComponent(() => import('@/views/examTrain/questionBank/components/Question-knowledge.vue')); // 关联知识
+const TrainTempOptional = defineAsyncComponent(() => import('@/views/examTrain/train/trainTemp/components/Train-temp-optional.vue')); // 自选试题页面
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['updateList']);
+
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 弹窗
+	ruleForm: {
+		name: '', // 模板名称
+		trainKnowladges: [], // 培训资料
+		isContainsPractice: null, // 是否包含习题
+		trainPracticeDtos: [], // 习题
+	},
+	loading: false, // 加载
+	tableLoading: false, // 表格加载
+});
+// 打开弹窗
+const ruleFormRef = ref<any>(); // 表单ref
+// 打开弹窗
+const openDialog = async (row: any) => {
+	state.dialogVisible = true;
+	try {
+		const { result } = await getTrainTemplateDetail(row.id);
+		state.ruleForm = result;
+	} catch (error) {
+		console.log(error);
+		state.loading = false;
+	}
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+	state.ruleForm.trainKnowladges = [];
+	state.ruleForm.trainPracticeDtos = [];
+};
+// 关闭弹窗
+const closeDialog = () => {
+	state.dialogVisible = false;
+	state.ruleForm.trainKnowladges = [];
+	state.ruleForm.trainPracticeDtos = [];
+};
+// 选择知识
+const QuestionKnowledgeRef = ref<RefType>();
+const onAddKnowladgesTable = () => {
+	QuestionKnowledgeRef.value.openDialog(state.ruleForm.trainKnowladges);
+};
+// 确定选择了知识库
+const chooseKnowledge = (data: any) => {
+	state.ruleForm.trainKnowladges = Other.deepClone(data);
+};
+// 删除知识
+const onRowDelKnowladgesTable = (row: any) => {
+	state.ruleForm.trainKnowladges = state.ruleForm.trainKnowladges.filter((it) => it.knowladgeId !== row.knowladgeId);
+	ElMessage.success('删除成功');
+};
+// 选择试题新增
+const trainTemplateOptionalRef = ref<RefType>();
+const onAddQuestionsTable = () => {
+	if (state.ruleForm.trainKnowladges.length > 0) {
+		trainTemplateOptionalRef.value.openDialog(state.ruleForm.trainKnowladges, state.ruleForm.trainPracticeDtos);
+	} else {
+		ElMessage.warning('请选择培训资料');
+	}
+};
+// 确定选择试题
+const chooseQuestion = (data: any) => {
+	state.ruleForm.trainPracticeDtos = Other.deepClone(data);
+};
+// 删除试题
+const onRowDelQuestionsTable = (row: any) => {
+	state.ruleForm.trainPracticeDtos = state.ruleForm.trainPracticeDtos.filter((it) => it.questionId !== row.questionId);
+	ElMessage.success('删除成功');
+};
+// 新增
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		console.log(state.ruleForm);
+		const submitObj = Other.deepClone(state.ruleForm);
+		if (!submitObj.isContainsPractice) {
+			submitObj.trainPracticeDtos = [];
+		}
+		editTrainTemplate(submitObj)
+			.then(() => {
+				emit('updateList');
+				closeDialog(); // 关闭弹窗
+				ElMessage.success('操作成功');
+				state.loading = false;
+			})
+			.catch(() => {
+				state.loading = false;
+			});
+	});
+};
+// 暴露变量
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>
+<style lang="scss">
+.tableFormItem .el-form-item__content {
+	display: block;
+}
+</style>

+ 62 - 57
src/views/examTrain/train/template/components/Template-optional.vue → src/views/examTrain/train/trainTemp/components/Train-temp-optional.vue

@@ -2,27 +2,34 @@
 	<el-dialog title="选择试题" v-model="dialogVisible" draggable append-to-body destroy-on-close width="800px">
 		<el-form :model="state.queryParams" ref="ruleDialogFormRef" inline @submit.native.prevent :disabled="state.loading" class="ruleDialogForm">
 			<el-form-item label="标签" prop="tagIds">
-                <el-tree-select
-                    v-model="state.queryParams.tagIds"
-                    :data="state.tagData"
-                    node-key="id"
-                    :props="{ label: 'name' }"
-                    multiple
-                    collapse-tags
-                    collapse-tags-tooltip
-                    :render-after-expand="false"
-                    style="width: 200px;"
-                    @change="handleQuery"
-                />
-            </el-form-item>
-            <el-form-item label="难易程度" prop="difficultyLevel">
-                <el-select v-model="state.queryParams.difficultyLevel" clearable placeholder="请选择" @change="handleQuery" :disabled="state.loading" style="width: 150px">
-                    <el-option key='0' label="容易" :value="0" />
-                    <el-option key='1' label="适中" :value="1" />
-                    <el-option key='2' label="困难" :value="2" />
-                </el-select>
-            </el-form-item>
-            <!-- <el-form-item label="难易程度" prop="questionType">
+				<el-tree-select
+					v-model="state.queryParams.tagIds"
+					:data="state.tagData"
+					node-key="id"
+					:props="{ label: 'name' }"
+					multiple
+					collapse-tags
+					collapse-tags-tooltip
+					:render-after-expand="false"
+					style="width: 200px"
+					@change="handleQuery"
+				/>
+			</el-form-item>
+			<el-form-item label="难易程度" prop="difficultyLevel">
+				<el-select
+					v-model="state.queryParams.difficultyLevel"
+					clearable
+					placeholder="请选择"
+					@change="handleQuery"
+					:disabled="state.loading"
+					style="width: 150px"
+				>
+					<el-option key="0" label="容易" :value="0" />
+					<el-option key="1" label="适中" :value="1" />
+					<el-option key="2" label="困难" :value="2" />
+				</el-select>
+			</el-form-item>
+			<!-- <el-form-item label="难易程度" prop="questionType">
                 <el-select v-model="state.queryParams.questionType" clearable placeholder="请选择" @change="handleQuery" :disabled="state.tableLoading">
                     <el-option key='0' label="单选题" :value="0" />
                     <el-option key='1' label="多选题" :value="1" />
@@ -53,8 +60,8 @@
 			>
 			<vxe-column type="checkbox" fixed="left" width="70" align="center"></vxe-column>
 			<vxe-column field="questionTypeDesc" title="题型" width="100"></vxe-column>
-            <vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
-            <vxe-column field="title" title="标题" min-width="150"></vxe-column>
+			<vxe-column field="difficultyLevelDesc" title="难度" width="100"></vxe-column>
+			<vxe-column field="title" title="标题" min-width="150"></vxe-column>
 		</vxe-table>
 		<pagination
 			@pagination="queryList"
@@ -75,10 +82,9 @@
 <script lang="ts" setup>
 import { defineAsyncComponent, reactive, ref } from 'vue';
 import { FormInstance } from 'element-plus';
-import { formatDate } from '@/utils/formatTime';
 import other from '@/utils/other';
-import {getQuestionData} from '@/api/examTrain/questionBank';
-import { examTagTreeList} from '@/api/examTrain/tag';
+import { getQuestionData } from '@/api/examTrain/questionBank';
+import { examTagTreeList } from '@/api/examTrain/tag';
 
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
@@ -94,10 +100,10 @@ const state = reactive({
 		PageIndex: 1, // 当前页
 		PageSize: 20, // 每页条数
 		tagIds: null, // 标签id集合
-        difficultyLevel: null, // 难易程度
-        knowladgeIds: [] as any [] // 关联的知识库id
+		difficultyLevel: null, // 难易程度
+		knowladgeIds: [] as any[], // 关联的知识库id
 	},
-	tableCheckbox: [] as any [], // 已选择的试题
+	tableCheckbox: [] as any[], // 已选择的试题
 	tagData: [], // 标签数据
 });
 const ruleDialogFormRef = ref<FormInstance>(); // 表单
@@ -108,24 +114,23 @@ const getTagData = async () => {
 	try {
 		const { result } = await examTagTreeList();
 		state.tagData = result ?? [];
-	} catch (error) {
-	}
+	} catch (error) {}
 };
 // 打开弹窗
 const openDialog = async (knowladgesData: any[], selData: any[]) => {
 	dialogVisible.value = true;
 	try {
-        if (knowladgesData) {
-			state.queryParams.knowladgeIds = knowladgesData.map(it => it.knowladgeId);
+		if (knowladgesData) {
+			state.queryParams.knowladgeIds = knowladgesData.map((it) => it.knowladgeId);
 		} else {
 			state.queryParams.knowladgeIds = [];
 		}
-        if (selData) {
+		if (selData) {
 			state.tableCheckbox = other.deepClone(selData);
 		} else {
 			state.tableCheckbox = [];
 		}
-	    getTagData();
+		getTagData();
 		queryList();
 	} catch (error) {
 		console.log(error);
@@ -145,11 +150,11 @@ const queryList = () => {
 			state.tableData = res.result?.items ?? [];
 			state.total = res.result?.pagination.totalCount ?? 0;
 			state.loading = false;
-            const rows = [] as any[];
-            state.tableCheckbox.forEach(item => {
-                rows.push(state.tableData.find(it => it.id === item.questionId));
-            })
-            tableRef.value.setCheckboxRow(rows, true);
+			const rows = [] as any[];
+			state.tableCheckbox.forEach((item) => {
+				rows.push(state.tableData.find((it) => it.id === item.questionId));
+			});
+			tableRef.value.setCheckboxRow(rows, true);
 		})
 		.catch(() => {
 			state.loading = false;
@@ -161,22 +166,22 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	handleQuery();
 };
 // 单个复选框点击
-const checkboxChangeEvent = ({row}) => {
-    let blog = 'add';
-    state.tableCheckbox.forEach(item => {
-        if(item.questionId == row.id){
-            blog = 'delete'
-        }
-    });
-    if (blog == 'add'){
-        const rowObj = other.deepClone(row);
-        rowObj.questionId = rowObj.id;
-        Reflect.deleteProperty(rowObj, 'id');
-        state.tableCheckbox.push(rowObj)
-    }else {
-        state.tableCheckbox = state.tableCheckbox.filter(it => it.questionId !== row.id )
-    }
-}
+const checkboxChangeEvent = ({ row }) => {
+	let blog = 'add';
+	state.tableCheckbox.forEach((item) => {
+		if (item.questionId == row.id) {
+			blog = 'delete';
+		}
+	});
+	if (blog == 'add') {
+		const rowObj = other.deepClone(row);
+		rowObj.questionId = rowObj.id;
+		Reflect.deleteProperty(rowObj, 'id');
+		state.tableCheckbox.push(rowObj);
+	} else {
+		state.tableCheckbox = state.tableCheckbox.filter((it) => it.questionId !== row.id);
+	}
+};
 // 关闭弹窗
 const closeDialog = () => {
 	dialogVisible.value = false;
@@ -191,6 +196,6 @@ defineExpose({ closeDialog, openDialog });
 </script>
 <style>
 .el-form--inline.ruleDialogForm .el-form-item .el-select {
-    min-width: 100px;
+	min-width: 100px;
 }
 </style>

+ 230 - 0
src/views/examTrain/train/trainTemp/index.vue

@@ -0,0 +1,230 @@
+<template>
+	<div class="exam-train-train-temp-index-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent :disabled="state.tableLoading">
+				<el-form-item label="模板编号" prop="code">
+					<el-input v-model="state.queryParams.code" placeholder="请输入" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="模板标题" prop="name">
+					<el-input v-model="state.queryParams.name" placeholder="请输入" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="包含习题" prop="isContainsPractice">
+					<el-select
+						v-model="state.queryParams.isContainsPractice"
+						clearable
+						placeholder="请选择"
+						@change="handleQuery"
+						:disabled="state.tableLoading"
+					>
+						<el-option key="0" label="包含" :value="0" />
+						<el-option key="1" label="不包含" :value="1" />
+					</el-select>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.tableLoading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+				<template #buttons>
+					<el-button type="primary" @click="onOpenAdd" v-auth="'examTrain:trainTemp:add'" :loading="state.tableLoading">
+						<SvgIcon name="ele-Plus" class="mr10" />新增
+					</el-button>
+				</template>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.tableLoading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:print-config="{}"
+					:scrollY="{ enabled: true, gt: 100 }"
+					id="examTrainTrainTemplate"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+				>
+					<vxe-column field="code" title="模板编号" width="200"></vxe-column>
+					<vxe-column field="name" title="模板标题" min-width="200"></vxe-column>
+					<vxe-column field="isContainsPracticeDes" title="是否包含习题" width="150"></vxe-column>
+					<!-- <vxe-column field="status" title="状态" width="160">
+                        <trainTemp #default="{ row }">
+                            <el-switch v-model="row.status" />
+                        </trainTemp>
+                    </vxe-column> -->
+					<vxe-column field="creatorName" title="创建人" width="150"></vxe-column>
+					<vxe-column field="creatorOrgName" title="创建部门" width="150"></vxe-column>
+					<vxe-column field="creationTime" title="创建时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="120" align="center" :show-overflow="false">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onOpenEdit(row)" title="编辑" v-auth="'examTrain:trainTemp:edit'"> 编辑 </el-button>
+							<el-button link type="danger" @click="onRowDel(row)" title="删除" v-auth="'examTrain:trainTemp:delete'"> 删除 </el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.tableLoading"
+			/>
+		</div>
+		<!--	更多查询	-->
+		<el-drawer v-model="drawer" title="更多查询" size="500px">
+			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
+				<el-form-item label="状态" prop="status">
+					<el-select v-model="state.queryParams.status" clearable placeholder="请选择" @change="handleQuery" :disabled="state.tableLoading">
+						<el-option key="0" label="停用" :value="0" />
+						<el-option key="1" label="启用" :value="1" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="创建人" prop="creatorName">
+					<el-input v-model="state.queryParams.creatorName" placeholder="请输入" clearable class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="创建时间>=" prop="minCreationTime">
+					<el-date-picker
+						v-model="state.queryParams.minCreationTime"
+						type="datetime"
+						class="w100"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						placeholder="请选择"
+						popper-class="no-atTheMoment"
+					/>
+				</el-form-item>
+				<el-form-item label="创建时间<=" prop="maxCreationTime">
+					<el-date-picker
+						v-model="state.queryParams.maxCreationTime"
+						type="datetime"
+						class="w100"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						placeholder="请选择"
+						popper-class="no-atTheMoment"
+					/>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+			</template>
+		</el-drawer>
+		<!--		新增模板-->
+		<train-temp-add ref="trainTemplateAddRef" @updateList="queryList" />
+		<!--		编辑模板-->
+		<train-temp-edit ref="trainTemplateEditRef" @updateList="queryList" />
+	</div>
+</template>
+
+<script lang="tsx" setup name="examTrainTrainTemplate">
+import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import type { FormInstance } from 'element-plus';
+import { formatDate } from '@/utils/formatTime';
+import 'splitpanes/dist/splitpanes.css';
+import Other from '@/utils/other';
+import { deleteTrainTemplate, getTrainTemplateData } from '@/api/examTrain/trainTemplate';
+
+// 引入组件
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const TrainTempAdd = defineAsyncComponent(() => import('@/views/examTrain/train/trainTemp/components/Train-temp-add.vue')); // 新增组件
+const TrainTempEdit = defineAsyncComponent(() => import('@/views/examTrain/train/trainTemp/components/Train-temp-edit.vue')); // 修改组件
+
+// 定义变量内容
+const state = reactive<any>({
+	queryParams: {
+		PageIndex: 1, //页码
+		PageSize: 20, //每页条数
+		code: null, // 编号
+		name: null, // 名称
+		status: null, // 状态
+		isContainsPractice: null, //  是否包含习题
+		creatorName: null, // 创建人
+		minCreationTime: null, // 创建时间>=
+		maxCreationTime: null, // 创建时间<=
+	},
+	tableData: [], //表格数据
+	total: 0, //总条数
+	tableLoading: false, //表格loading
+});
+/** 搜索按钮操作 节流操作 */
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+/** 获取试题列表 */
+const requestParams = ref<EmptyObjectType>({});
+const queryList = () => {
+	state.tableLoading = true;
+	requestParams.value = Other.deepClone(state.queryParams);
+	getTrainTemplateData(requestParams.value)
+		.then((response: any) => {
+			state.tableData = response?.result.items ?? [];
+			state.total = response?.result.pagination.totalCount ?? 0;
+			state.tableLoading = false;
+		})
+		.catch(() => {
+			state.tableLoading = false;
+		});
+};
+/** 重置按钮操作 */
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(); // 表单ref
+const drawer = ref(false);
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	ruleFormRef.value?.resetFields();
+	handleQuery();
+};
+// 打开新增弹窗
+const trainTemplateAddRef = ref<RefType>(); // 新增ref
+const onOpenAdd = () => {
+	trainTemplateAddRef.value.openDialog();
+};
+// 打开编辑弹窗
+const trainTemplateEditRef = ref<RefType>(); // 修改ref
+const onOpenEdit = (row: any) => {
+	trainTemplateEditRef.value.openDialog(row, state.tableData);
+};
+// 删除当前行
+const onRowDel = (row: any) => {
+	ElMessageBox.confirm(`是否确认删除当前培训模板?删除后不可恢复`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+	})
+		.then(() => {
+			deleteTrainTemplate({ id: row.id }).then(() => {
+				ElMessage.success('删除成功');
+				queryList();
+			});
+		})
+		.catch(() => {});
+};
+
+const tableRef = ref<RefType>();
+const toolbarRef = ref<RefType>();
+onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>