SelectQuestionDialog.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <template>
  2. <el-dialog
  3. class="select-question-dialog"
  4. :visible.sync="modalIsShow"
  5. :close-on-click-modal="false"
  6. :close-on-press-escape="false"
  7. :show-close="false"
  8. append-to-body
  9. fullscreen
  10. @open="visibleChange"
  11. >
  12. <div slot="title" class="box-justify">
  13. <h3>选择试题</h3>
  14. <el-button size="mini" type="primary" @click="confirm">确定</el-button>
  15. </div>
  16. <el-tabs
  17. v-model="tabType"
  18. class="part-box"
  19. type="card"
  20. @tab-click="tabChange"
  21. >
  22. <el-tab-pane name="1">
  23. <span slot="label">试题筛选</span>
  24. <div class="part-filter">
  25. <div class="part-filter-form">
  26. <el-form class="part-filter-form" :inline="true" :model="filter">
  27. <el-form-item label="题型">
  28. <source-detail-select
  29. v-model="filter"
  30. :course-id="filter.courseId"
  31. :disabled="disabledSourceDetail"
  32. >
  33. </source-detail-select>
  34. </el-form-item>
  35. <el-form-item label="题目内容">
  36. <el-input
  37. v-model="filter.questionBody"
  38. placeholder="题目内容"
  39. ></el-input>
  40. </el-form-item>
  41. <el-form-item label="属性">
  42. <property-tree-select
  43. v-model="filter.questionProperty"
  44. :course-id="filter.courseId"
  45. ></property-tree-select>
  46. </el-form-item>
  47. <el-form-item>
  48. <el-button type="danger" @click="toPage(1)">查询</el-button>
  49. </el-form-item>
  50. </el-form>
  51. </div>
  52. </div>
  53. <el-table :data="questions">
  54. <el-table-column
  55. width="60"
  56. type="index"
  57. :index="indexMethod"
  58. label="编号"
  59. >
  60. </el-table-column>
  61. <el-table-column label="题干">
  62. <div slot-scope="scope" @click="toViewQuestion(scope.row)">
  63. <rich-text
  64. class="row-question-body"
  65. title="点击查看试题"
  66. :text-json="scope.row.quesBody"
  67. ></rich-text>
  68. </div>
  69. </el-table-column>
  70. <el-table-column label="课程" width="120">
  71. <template slot-scope="scope">
  72. <span>{{ scope.row.course.name }}</span>
  73. </template>
  74. </el-table-column>
  75. <el-table-column label="题型" prop="sourceDetailName" width="100">
  76. </el-table-column>
  77. <el-table-column label="难度" prop="difficulty" width="80">
  78. </el-table-column>
  79. <el-table-column label="使用量" prop="usageAmount" width="80">
  80. </el-table-column>
  81. <el-table-column label="创建人" prop="creator" width="120">
  82. </el-table-column>
  83. <el-table-column label="创建时间" width="170" prop="creationTime">
  84. </el-table-column>
  85. <el-table-column label="操作" width="160" fixed="right">
  86. <div v-if="!scope.row.disabled" slot-scope="scope">
  87. <el-button
  88. v-if="scope.row.selected"
  89. size="mini"
  90. type="danger"
  91. @click="toDelete(scope.row)"
  92. >
  93. 删除
  94. </el-button>
  95. <el-button
  96. v-else
  97. size="mini"
  98. type="primary"
  99. plain
  100. @click="toSelect(scope.row)"
  101. >
  102. 添加
  103. </el-button>
  104. </div>
  105. </el-table-column>
  106. </el-table>
  107. <div class="part-page">
  108. <el-pagination
  109. background
  110. :current-page="currentPage"
  111. :page-size="pageSize"
  112. :page-sizes="[10, 20, 50, 100, 200, 300]"
  113. layout="total, sizes, prev, pager, next, jumper"
  114. :total="total"
  115. @current-change="toPage"
  116. @size-change="handleSizeChange"
  117. />
  118. </div>
  119. </el-tab-pane>
  120. <el-tab-pane name="2">
  121. <span slot="label">
  122. <span>已选试题</span>
  123. <span class="color-primary">({{ curSelectedQuestions.length }})</span>
  124. </span>
  125. <el-table :data="curSelectedQuestions" border>
  126. <el-table-column width="60" type="index" label="编号">
  127. </el-table-column>
  128. <el-table-column label="题干">
  129. <div slot-scope="scope" @click="toViewQuestion(scope.row)">
  130. <rich-text
  131. class="row-question-body"
  132. title="点击查看试题"
  133. :text-json="scope.row.quesBody"
  134. ></rich-text>
  135. </div>
  136. </el-table-column>
  137. <el-table-column label="课程" width="200">
  138. <template slot-scope="scope">
  139. <span>{{ scope.row.course.name }}</span>
  140. </template>
  141. </el-table-column>
  142. <el-table-column label="题型" prop="sourceDetailName" width="100">
  143. </el-table-column>
  144. <el-table-column label="难度" prop="difficulty" width="80">
  145. </el-table-column>
  146. <el-table-column label="使用量" prop="usageAmount" width="80">
  147. </el-table-column>
  148. <el-table-column label="创建人" prop="creator" width="120">
  149. </el-table-column>
  150. <el-table-column label="创建时间" width="170" prop="creationTime">
  151. </el-table-column>
  152. <el-table-column label="操作" width="160" fixed="right">
  153. <div slot-scope="scope">
  154. <el-button
  155. size="mini"
  156. type="danger"
  157. @click="toDeleteSelected(scope.row)"
  158. >
  159. 删除
  160. </el-button>
  161. </div>
  162. </el-table-column>
  163. </el-table>
  164. </el-tab-pane>
  165. </el-tabs>
  166. <div slot="footer"></div>
  167. <question-preview-dialog
  168. ref="QuestionPreviewDialog"
  169. :topic="curQuestion"
  170. ></question-preview-dialog>
  171. </el-dialog>
  172. </template>
  173. <script>
  174. import QuestionPreviewDialog from "../../question/components/QuestionPreviewDialog";
  175. import PropertyTreeSelect from "../../question/components/PropertyTreeSelect.vue";
  176. import { questionPageListApi } from "../../question/api";
  177. import { deepCopy } from "@/plugins/utils";
  178. export default {
  179. name: "SelectQuestionDialog",
  180. components: { QuestionPreviewDialog, PropertyTreeSelect },
  181. props: {
  182. courseId: {
  183. type: [String, Number],
  184. default: "",
  185. },
  186. sourceDetail: {
  187. type: Object,
  188. default() {
  189. return {
  190. questionType: "",
  191. sourceDetailId: "",
  192. };
  193. },
  194. },
  195. disabledSourceDetail: {
  196. type: Boolean,
  197. default: false,
  198. },
  199. selectedQuestionIds: {
  200. type: Array,
  201. default() {
  202. return [];
  203. },
  204. },
  205. disabledQuestionIds: {
  206. type: Array,
  207. default() {
  208. return [];
  209. },
  210. },
  211. },
  212. data() {
  213. return {
  214. modalIsShow: false,
  215. filter: {
  216. courseId: "",
  217. questionType: "",
  218. sourceDetailId: "",
  219. questionBody: "",
  220. questionProperty: [],
  221. },
  222. tabType: "1",
  223. tableData: [],
  224. currentPage: 1,
  225. pageSize: 10,
  226. total: 10,
  227. questions: [],
  228. curSelectedQuestions: [],
  229. curSelectedQuestionIds: [],
  230. curQuestion: {},
  231. };
  232. },
  233. methods: {
  234. initData() {
  235. this.filter = Object.assign({}, this.filter, {
  236. courseId: this.courseId,
  237. questionType: this.sourceDetail.questionType,
  238. sourceDetailId: this.sourceDetail.sourceDetailId,
  239. });
  240. this.curSelectedQuestions = [];
  241. this.curSelectedQuestionIds = [];
  242. this.toPage(this.currentPage);
  243. },
  244. visibleChange() {
  245. this.initData();
  246. },
  247. cancel() {
  248. this.modalIsShow = false;
  249. },
  250. open() {
  251. this.modalIsShow = true;
  252. },
  253. async getList() {
  254. let data = {
  255. ...this.filter,
  256. pageNumber: this.currentPage,
  257. pageSize: this.pageSize,
  258. };
  259. data.questionProperty = data.questionProperty.join();
  260. const res = await questionPageListApi(data).catch(() => {});
  261. this.questions = res.data.content.map((item) => {
  262. return {
  263. ...item,
  264. selected: this.curSelectedQuestionIds.includes(item.id),
  265. disabled: this.disabledQuestionIds.includes(item.id),
  266. };
  267. });
  268. this.total = res.total;
  269. },
  270. indexMethod(index) {
  271. return index + (this.currentPage - 1) * this.pageSize + 1;
  272. },
  273. toPage(val) {
  274. this.currentPage = val;
  275. this.getList();
  276. },
  277. handleSizeChange(val) {
  278. this.pageSize = val;
  279. this.currentPage = 1;
  280. this.getList();
  281. },
  282. tabChange(val) {
  283. if (val.name === "1") {
  284. this.questions.forEach((item) => {
  285. item.selected = this.curSelectedQuestionIds.includes(item.id);
  286. });
  287. }
  288. },
  289. toViewQuestion(row) {
  290. this.curQuestion = row;
  291. this.$refs.QuestionPreviewDialog.open();
  292. },
  293. toSelect(row) {
  294. row.selected = true;
  295. this.curSelectedQuestions.push({ ...row });
  296. this.updateSelectedQuestionIds();
  297. },
  298. toDelete(row) {
  299. row.selected = false;
  300. this.toDeleteSelected(row);
  301. },
  302. toDeleteSelected(row) {
  303. const pos = this.curSelectedQuestions.findIndex(
  304. (item) => item.id === row.id
  305. );
  306. this.curSelectedQuestions.splice(pos, 1);
  307. this.updateSelectedQuestionIds();
  308. },
  309. updateSelectedQuestionIds() {
  310. this.curSelectedQuestionIds = this.curSelectedQuestions.map(
  311. (item) => item.id
  312. );
  313. },
  314. confirm() {
  315. this.$emit("confirm", deepCopy(this.curSelectedQuestions));
  316. this.cancel();
  317. },
  318. },
  319. };
  320. </script>