detail.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <div id="detail">
  3. <detail-frame :title="mainTitle" returns="./index">
  4. <el-form ref="infoForm" :model="info" label-width="120px" :rules="rules" size="small" @submit.native.prevent
  5. style="background:#fff;padding:50px">
  6. <el-form-item label="序号" required prop="num">
  7. <el-input v-model="info.num"></el-input>
  8. </el-form-item>
  9. <el-form-item label="标题" required prop="name">
  10. <el-input v-model="info.name"></el-input>
  11. </el-form-item>
  12. <el-form-item label="问卷类型" required prop="type">
  13. <el-radio-group v-model="info.type">
  14. <el-radio label="0">常用问卷</el-radio>
  15. <el-radio label="1">非常用问卷</el-radio>
  16. <el-radio label="2">教师问卷</el-radio>
  17. </el-radio-group>
  18. </el-form-item>
  19. <el-form-item label="状态" required prop="type">
  20. <el-radio-group v-model="info.status">
  21. <el-radio label="0" v-if="isNew == true">草稿</el-radio>
  22. <el-radio label="1">发布</el-radio>
  23. <el-radio label="2">禁用</el-radio>
  24. </el-radio-group>
  25. </el-form-item>
  26. <el-form-item label="题目" prop="question">
  27. <el-row>
  28. <el-col :span="24" style="text-align:right;padding-bottom:10px">
  29. <el-button type="primary" size="mini" @click="addQuestion()" v-if="isNew == true">添加题目</el-button>
  30. </el-col>
  31. <el-col :span="24">
  32. <el-table :data="info.question" border stripe size="mini">
  33. <el-table-column align="center" label="标题" prop="topic"></el-table-column>
  34. <!-- :formatter="codeDisplay" -->
  35. <el-table-column align="center" label="类型" prop="type" :formatter="typeFormat"></el-table-column>
  36. <el-table-column align="center" label="操作">
  37. <template v-slot="{ row, $index }">
  38. <el-tooltip effect="dark" content="删除" placement="bottom">
  39. <el-button type="text" size="mini" icon="el-icon-delete"
  40. @click="toCdelete(row, $index)"></el-button>
  41. </el-tooltip>
  42. </template>
  43. </el-table-column>
  44. </el-table>
  45. </el-col>
  46. </el-row>
  47. </el-form-item>
  48. <el-form-item>
  49. <el-row type="flex" justify="center">
  50. <el-col :span="6">
  51. <el-button type="primary" @click="handleSave">保&nbsp;&nbsp;&nbsp;&nbsp;存</el-button>
  52. </el-col>
  53. <el-col :span="6">
  54. <el-button @click="$refs.infoForm.resetFields()">重&nbsp;&nbsp;&nbsp;&nbsp;置</el-button>
  55. </el-col>
  56. </el-row>
  57. </el-form-item>
  58. </el-form>
  59. </detail-frame>
  60. <el-dialog :visible.sync="dialog" title="题库" center>
  61. <el-row>
  62. <el-col :span="24" style="text-align:center;padding-bottom:20px">已选择{{ this.info.question.length }}道题</el-col>
  63. <el-col :span="24">
  64. <el-table v-loading="qProp.loading" ref="selectTable" :data="qList" @select="handleSelect"
  65. @select-all="handleSelectAll" border stripe size="mini" :height="350" row-key="id">
  66. <el-table-column type="selection" align="center" width="55" :reserve-selection="true"> </el-table-column>
  67. <el-table-column label="题目" align="center" prop="topic"></el-table-column>
  68. <el-table-column label="类型" align="center" prop="type" :formatter="typeFormat"></el-table-column>
  69. </el-table>
  70. </el-col>
  71. </el-row>
  72. <el-row type="flex" justify="center">
  73. <el-col :span="2" style="padding-top:20px">
  74. <el-button type="primary" plain size="mini" @click="dialog = false">关&nbsp;&nbsp;&nbsp;&nbsp;闭</el-button>
  75. </el-col>
  76. </el-row>
  77. </el-dialog>
  78. </div>
  79. </template>
  80. <script>
  81. import detailFrame from '@frame/layout/admin/detail-frame';
  82. import { createNamespacedHelpers } from 'vuex';
  83. import _ from 'lodash';
  84. const { mapActions } = createNamespacedHelpers('questionnaire');
  85. const { mapActions: mapQuestion } = createNamespacedHelpers('question');
  86. export default {
  87. metaInfo: { title: '问卷详情页' },
  88. name: 'detail',
  89. props: {},
  90. components: {
  91. detailFrame,
  92. },
  93. data: () => ({
  94. info: { question: [] },
  95. dialog: true,
  96. loading: true,
  97. rules: {
  98. num: [{ required: true, message: '请输入序号' }],
  99. name: [{ required: true, message: '请输入标题' }],
  100. type: [{ required: true, message: '请选择问卷类型' }],
  101. // question: [{ required: true, message: '请选择题目' }],
  102. },
  103. qList: [], //题库
  104. qProp: {
  105. loading: true,
  106. page: 1,
  107. total: 0,
  108. pageSize: 5,
  109. },
  110. }),
  111. async created() {
  112. this.dialog = false;
  113. await this.getOtherList();
  114. },
  115. computed: {
  116. id() {
  117. return this.$route.query.id;
  118. },
  119. isNew() {
  120. return this.$route.query.id ? false : true;
  121. },
  122. mainTitle() {
  123. let meta = this.$route.meta;
  124. let main = meta.title || '';
  125. let sub = meta.sub || '';
  126. return `${main}${sub}`;
  127. },
  128. keyWord() {
  129. let meta = this.$route.meta;
  130. let main = meta.title || '';
  131. return main;
  132. },
  133. },
  134. watch: {
  135. isNew: {
  136. immediate: true,
  137. handler(val) {
  138. if (val) this.loading = false;
  139. else this.search();
  140. },
  141. },
  142. },
  143. methods: {
  144. ...mapActions(['fetch', 'create', 'update']),
  145. ...mapQuestion({ qQuery: 'query' }),
  146. async search({ skip = 0, limit = 10, ...info } = {}) {
  147. const res = await this.fetch(this.id);
  148. if (this.$checkRes(res)) {
  149. console.log(res.data);
  150. this.$set(this, `info`, res.data);
  151. //需要将code中的id转换为题目重新放进列表中
  152. //需要过滤出已选择的题目,每次选择题目时也需要过滤
  153. }
  154. this.loading = false;
  155. },
  156. // 分页
  157. pagChange(size = this.qProp.pageSize, page = this.qProp.page) {
  158. this.qProp.pageSize = size;
  159. this.qProp.page = page;
  160. let skip = (this.qProp.page - 1) * this.qProp.pageSize;
  161. this.getOtherList({ skip, limit: size });
  162. },
  163. // 分页
  164. async getOtherList() {
  165. this.qProp.loading = true;
  166. const res = await this.qQuery();
  167. if (this.$checkRes(res)) {
  168. this.$set(this, `qList`, res.data);
  169. this.$set(this.qProp, `total`, res.total);
  170. }
  171. this.qProp.loading = false;
  172. },
  173. //打开添加题目dialog
  174. addQuestion() {
  175. this.dialog = true;
  176. this.$nextTick(() => {
  177. this.setNewTableSelect();
  178. });
  179. },
  180. toCdelete(row, index) {
  181. this.info.question.splice(index, 1);
  182. this.setNewTableSelect();
  183. },
  184. // 刷新选择题库的表格选择状态
  185. setNewTableSelect() {
  186. this.$refs.selectTable.clearSelection();
  187. if (this.info.question.length > 0) {
  188. for (const item of this.info.question) {
  189. let res = this.qList.filter(fil => fil.id === item.id);
  190. if (res.length > 0) this.$refs.selectTable.toggleRowSelection(res[0]);
  191. }
  192. }
  193. },
  194. // 题库操作
  195. handleSelect(selection, row) {
  196. if (selection.length > 0) {
  197. let data = this.info.question.concat(selection);
  198. data = _.unionBy(data, 'id');
  199. this.$set(this.info, `question`, data);
  200. } else {
  201. this.$set(this.info, `question`, []);
  202. }
  203. },
  204. //全选
  205. handleSelectAll(selection) {
  206. let data = this.info.question.concat(selection);
  207. data = _.unionBy(data, 'id');
  208. this.$set(this.info, `question`, selection);
  209. },
  210. //提交操作
  211. handleSave() {
  212. this.$refs['infoForm'].validate(valid => {
  213. if (valid) {
  214. this.toSave();
  215. } else {
  216. console.warn('form validate error!!!');
  217. }
  218. });
  219. },
  220. async toSave() {
  221. let res;
  222. let msg;
  223. let data = JSON.parse(JSON.stringify(this.info));
  224. let ids = data.question.map(item => item.id || item._id);
  225. data.question = ids;
  226. if (this.isNew) {
  227. res = await this.create(data);
  228. msg = `${this.keyWord}添加成功`;
  229. } else {
  230. res = await this.update(data);
  231. msg = `${this.keyWord}修改成功`;
  232. }
  233. if (this.$checkRes(res, msg)) this.$router.push({ path: '/questionnaire/index' });
  234. },
  235. // format转换
  236. codeDisplay(row, column, cellValue, index) {
  237. let cell = '';
  238. let prop = column.property;
  239. let res = this.qList.filter(fil => fil.id === row);
  240. if (res.length > 0) {
  241. if (prop === 'type') cell = this.typeFormat(null, null, _.get(res[0], prop, ''));
  242. else cell = _.get(res[0], prop, '');
  243. }
  244. return cell;
  245. },
  246. typeFormat(row, column, cellValue, index) {
  247. return cellValue === '0' ? '单选' : cellValue === '1' ? '多选' : '简答';
  248. },
  249. },
  250. };
  251. </script>
  252. <style lang="less" scoped></style>