Question.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <template>
  2. <section class="content">
  3. <div class="part-box">
  4. <h2 class="part-box-title">试题列表</h2>
  5. <el-form class="part-filter-form" :inline="true" :model="formSearch">
  6. <el-form-item label="课程名称">
  7. <el-select
  8. v-model="formSearch.courseId"
  9. filterable
  10. :remote-method="getCourses"
  11. remote
  12. clearable
  13. placeholder="请选择"
  14. @change="getCoursesProperty('')"
  15. @clear="getCourses('')"
  16. >
  17. <el-option
  18. v-for="item in courseInfoSelect"
  19. :key="item.courseId"
  20. :label="item.courseInfo"
  21. :value="item.courseId"
  22. >
  23. </el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="层次">
  27. <el-select
  28. v-model="formSearch.courseLevel"
  29. filterable
  30. clearable
  31. placeholder="请选择"
  32. >
  33. <el-option
  34. v-for="item in levelList"
  35. :key="item.value"
  36. :label="item.label"
  37. :value="item.value"
  38. >
  39. </el-option>
  40. </el-select>
  41. </el-form-item>
  42. <el-form-item label="题型">
  43. <el-select
  44. v-model="formSearch.questionType"
  45. filterable
  46. clearable
  47. placeholder="请选择"
  48. >
  49. <el-option
  50. v-for="item in questionTypes"
  51. :key="item.value"
  52. :label="item.label"
  53. :value="item.value"
  54. >
  55. </el-option>
  56. </el-select>
  57. </el-form-item>
  58. <el-form-item label="属性名">
  59. <el-select
  60. v-model="formSearch.coursePropertyId"
  61. :remote-method="getCoursesProperty"
  62. :loading="coursePropertyLoading"
  63. remote
  64. filterable
  65. clearablee
  66. :disabled="updatePorperty"
  67. placeholder="请选择"
  68. @change="searchFirst"
  69. >
  70. <el-option
  71. v-for="item in coursePropertyList"
  72. :key="item.id"
  73. :label="item.name"
  74. :value="item.id"
  75. ></el-option>
  76. </el-select>
  77. </el-form-item>
  78. <!-- created by wwh -->
  79. <el-form-item label="一级属性">
  80. <el-select
  81. v-model="formSearch.firstPropertyId"
  82. filterable
  83. clearable
  84. :disabled="updateFirst"
  85. placeholder="请选择"
  86. @change="searchSecond"
  87. >
  88. <el-option
  89. v-for="item in firstPropertyList"
  90. :key="item.id"
  91. :label="item.name"
  92. :value="item.id"
  93. ></el-option>
  94. </el-select>
  95. </el-form-item>
  96. <el-form-item label="二级属性">
  97. <el-select
  98. v-model="formSearch.secondPropertyId"
  99. filterable
  100. clearable
  101. :disabled="updateSecond"
  102. placeholder="请选择"
  103. >
  104. <el-option
  105. v-for="item in secondPropertyList"
  106. :key="item.id"
  107. :label="item.name"
  108. :value="item.id"
  109. ></el-option>
  110. </el-select>
  111. </el-form-item>
  112. <el-form-item label="公开度">
  113. <el-select
  114. v-model="formSearch.publicity"
  115. filterable
  116. clearable
  117. placeholder="请选择"
  118. >
  119. <el-option
  120. v-for="item in publicityList"
  121. :key="item.value"
  122. :label="item.label"
  123. :value="item.value"
  124. >
  125. </el-option>
  126. </el-select>
  127. </el-form-item>
  128. <el-form-item>
  129. <el-button type="danger" @click="searchFrom">查询</el-button>
  130. <el-button type="danger" plain @click="resetForm">重置</el-button>
  131. </el-form-item>
  132. </el-form>
  133. </div>
  134. <div class="part-box">
  135. <!-- 页面列表 -->
  136. <el-table v-loading="loading" :data="tableData">
  137. <el-table-column label="课程" width="180">
  138. <template slot-scope="scope">
  139. <span>{{ scope.row.course.name }}</span>
  140. </template>
  141. </el-table-column>
  142. <el-table-column label="层次" width="100">
  143. <template slot-scope="scope">
  144. <span>{{ getLevel(scope.row.course.level) }}</span>
  145. </template>
  146. </el-table-column>
  147. <el-table-column label="题型" width="100">
  148. <template slot-scope="scope">
  149. <span>{{ scope.row.questionType | questionType }}</span>
  150. </template>
  151. </el-table-column>
  152. <el-table-column label="题干">
  153. <template slot-scope="scope">
  154. <rich-text
  155. class="row-question-body"
  156. title="点击查看试题"
  157. :text-json="scope.row.quesBody"
  158. @click="prevViewQues(scope.row)"
  159. ></rich-text>
  160. </template>
  161. </el-table-column>
  162. <el-table-column label="操作" width="160">
  163. <template slot-scope="scope">
  164. <div class="operate_left">
  165. <el-button
  166. v-if="!isNested(scope.row.questionType)"
  167. size="mini"
  168. type="primary"
  169. plain
  170. @click="updateRow(scope.row)"
  171. >
  172. 编辑
  173. </el-button>
  174. <el-button
  175. size="mini"
  176. type="danger"
  177. plain
  178. @click="deleteRow(scope.row)"
  179. >
  180. 删除
  181. </el-button>
  182. </div>
  183. </template>
  184. </el-table-column>
  185. </el-table>
  186. <div class="part-page">
  187. <el-pagination
  188. :current-page="currentPage"
  189. :page-size="pageSize"
  190. :page-sizes="[10, 20, 50, 100, 200, 300]"
  191. layout="total, sizes, prev, pager, next, jumper"
  192. :total="total"
  193. @current-change="handleCurrentChange"
  194. @size-change="handleSizeChange"
  195. >
  196. </el-pagination>
  197. </div>
  198. </div>
  199. <!-- 试题预览 -->
  200. <question-preview
  201. ref="QuestionPreview"
  202. :ques-model="quesModel"
  203. ></question-preview>
  204. <el-dialog title="提示" :visible.sync="deleteDialogVisible" append-to-body>
  205. <span>{{ deleteInfo }}</span>
  206. <span slot="footer" class="dialog-footer">
  207. <el-button type="primary" @click="deleteDialogVisible = false"
  208. >确定</el-button
  209. >
  210. </span>
  211. </el-dialog>
  212. </section>
  213. </template>
  214. <script>
  215. import { QUESTION_API } from "@/constants/constants";
  216. import { QUESTION_TYPES, LEVEL_TYPE } from "../constants/constants";
  217. import { mapState } from "vuex";
  218. import QuestionPreview from "./QuestionPreview";
  219. export default {
  220. name: "QuestionList",
  221. components: { QuestionPreview },
  222. data() {
  223. return {
  224. coursePropertyLoading: false,
  225. formSearch: {
  226. questionType: "",
  227. courseId: null,
  228. courseLevel: "",
  229. publicity: "",
  230. coursePropertyId: null,
  231. firstPropertyId: null,
  232. secondPropertyId: null,
  233. },
  234. courseList: [], //课程list
  235. levelList: LEVEL_TYPE, //层次list
  236. tableData: [],
  237. currentPage: 1,
  238. pageSize: 10,
  239. total: 10,
  240. quesModel: {},
  241. questionTypes: [],
  242. quesDialog: false,
  243. loading: false,
  244. deleteDialogVisible: false,
  245. deleteInfo: "",
  246. singleRightAnswer: "", //接收单选答案
  247. multipleRightAnswer: [], //接收多选答案
  248. publicityList: [
  249. { label: "公开", value: true },
  250. { label: "非公开", value: false },
  251. ],
  252. coursePropertyList: [], //课程属性集合
  253. firstPropertyList: [], //一级属性集合
  254. secondPropertyList: [], //二级属性集合
  255. isClear: 0,
  256. };
  257. },
  258. computed: {
  259. ...mapState({ user: (state) => state.user }),
  260. courseInfoSelect() {
  261. var courseList = [];
  262. for (let course of this.courseList) {
  263. var courseInfo = course.name + "(" + course.code + ")";
  264. var courseId = course.id;
  265. courseList.push({ courseId: courseId, courseInfo: courseInfo });
  266. }
  267. return courseList;
  268. },
  269. answer() {
  270. if (this.quesModel.questionType == "SINGLE_ANSWER_QUESTION") {
  271. return this.singleRightAnswer;
  272. } else if (this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION") {
  273. var obj = this.multipleRightAnswer;
  274. return obj.sort().toString();
  275. } else {
  276. return this.quesModel.quesAnswer;
  277. }
  278. },
  279. updateFirst() {
  280. if (this.formSearch.coursePropertyId) {
  281. return false;
  282. }
  283. return true;
  284. },
  285. updateSecond() {
  286. if (this.formSearch.firstPropertyId) {
  287. return false;
  288. }
  289. return true;
  290. },
  291. updatePorperty() {
  292. if (this.formSearch.courseId) {
  293. return false;
  294. }
  295. return true;
  296. },
  297. },
  298. watch: {
  299. $route: "initVue",
  300. },
  301. //钩子函数
  302. created() {
  303. var url =
  304. QUESTION_API +
  305. "/org/property/" +
  306. this.user.rootOrgId +
  307. "/ROOT_ORG_QUESTION_TYPES";
  308. this.$http.get(url).then((response) => {
  309. if (response.data && response.data.length > 0) {
  310. this.questionTypes = QUESTION_TYPES.filter((m) =>
  311. response.data.includes(m.value)
  312. );
  313. }
  314. });
  315. this.initVue();
  316. },
  317. methods: {
  318. getCoursesProperty(name) {
  319. this.coursePropertyLoading = true;
  320. this.formSearch.coursePropertyId = "";
  321. this.formSearch.firstPropertyId = "";
  322. this.formSearch.secondPropertyId = "";
  323. this.$httpWithMsg
  324. .get(
  325. QUESTION_API +
  326. "/courseProperty/enable?courseId=" +
  327. this.formSearch.courseId +
  328. "&name=" +
  329. name
  330. )
  331. .then((response) => {
  332. this.coursePropertyList = response.data;
  333. this.coursePropertyLoading = false;
  334. });
  335. },
  336. isMatchingQuestion(questionType) {
  337. if (
  338. questionType == "PARAGRAPH_MATCHING" ||
  339. questionType == "BANKED_CLOZE"
  340. ) {
  341. return true;
  342. } else {
  343. return false;
  344. }
  345. },
  346. isNested(questionType) {
  347. if (
  348. questionType == "PARAGRAPH_MATCHING" ||
  349. questionType == "BANKED_CLOZE" ||
  350. questionType == "CLOZE" ||
  351. questionType == "READING_COMPREHENSION" ||
  352. questionType == "LISTENING_QUESTION"
  353. ) {
  354. return true;
  355. } else {
  356. return false;
  357. }
  358. },
  359. resetForm() {
  360. this.formSearch = {
  361. questionType: "",
  362. courseId: null,
  363. courseLevel: "",
  364. publicity: "",
  365. coursePropertyId: null,
  366. firstPropertyId: "",
  367. secondPropertyId: "",
  368. };
  369. },
  370. getLevel(level) {
  371. if (level == "ZSB") {
  372. return "专升本";
  373. } else if (level == "GQZ") {
  374. return "高起专";
  375. } else if (level == "GQB") {
  376. return "高起本";
  377. } else if (level == "ALL") {
  378. return "不限";
  379. } else {
  380. return "";
  381. }
  382. },
  383. //查询列表
  384. searchFrom() {
  385. this.currentPage = 1;
  386. this.searchQues();
  387. },
  388. searchQues() {
  389. var pageNo = this.currentPage || 1;
  390. this.currentPage = 1;
  391. this.tableData = [];
  392. var url = QUESTION_API + "/question/" + pageNo + "/" + this.pageSize;
  393. this.loading = true;
  394. this.$http.get(url, { params: this.formSearch }).then((response) => {
  395. this.tableData = response.data.content;
  396. this.total = response.data.totalElements;
  397. this.currentPage = pageNo;
  398. this.loading = false;
  399. });
  400. },
  401. //分页
  402. handleCurrentChange(val) {
  403. this.currentPage = val;
  404. this.searchQues();
  405. },
  406. handleSizeChange(val) {
  407. this.pageSize = val;
  408. this.currentPage = 1;
  409. this.searchQues();
  410. },
  411. //修改
  412. updateRow(row) {
  413. //选择题:单选、多选
  414. if (
  415. row.questionType === "SINGLE_ANSWER_QUESTION" ||
  416. row.questionType === "MULTIPLE_ANSWER_QUESTION"
  417. ) {
  418. this.$router.push({
  419. path: "/questions/edit_select_question/" + row.id,
  420. });
  421. }
  422. //判断、填空、问答
  423. if (
  424. row.questionType === "BOOL_ANSWER_QUESTION" ||
  425. row.questionType === "FILL_BLANK_QUESTION" ||
  426. row.questionType === "TEXT_ANSWER_QUESTION"
  427. ) {
  428. this.$router.push({
  429. path: "/questions/edit_other_question/" + row.id,
  430. });
  431. }
  432. sessionStorage.setItem("question", JSON.stringify(this.formSearch));
  433. sessionStorage.setItem("question_currentPage", this.currentPage);
  434. },
  435. //删除
  436. deleteRow(row) {
  437. this.$confirm("确认删除试题吗?", "提示", {
  438. type: "warning",
  439. }).then(() => {
  440. this.loading = true;
  441. this.$http
  442. .delete(QUESTION_API + "/paper/deleteQuestion/" + row.id)
  443. .then(
  444. (response) => {
  445. if (response.data.length > 0) {
  446. this.loading = false;
  447. this.deleteInfo =
  448. "该试题被试卷:" +
  449. response.data.join(" , ") +
  450. "使用,不能删除";
  451. this.deleteDialogVisible = true;
  452. } else {
  453. this.$notify({
  454. message: "删除成功",
  455. type: "success",
  456. });
  457. this.searchQues();
  458. }
  459. },
  460. () => {
  461. this.$notify({
  462. message: "删除失败",
  463. type: "error",
  464. });
  465. this.loading = false;
  466. }
  467. );
  468. });
  469. },
  470. //预览
  471. prevViewQues(row) {
  472. this.quesModel = row;
  473. this.disposeSelectAnswer();
  474. this.$refs.QuestionPreview.open();
  475. },
  476. getCourseById(cid) {
  477. this.$http.get(QUESTION_API + "/course/" + cid).then((response) => {
  478. this.courseList.push(response.data);
  479. if (this.formSearch.coursePropertyId) {
  480. this.$http
  481. .get(
  482. QUESTION_API +
  483. "/courseProperty/find?id=" +
  484. this.formSearch.coursePropertyId
  485. )
  486. .then((response) => {
  487. if (response.data) {
  488. this.coursePropertyList.push(response.data);
  489. this.getFirst();
  490. }
  491. });
  492. }
  493. });
  494. },
  495. //查询所有课程
  496. getCourses(query) {
  497. this.$http
  498. .get(QUESTION_API + "/course/query?name=" + query + "&enable=true")
  499. .then((response) => {
  500. this.courseList = response.data;
  501. this.coursePropertyList = [];
  502. this.firstPropertyList = [];
  503. this.secondPropertyList = [];
  504. });
  505. },
  506. //重置查询表单
  507. resetSearchForm() {
  508. this.formSearch = {
  509. questionType: "",
  510. courseId: "",
  511. };
  512. },
  513. /*处理选择题答案显示,处理套题下选择题答案显示*/
  514. disposeSelectAnswer() {
  515. //处理选择题答案显示
  516. if (
  517. this.quesModel.questionType == "SINGLE_ANSWER_QUESTION" ||
  518. this.quesModel.questionType == "MULTIPLE_ANSWER_QUESTION"
  519. ) {
  520. let answers = [];
  521. this.quesModel.quesOptions.forEach((option, index) => {
  522. if (option.isCorrect) {
  523. answers.push(String.fromCharCode(65 + index));
  524. }
  525. });
  526. this.quesModel.quesAnswer = answers.sort().toString();
  527. }
  528. //处理套题下选择题答案显示
  529. if (this.quesModel.questionType == "NESTED_ANSWER_QUESTION") {
  530. var subQuestions = this.quesModel.subQuestions;
  531. for (var ii = 0; ii < subQuestions.length; ii++) {
  532. var subQuestion = subQuestions[ii];
  533. if (subQuestion.questionType == "SINGLE_ANSWER_QUESTION") {
  534. for (var j = 0; j < subQuestion.quesOptions.length; j++) {
  535. var option_j = subQuestion.quesOptions[j];
  536. var orderNum_j = String.fromCharCode(65 + j);
  537. if (option_j.isCorrect == 1) {
  538. subQuestion["quesAnswer"] = orderNum_j;
  539. }
  540. }
  541. }
  542. if (subQuestion.questionType == "MULTIPLE_ANSWER_QUESTION") {
  543. var subQuestionMultipleRightAnswer = [];
  544. for (var k = 0; k < subQuestion.quesOptions.length; k++) {
  545. var option2 = subQuestion.quesOptions[k];
  546. var orderNum2 = String.fromCharCode(65 + k);
  547. if (option2.isCorrect == 1) {
  548. subQuestionMultipleRightAnswer.push(orderNum2);
  549. }
  550. }
  551. subQuestion["quesAnswer"] = subQuestionMultipleRightAnswer
  552. .sort()
  553. .toString();
  554. }
  555. }
  556. }
  557. },
  558. //查询一级属性
  559. searchFirst() {
  560. if (this.formSearch.coursePropertyId) {
  561. this.formSearch.firstPropertyId = "";
  562. this.formSearch.secondPropertyId = "";
  563. this.$http
  564. .get(
  565. QUESTION_API + "/property/first/" + this.formSearch.coursePropertyId
  566. )
  567. .then((response) => {
  568. this.firstPropertyList = response.data;
  569. });
  570. }
  571. },
  572. //查询二级属性
  573. searchSecond() {
  574. if (this.formSearch.firstPropertyId) {
  575. this.formSearch.secondPropertyId = "";
  576. this.$http
  577. .get(
  578. QUESTION_API + "/property/second/" + this.formSearch.firstPropertyId
  579. )
  580. .then((response) => {
  581. this.secondPropertyList = response.data;
  582. });
  583. }
  584. },
  585. getFirst() {
  586. if (this.formSearch.firstPropertyId) {
  587. this.$http
  588. .get(
  589. QUESTION_API +
  590. "/property/find?id=" +
  591. this.formSearch.firstPropertyId
  592. )
  593. .then((response) => {
  594. this.firstPropertyList.push(response.data);
  595. //查询二级
  596. this.getSecond();
  597. });
  598. }
  599. },
  600. getSecond() {
  601. if (this.formSearch.secondPropertyId) {
  602. this.$http
  603. .get(
  604. QUESTION_API +
  605. "/property/find?id=" +
  606. this.formSearch.secondPropertyId
  607. )
  608. .then((response) => {
  609. this.secondPropertyList.push(response.data);
  610. });
  611. }
  612. },
  613. initVue() {
  614. this.isClear = this.$route.params.isClear;
  615. if (this.isClear == 0 || !this.isClear) {
  616. sessionStorage.removeItem("question");
  617. sessionStorage.removeItem("question_currentPage");
  618. this.formSearch = {
  619. questionType: "",
  620. courseId: "",
  621. courseLevel: "",
  622. publicity: "",
  623. coursePropertyId: "",
  624. firstPropertyId: "",
  625. secondPropertyId: "",
  626. };
  627. this.currentPage = 1;
  628. this.getCourses("");
  629. } else {
  630. this.formSearch = JSON.parse(sessionStorage.getItem("question"));
  631. this.currentPage = parseInt(
  632. sessionStorage.getItem("question_currentPage")
  633. );
  634. if (this.formSearch && this.formSearch.courseId) {
  635. this.getCourseById(this.formSearch.courseId);
  636. } else {
  637. this.getCourses("");
  638. }
  639. }
  640. this.searchQues();
  641. },
  642. },
  643. };
  644. </script>