|
@@ -2,37 +2,323 @@
|
|
|
<div id="questions">
|
|
|
<el-row>
|
|
|
<el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
|
|
|
- <el-col :span="24" class="one">系统首页</el-col>
|
|
|
+ <el-col :span="24" class="one">
|
|
|
+ <cSearch :is_title="false" :is_back="true" @toBack="toBack"></cSearch>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" class="two">
|
|
|
+ <cButton @toAdd="toAdd"></cButton>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" class="thr">
|
|
|
+ <el-col :span="24" class="thr_1">{{ form.title }}</el-col>
|
|
|
+ <el-col :span="24" class="thr_2">
|
|
|
+ <el-col :span="24" class="list" v-for="(i, index) in form.questions" :key="index">
|
|
|
+ <el-col :span="24" class="list_1">
|
|
|
+ <span>{{ index + 1 }}.</span>
|
|
|
+ <span>{{ i.title }}</span>
|
|
|
+ <el-button type="danger" size="small" @click="fseDel(i)">删除</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" class="list_2">
|
|
|
+ <template v-if="i.type == '1'">
|
|
|
+ <el-radio v-for="(t, tindex) in i.selects" :key="tindex" :label="t.value">{{ t.label }}</el-radio>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="i.type == '2'">
|
|
|
+ <el-checkbox v-for="(y, yindex) in i.selects" :key="yindex" :label="y.label" />
|
|
|
+ </template>
|
|
|
+ <template v-else-if="i.type == '3'">
|
|
|
+ <el-input placeholder="请输入内容" type="textarea" :disabled="true"></el-input>
|
|
|
+ </template>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
+ </el-col>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
+ <cDialog :dialog="dialog" @toClose="toClose">
|
|
|
+ <template v-slot:info>
|
|
|
+ <el-col :span="24" class="dialog_one" v-if="dialog.type == '1'">
|
|
|
+ <cForm :span="24" :fields="quesfields" :form="quesform" :rules="{}" @save="toSave" label-width="auto" @dataChange="dataChange">
|
|
|
+ <template #addType>
|
|
|
+ <el-radio v-for="(i, index) in addtypeList" :key="index" :label="i.value">{{ i.label }}</el-radio>
|
|
|
+ </template>
|
|
|
+ <!-- 选择题目 -->
|
|
|
+ <template #questionList>
|
|
|
+ <el-select
|
|
|
+ v-model="quesform.questionList"
|
|
|
+ value-key="_id"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="4"
|
|
|
+ placeholder="请选择"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option v-for="i in copyquestionList" :key="i._id" :label="i.title" :value="i">
|
|
|
+ <span style="float: left">{{ i.title }}</span>
|
|
|
+ <span style="float: right">{{ getDict(i.type, 'type') }}</span>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ <!-- 添加题目 -->
|
|
|
+ <template #type>
|
|
|
+ <el-radio v-for="(i, index) in typeList" :key="index" :label="i.value">{{ i.label }}</el-radio>
|
|
|
+ </template>
|
|
|
+ <template #selects>
|
|
|
+ <el-row class="selects" v-if="quesform.type != '3'">
|
|
|
+ <el-col :span="24" class="selects_1">
|
|
|
+ <el-button type="primary" @click="seAdd">添加</el-button>
|
|
|
+ <el-button type="primary" @click="seSort">刷新排序</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-table :data="quesform.selects" style="width: 100%" border>
|
|
|
+ <el-table-column type="index" label="序号" width="100" align="center"> </el-table-column>
|
|
|
+ <el-table-column label="标签" align="center">
|
|
|
+ <template #default="scope: any">
|
|
|
+ <el-input v-model="scope.row.label" placeholder="请输入标签" clearable />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="键值" align="center">
|
|
|
+ <template #default="scope: any">
|
|
|
+ <el-input v-model="scope.row.value" placeholder="请输入标签" clearable />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="排序" align="center">
|
|
|
+ <template #default="scope: any">
|
|
|
+ <el-input v-model="scope.row.sort" type="number" placeholder="请输入排序" clearable />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center" width="100">
|
|
|
+ <template v-slot="scope: any">
|
|
|
+ <el-button size="mini" type="danger" @click="seDel(scope.row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </template>
|
|
|
+ </cForm>
|
|
|
+ </el-col>
|
|
|
+ </template>
|
|
|
+ </cDialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
// 基础
|
|
|
+import moment from 'moment';
|
|
|
+import _ from 'lodash';
|
|
|
import type { Ref } from 'vue';
|
|
|
-// reactive,
|
|
|
-import { onMounted, ref, getCurrentInstance } from 'vue';
|
|
|
+import { onMounted, ref } from 'vue';
|
|
|
+import { useRoute } from 'vue-router';
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
+
|
|
|
// 接口
|
|
|
-//import { TestStore } from '@common/src/stores/test';
|
|
|
-//import type { IQueryResult } from '@/util/types.util';
|
|
|
-//const testAxios = TestStore();
|
|
|
-const { proxy } = getCurrentInstance() as any;
|
|
|
+import { QuestionnaireStore } from '@common/src/stores/question/questionnaire'; //
|
|
|
+import { QuestionStore } from '@common/src/stores/question/question'; //
|
|
|
+import { DictDataStore } from '@common/src/stores/system/dictData'; // 字典表
|
|
|
+import type { IQueryResult } from '@/util/types.util';
|
|
|
+const qnaireAxios = QuestionnaireStore();
|
|
|
+const qquesAxios = QuestionStore();
|
|
|
+const dictAxios = DictDataStore();
|
|
|
+
|
|
|
+// 路由
|
|
|
+const route = useRoute();
|
|
|
// 加载中
|
|
|
const loading: Ref<any> = ref(false);
|
|
|
-// 分页数据
|
|
|
-// const skip = 0;
|
|
|
-// const limit = proxy.limit;;
|
|
|
+
|
|
|
+const form: Ref<any> = ref({ questions: [] });
|
|
|
+
|
|
|
+// 弹框
|
|
|
+const dialog: Ref<any> = ref({ title: '题目管理', show: false, type: '1' });
|
|
|
+// 题库管理
|
|
|
+const quesform: Ref<any> = ref({ selects: [] });
|
|
|
+const quesfields: Ref<any> = ref([{ label: '添加题目方式', model: 'addType', type: 'radio' }]);
|
|
|
+
|
|
|
+// 字典表
|
|
|
+const addtypeList: Ref<any> = ref([
|
|
|
+ {
|
|
|
+ label: '选择题库',
|
|
|
+ value: '0'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '手动添加',
|
|
|
+ value: '1'
|
|
|
+ }
|
|
|
+]);
|
|
|
+const typeList: Ref<any> = ref([]);
|
|
|
+const questionList: Ref<any> = ref([]);
|
|
|
+const copyquestionList: Ref<any> = ref([]);
|
|
|
+
|
|
|
// 请求
|
|
|
onMounted(async () => {
|
|
|
loading.value = true;
|
|
|
- // await search({ skip, limit });
|
|
|
+ await searchOther();
|
|
|
+ await search();
|
|
|
loading.value = false;
|
|
|
});
|
|
|
-//const search = async (e: { skip: number; limit: number }) => {
|
|
|
-// const info = { skip: e.skip, limit: e.limit, ...searchInfo.value };
|
|
|
-// const res: IQueryResult = await testAxios.query(info);
|
|
|
-// console.log(res);
|
|
|
-//};
|
|
|
+const search = async () => {
|
|
|
+ let id = route.query.id;
|
|
|
+ let info: any = { questions: [] };
|
|
|
+ if (id) {
|
|
|
+ let res: IQueryResult = await qnaireAxios.fetch(id);
|
|
|
+ if (res.errcode == '0') {
|
|
|
+ info = res.data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ form.value = info;
|
|
|
+};
|
|
|
+const getDict = (e, model) => {
|
|
|
+ if (model == 'type') {
|
|
|
+ let data: any = typeList.value.find((i: any) => i.value == e);
|
|
|
+ if (data) return data.label;
|
|
|
+ else return '暂无';
|
|
|
+ }
|
|
|
+};
|
|
|
+// 添加
|
|
|
+const toAdd = () => {
|
|
|
+ dialog.value = { title: '题库管理', show: true, type: '1' };
|
|
|
+};
|
|
|
+// 选择类型
|
|
|
+const dataChange = (e: { value; model }) => {
|
|
|
+ if (e.model == 'addType') {
|
|
|
+ let list: any = [];
|
|
|
+ if (e.value == '0') {
|
|
|
+ // 过滤数据
|
|
|
+ getonequesList();
|
|
|
+ // 处理表单fields
|
|
|
+ quesfields.value = quesfields.value.filter((i) => i.model == 'addType');
|
|
|
+ // 新增
|
|
|
+ list = [{ label: '题库列表', model: 'questionList', custom: true }];
|
|
|
+ } else if (e.value == '1') {
|
|
|
+ // 处理表单fields
|
|
|
+ quesfields.value = quesfields.value.filter((i) => i.model == 'addType');
|
|
|
+ // 新增
|
|
|
+ list = [
|
|
|
+ { label: '类型', model: 'type', type: 'radio' },
|
|
|
+ { label: '标题', model: 'title' },
|
|
|
+ { label: '选项', model: 'selects', custom: true }
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ quesfields.value = [...quesfields.value, ...list];
|
|
|
+ }
|
|
|
+};
|
|
|
+// 过滤数据
|
|
|
+const getonequesList = () => {
|
|
|
+ let qList: any = [];
|
|
|
+ if (form.value && form.value.questions && form.value.questions.length > 0) {
|
|
|
+ let p1 = form.value.questions.map((i) => i._id);
|
|
|
+ qList = questionList.value.filter((i) => p1.indexOf(i._id) === -1) || [];
|
|
|
+ } else {
|
|
|
+ qList = questionList.value;
|
|
|
+ }
|
|
|
+ copyquestionList.value = qList;
|
|
|
+};
|
|
|
+// 手动添加
|
|
|
+// 添加
|
|
|
+const seAdd = () => {
|
|
|
+ quesform.value.selects.push({ _id: moment().valueOf(), label: '', value: '', sort: '' });
|
|
|
+};
|
|
|
+// 删除
|
|
|
+const seDel = (data) => {
|
|
|
+ quesform.value.selects = form.value.selects.filter((i) => i._id != data._id);
|
|
|
+};
|
|
|
+// 刷新排序
|
|
|
+const seSort = () => {
|
|
|
+ let selects = _.sortBy(quesform.value.selects, ['sort']);
|
|
|
+ quesform.value.selects = selects;
|
|
|
+};
|
|
|
+// 提交保存
|
|
|
+const toSave = async (data) => {
|
|
|
+ let object: any = form.value;
|
|
|
+ if (data.addType == '0') {
|
|
|
+ object.questions = [...object.questions, ...data.questionList];
|
|
|
+ } else if (data.addType == '1') {
|
|
|
+ object.questions = [...object.questions, { _id: data._id, title: data.title, type: data.type, selects: data.selects }];
|
|
|
+ }
|
|
|
+ toSubmit(object);
|
|
|
+};
|
|
|
+const toSubmit = async (object) => {
|
|
|
+ let res: IQueryResult = await qnaireAxios.update(object);
|
|
|
+ if (res.errcode == '0') {
|
|
|
+ ElMessage({ message: '题库信息维护成功', type: 'success' });
|
|
|
+ toClose();
|
|
|
+ } else {
|
|
|
+ ElMessage({ message: `${res.errmsg}`, type: 'error' });
|
|
|
+ }
|
|
|
+};
|
|
|
+// 关闭弹框
|
|
|
+const toClose = () => {
|
|
|
+ quesform.value = { selects: [] };
|
|
|
+ quesfields.value = [{ label: '类型', model: 'addType', type: 'radio' }];
|
|
|
+ search();
|
|
|
+ dialog.value = { title: '题库管理', show: false, type: '1' };
|
|
|
+};
|
|
|
+// 选项删除
|
|
|
+const fseDel = (data) => {
|
|
|
+ let object = form.value;
|
|
|
+ ElMessageBox.confirm('确认要删除此信息吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
|
|
+ .then(() => {
|
|
|
+ object.questions = object.questions.filter((i) => i._id != data._id);
|
|
|
+ toSubmit(object);
|
|
|
+ })
|
|
|
+ .catch(() => {});
|
|
|
+};
|
|
|
+const searchOther = async () => {
|
|
|
+ let res: IQueryResult;
|
|
|
+ // 题库
|
|
|
+ res = await qquesAxios.query({ is_use: '0' });
|
|
|
+ if (res.errcode == '0') {
|
|
|
+ questionList.value = res.data;
|
|
|
+ }
|
|
|
+ // 类型
|
|
|
+ res = await dictAxios.query({ type: 'wenjuan-question-type' });
|
|
|
+ if (res.errcode == '0') {
|
|
|
+ console.log(res.data);
|
|
|
+ typeList.value = res.data;
|
|
|
+ }
|
|
|
+};
|
|
|
+// 返回上一步
|
|
|
+const toBack = () => {
|
|
|
+ window.history.go(-1);
|
|
|
+};
|
|
|
</script>
|
|
|
-<style scoped lang="scss"></style>
|
|
|
+<style scoped lang="scss">
|
|
|
+.main {
|
|
|
+ .two {
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ }
|
|
|
+ .thr {
|
|
|
+ .thr_1 {
|
|
|
+ text-align: center;
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ font-family: monospace;
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ }
|
|
|
+ .thr_2 {
|
|
|
+ border: 2px solid #000000;
|
|
|
+ padding: 10px;
|
|
|
+ border-radius: 5px;
|
|
|
+ .list {
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ .list_1 {
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ span {
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ span:nth-child(2) {
|
|
|
+ display: inline-block;
|
|
|
+ margin: 0 10px 0 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .list_2 {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.selects {
|
|
|
+ .selects_1 {
|
|
|
+ margin: 0 0 10px 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|