CourseProperty.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. <template>
  2. <section class="content">
  3. <!-- 正文信息 -->
  4. <div class="part-box">
  5. <h2 class="part-box-title">课程属性</h2>
  6. <el-form class="part-filter-form" :inline="true" :model="formSearch">
  7. <el-form-item label="属性名称">
  8. <el-input
  9. v-model="formSearch.name"
  10. placeholder="请输入属性名称"
  11. ></el-input>
  12. </el-form-item>
  13. <el-form-item label="课程名称">
  14. <course-select v-model="formSearch.courseId"> </course-select>
  15. </el-form-item>
  16. <el-form-item>
  17. <el-button type="danger" @click="searchFrom">查询</el-button>
  18. </el-form-item>
  19. </el-form>
  20. <div class="part-box-action">
  21. <div>
  22. <el-button
  23. type="danger"
  24. plain
  25. icon="icon icon-delete"
  26. :disabled="noBatchSelected"
  27. @click="toBatchDeleteCourseProperty"
  28. >删除</el-button
  29. >
  30. <el-button
  31. type="primary"
  32. plain
  33. icon="icon icon-import"
  34. @click="impCourseProperty"
  35. >导入
  36. </el-button>
  37. </div>
  38. <el-button
  39. type="primary"
  40. icon="icon icon-plus-white"
  41. @click="addCourseProperty"
  42. >新增</el-button
  43. >
  44. </div>
  45. </div>
  46. <div class="part-box">
  47. <!-- 页面列表 -->
  48. <el-table
  49. v-loading="loading"
  50. :data="tableData"
  51. element-loading-text="拼命加载中"
  52. @selection-change="selectionChange"
  53. >
  54. <el-table-column
  55. type="selection"
  56. width="50"
  57. align="center"
  58. ></el-table-column>
  59. <el-table-column label="课程名称">
  60. <template slot-scope="scope">
  61. <span>{{ scope.row.courseName }}</span>
  62. </template>
  63. </el-table-column>
  64. <el-table-column label="属性名称">
  65. <template slot-scope="scope">
  66. <span>{{ scope.row.name }}</span>
  67. </template>
  68. </el-table-column>
  69. <el-table-column label="状态">
  70. <template slot-scope="scope">
  71. <span v-if="scope.row.enable">
  72. <el-tooltip
  73. class="item"
  74. effect="dark"
  75. content="启用"
  76. placement="left"
  77. >
  78. <i class="icon icon-right"></i>
  79. </el-tooltip>
  80. </span>
  81. <span v-else>
  82. <el-tooltip
  83. class="item"
  84. effect="dark"
  85. content="禁用"
  86. placement="left"
  87. >
  88. <i class="icon icon-error"></i>
  89. </el-tooltip>
  90. </span>
  91. </template>
  92. </el-table-column>
  93. <el-table-column label="操作" width="160">
  94. <template slot-scope="scope">
  95. <div class="operate_left">
  96. <el-button
  97. size="mini"
  98. type="primary"
  99. plain
  100. @click="editCourseProperty(scope.row)"
  101. >详情
  102. </el-button>
  103. <el-button
  104. size="mini"
  105. type="danger"
  106. plain
  107. @click="toDeleteCourseProperty(scope.row)"
  108. >
  109. 删除
  110. </el-button>
  111. </div>
  112. </template>
  113. </el-table-column>
  114. </el-table>
  115. <div class="part-page">
  116. <el-pagination
  117. :current-page.sync="currentPage"
  118. :page-size="pageSize"
  119. :page-sizes="[10, 20, 50, 100, 200, 300]"
  120. layout="total, sizes, prev, pager, next, jumper"
  121. :total="total"
  122. @current-change="handleCurrentChange"
  123. @size-change="handleSizeChange"
  124. >
  125. </el-pagination>
  126. </div>
  127. </div>
  128. <el-dialog
  129. title="新增课程属性名称"
  130. :visible.sync="coursePropertyDialog"
  131. width="520px"
  132. :modal="false"
  133. append-to-body
  134. custom-class="side-dialog"
  135. >
  136. <el-form
  137. ref="coursePropertyForm"
  138. :model="coursePropertyForm"
  139. :rules="rules"
  140. label-position="right"
  141. label-width="90px"
  142. inline-message
  143. class="form-tight"
  144. >
  145. <el-form-item label="属性名称" prop="name">
  146. <el-input
  147. v-model="coursePropertyForm.name"
  148. class="dialog-input-width"
  149. maxlength="100"
  150. placeholder="请输入"
  151. ></el-input>
  152. </el-form-item>
  153. <el-form-item label="课程名称" prop="courseId">
  154. <el-select
  155. v-model="coursePropertyForm.courseId"
  156. :remote-method="getCoursesForAdd"
  157. :loading="courseAddSearch"
  158. remote
  159. filterable
  160. clearable
  161. class="dialog-input-width"
  162. placeholder="请选择课程"
  163. @clear="getCoursesForAdd('')"
  164. >
  165. <el-option
  166. v-for="item in courseAddList"
  167. :key="item.id"
  168. :label="item.name + '(' + item.code + ')'"
  169. :value="item.id"
  170. >
  171. </el-option>
  172. </el-select>
  173. </el-form-item>
  174. </el-form>
  175. <div slot="footer">
  176. <el-button type="primary" @click="submit('coursePropertyForm')"
  177. >保存</el-button
  178. >
  179. <el-button type="danger" plain @click="resetForm('coursePropertyForm')"
  180. >重置</el-button
  181. >
  182. <el-button type="danger" plain @click="back('coursePropertyForm')"
  183. >返回</el-button
  184. >
  185. </div>
  186. </el-dialog>
  187. <!-- 导入弹窗 -->
  188. <el-dialog
  189. title="导入课程"
  190. width="520px"
  191. :visible.sync="impDialog"
  192. :modal="false"
  193. append-to-body
  194. custom-class="side-dialog"
  195. >
  196. <el-form>
  197. <el-form-item style="margin-left: 20px">
  198. <el-upload
  199. ref="upload"
  200. class="form_left"
  201. accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  202. :action="uploadAction"
  203. :headers="uploadHeaders"
  204. :data="uploadData"
  205. :before-upload="beforeUpload"
  206. :on-progress="uploadProgress"
  207. :on-success="uploadSuccess"
  208. :on-error="uploadError"
  209. :file-list="fileList"
  210. :auto-upload="false"
  211. :multiple="false"
  212. >
  213. <el-button
  214. slot="trigger"
  215. size="small"
  216. type="primary"
  217. icon="icon icon-search-white"
  218. >
  219. 选择文件
  220. </el-button>
  221. <el-button
  222. size="small"
  223. type="primary"
  224. icon="icon icon-save-white"
  225. @click="submitUpload"
  226. >
  227. 确认上传
  228. </el-button>
  229. <el-button
  230. size="small"
  231. type="primary"
  232. icon="icon icon-delete-white"
  233. @click="removeFile"
  234. >
  235. 清空文件
  236. </el-button>
  237. <el-button
  238. size="small"
  239. type="primary"
  240. icon="icon icon-export-white"
  241. @click="exportFile"
  242. >
  243. 下载模板
  244. </el-button>
  245. <div slot="tip" class="el-upload__tip">只能上传xlsx文件</div>
  246. </el-upload>
  247. </el-form-item>
  248. </el-form>
  249. </el-dialog>
  250. <!-- 导入错误信息列表 -->
  251. <el-dialog title="错误提示" :visible.sync="errDialog" append-to-body>
  252. <div
  253. v-for="errMessage in errMessages"
  254. :key="errMessage.lineNum"
  255. class="text-danger"
  256. >
  257. 第{{ errMessage.lineNum }}行:{{ errMessage.msg }}
  258. </div>
  259. <span slot="footer" class="dialog-footer">
  260. <el-button @click="errDialog = false">确定</el-button>
  261. </span>
  262. </el-dialog>
  263. </section>
  264. </template>
  265. <script>
  266. import { QUESTION_API } from "@/constants/constants";
  267. import { mapState } from "vuex";
  268. export default {
  269. data() {
  270. return {
  271. courseAddSearch: false,
  272. courseLoading4Search: false,
  273. formSearch: {
  274. name: "",
  275. courseId: "",
  276. },
  277. impDialog: false,
  278. uploadAction: QUESTION_API + "/courseProperty/import",
  279. uploadHeaders: {},
  280. uploadData: {},
  281. errMessages: [],
  282. errDialog: false,
  283. fileLoading: false,
  284. fileList: [],
  285. courseList: [],
  286. courseAddList: [],
  287. loading: false,
  288. tableData: [],
  289. currentPage: 1,
  290. pageSize: 10,
  291. total: 10,
  292. coursePropertyForm: {
  293. name: "",
  294. courseId: "",
  295. },
  296. coursePropertyDialog: false,
  297. selectedList: [],
  298. rules: {
  299. name: [{ required: true, message: "请输入属性名称", trigger: "blur" }],
  300. courseId: [
  301. { required: true, message: "请选择课程名称", trigger: "change" },
  302. ],
  303. },
  304. };
  305. },
  306. computed: {
  307. ...mapState({
  308. user: (state) => state.user,
  309. }),
  310. selectedIds() {
  311. var selectedIdsStr = "";
  312. for (let id of this.selectedList) {
  313. if (!selectedIdsStr) {
  314. selectedIdsStr += id;
  315. } else {
  316. selectedIdsStr += "," + id;
  317. }
  318. }
  319. return selectedIdsStr;
  320. },
  321. courseInfoSelect() {
  322. var courseList = [];
  323. for (var i = 0; i < this.courseList.length; i++) {
  324. var courseInfo = {
  325. courseInfo:
  326. this.courseList[i].name + "(" + this.courseList[i].code + ")",
  327. courseId: this.courseList[i].id,
  328. };
  329. courseList.push(courseInfo);
  330. }
  331. return courseList;
  332. },
  333. noBatchSelected() {
  334. return this.selectedList.length === 0;
  335. },
  336. },
  337. watch: {
  338. $route: "initValue",
  339. },
  340. created() {
  341. this.initValue();
  342. this.uploadHeaders = {
  343. key: this.user.key,
  344. token: this.user.token,
  345. };
  346. this.getCourses("");
  347. this.getCoursesForAdd("");
  348. },
  349. methods: {
  350. //导入
  351. impCourseProperty() {
  352. this.impDialog = true;
  353. this.initUpload();
  354. },
  355. initUpload() {
  356. this.fileList = [];
  357. },
  358. beforeUpload(file) {
  359. console.log(file);
  360. },
  361. uploadProgress() {
  362. console.log("uploadProgress");
  363. },
  364. uploadSuccess(response) {
  365. if (!response.hasError) {
  366. this.$notify({
  367. message: "上传成功",
  368. type: "success",
  369. });
  370. this.fileLoading = false;
  371. this.impDialog = false;
  372. this.searchCourProperty();
  373. } else {
  374. this.fileLoading = false;
  375. this.impDialog = false;
  376. this.errMessages = response.failRecords;
  377. this.errDialog = true;
  378. }
  379. },
  380. uploadError(response) {
  381. var json = JSON.parse(response.message);
  382. if (response.status == 500) {
  383. this.$notify({
  384. message: json.desc,
  385. type: "error",
  386. });
  387. }
  388. this.fileLoading = false;
  389. },
  390. //确定上传
  391. submitUpload() {
  392. if (!this.checkUpload()) {
  393. return false;
  394. }
  395. this.$refs.upload.submit();
  396. this.fileLoading = true;
  397. },
  398. checkUpload() {
  399. var fileList = this.$refs.upload.uploadFiles;
  400. if (fileList.length == 0) {
  401. this.$notify({
  402. message: "上传文件不能为空",
  403. type: "error",
  404. });
  405. return false;
  406. }
  407. if (fileList.length > 1) {
  408. this.$notify({
  409. message: "每次只能上传一个文件",
  410. type: "error",
  411. });
  412. return false;
  413. }
  414. for (let file of fileList) {
  415. if (!file.name.endsWith(".xlsx")) {
  416. this.$notify({
  417. message: "上传文件必须为xlsx格式",
  418. type: "error",
  419. });
  420. this.initUpload();
  421. return false;
  422. }
  423. }
  424. return true;
  425. },
  426. //清空文件
  427. removeFile() {
  428. // this.fileList = [];
  429. this.$refs.upload.clearFiles();
  430. },
  431. //下载模板
  432. exportFile() {
  433. window.location.href =
  434. QUESTION_API +
  435. "/courseProperty/importTemplate?$key=" +
  436. this.user.key +
  437. "&$token=" +
  438. this.user.token;
  439. },
  440. //查询所有课程属性
  441. searchFrom() {
  442. this.currentPage = 1;
  443. this.searchCourProperty();
  444. },
  445. searchCourProperty() {
  446. var pageNo = Number(this.currentPage);
  447. this.loading = true;
  448. var url =
  449. QUESTION_API +
  450. "/courseProperty/all/" +
  451. this.currentPage +
  452. "/" +
  453. this.pageSize;
  454. this.$http.get(url, { params: this.formSearch }).then((response) => {
  455. this.tableData = response.data.content;
  456. this.total = response.data.totalElements;
  457. this.currentPage = pageNo;
  458. this.loading = false;
  459. });
  460. },
  461. //新增
  462. addCourseProperty() {
  463. this.coursePropertyDialog = true;
  464. this.coursePropertyForm.name = "";
  465. this.coursePropertyForm.courseId = "";
  466. this.getCoursesForAdd("");
  467. },
  468. //重置
  469. resetForm(formData) {
  470. this.coursePropertyForm.name = "";
  471. this.coursePropertyForm.courseId = "";
  472. this.$refs[formData].clearValidate();
  473. },
  474. //返回
  475. back(formData) {
  476. this.resetForm(formData);
  477. this.coursePropertyDialog = false;
  478. },
  479. //修改
  480. editCourseProperty(row) {
  481. sessionStorage.setItem("course_property_name", this.formSearch.name);
  482. sessionStorage.setItem(
  483. "course_property_courseId",
  484. this.formSearch.courseId
  485. );
  486. sessionStorage.setItem("course_property_currentPage", this.currentPage);
  487. sessionStorage.setItem("courseProperty", JSON.stringify(row));
  488. this.$router.push({
  489. path: "/questions/property_info/" + row.id,
  490. });
  491. },
  492. // 删除
  493. async deleteCourseProperty(ids) {
  494. if (this.loading) return;
  495. this.loading = true;
  496. const res = await this.$httpWithMsg
  497. .post(
  498. QUESTION_API + "/courseProperty/delete",
  499. {},
  500. { params: { coursePropertyIdList: ids } }
  501. )
  502. .catch(() => {});
  503. this.loading = false;
  504. if (!res) return;
  505. this.$message.success("操作成功!");
  506. this.searchCourProperty();
  507. },
  508. async toDeleteCourseProperty(row) {
  509. const confirm = await this.$confirm("确认删除?", "提示", {
  510. type: "warning",
  511. }).catch(() => {});
  512. if (confirm !== "confirm") return;
  513. await this.deleteCourseProperty(row.id);
  514. },
  515. //批量关闭
  516. async toBatchDeleteCourseProperty() {
  517. if (!this.selectedIds.length) {
  518. this.$message.error("请选择要删除数据");
  519. return;
  520. }
  521. const confirm = await this.$confirm("确认删除?", "提示", {
  522. type: "warning",
  523. }).catch(() => {});
  524. if (confirm !== "confirm") return;
  525. await this.deleteCourseProperty(this.selectedIds);
  526. },
  527. //分页
  528. handleCurrentChange(val) {
  529. this.currentPage = val;
  530. this.searchCourProperty();
  531. },
  532. handleSizeChange(val) {
  533. this.pageSize = val;
  534. this.currentPage = 1;
  535. this.searchCourProperty();
  536. },
  537. //确定
  538. submit(formData) {
  539. this.$refs[formData].validate((valid) => {
  540. if (valid) {
  541. this.$http
  542. .post(
  543. QUESTION_API + "/courseProperty/save",
  544. this.coursePropertyForm
  545. )
  546. .then(() => {
  547. this.$notify({
  548. message: "新增成功",
  549. type: "success",
  550. });
  551. this.coursePropertyDialog = false;
  552. this.searchCourProperty();
  553. })
  554. .catch((error) => {
  555. this.$notify({
  556. type: "error",
  557. message: error.response.data.desc,
  558. });
  559. });
  560. } else {
  561. return false;
  562. }
  563. });
  564. },
  565. //查询所有课程
  566. getCourses(query) {
  567. this.courseLoading4Search = true;
  568. this.$httpWithMsg
  569. .get(QUESTION_API + "/course/query?name=" + query)
  570. .then((response) => {
  571. this.courseList = response.data;
  572. this.courseLoading4Search = false;
  573. });
  574. },
  575. getCoursesForAdd(query) {
  576. this.courseAddSearch = true;
  577. this.$httpWithMsg
  578. .get(QUESTION_API + "/course/query?name=" + query + "&enable=true")
  579. .then((response) => {
  580. this.courseAddList = response.data;
  581. this.courseAddSearch = false;
  582. });
  583. },
  584. removeItem() {
  585. sessionStorage.removeItem("course_property_name");
  586. sessionStorage.removeItem("course_property_courseId");
  587. sessionStorage.removeItem("course_property_currentPage");
  588. },
  589. //页面回填值
  590. initValue() {
  591. this.isClear = this.$route.params.isClear;
  592. if (this.isClear == 0 || !this.isClear) {
  593. this.removeItem();
  594. this.formSearch = {
  595. name: "",
  596. courseId: "",
  597. };
  598. } else {
  599. this.formSearch.name =
  600. sessionStorage.getItem("course_property_name") == "null"
  601. ? ""
  602. : sessionStorage.getItem("course_property_name");
  603. this.formSearch.courseId =
  604. sessionStorage.getItem("course_property_courseId") == ""
  605. ? ""
  606. : parseInt(sessionStorage.getItem("course_property_courseId"));
  607. this.currentPage =
  608. sessionStorage.getItem("course_property_currentPage") == null
  609. ? 1
  610. : parseInt(sessionStorage.getItem("course_property_currentPage"));
  611. }
  612. this.getOneCourse(this.formSearch.courseId);
  613. this.handleCurrentChange(this.currentPage);
  614. },
  615. //查询单个课程
  616. getOneCourse(courseId) {
  617. if (courseId) {
  618. this.$http
  619. .get(QUESTION_API + "/course/" + courseId)
  620. .then((response) => {
  621. this.courseList.push(response.data);
  622. });
  623. } else {
  624. this.courseList = [];
  625. }
  626. },
  627. //全选
  628. selectionChange(val) {
  629. this.selectedList = [];
  630. var selectedList = this.selectedList;
  631. val.forEach((element) => {
  632. selectedList.push(element.id);
  633. });
  634. this.selectedList = selectedList;
  635. },
  636. },
  637. };
  638. </script>