CourseProperty.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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="primary" @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. <el-button
  38. type="primary"
  39. plain
  40. icon="icon icon-export"
  41. :disabled="noBatchSelected"
  42. @click="exportCourseProperty(selectedList)"
  43. >导出
  44. </el-button>
  45. </div>
  46. <el-button
  47. type="primary"
  48. icon="icon icon-plus-white"
  49. @click="addCourseProperty"
  50. >新增</el-button
  51. >
  52. </div>
  53. </div>
  54. <div class="part-box">
  55. <!-- 页面列表 -->
  56. <el-table
  57. v-loading="loading"
  58. :data="tableData"
  59. element-loading-text="拼命加载中"
  60. @selection-change="selectionChange"
  61. >
  62. <el-table-column
  63. type="selection"
  64. width="50"
  65. align="center"
  66. ></el-table-column>
  67. <el-table-column label="课程名称">
  68. <template slot-scope="scope">
  69. <span>{{ scope.row.courseName }}</span>
  70. </template>
  71. </el-table-column>
  72. <el-table-column label="属性名称">
  73. <template slot-scope="scope">
  74. <span>{{ scope.row.name }}</span>
  75. </template>
  76. </el-table-column>
  77. <el-table-column label="状态">
  78. <template slot-scope="scope">
  79. <span v-if="scope.row.enable">
  80. <el-tooltip
  81. class="item"
  82. effect="dark"
  83. content="启用"
  84. placement="left"
  85. >
  86. <i class="icon icon-right"></i>
  87. </el-tooltip>
  88. </span>
  89. <span v-else>
  90. <el-tooltip
  91. class="item"
  92. effect="dark"
  93. content="禁用"
  94. placement="left"
  95. >
  96. <i class="icon icon-error"></i>
  97. </el-tooltip>
  98. </span>
  99. </template>
  100. </el-table-column>
  101. <el-table-column label="操作" width="220">
  102. <template slot-scope="scope">
  103. <div class="operate_left">
  104. <el-button
  105. size="mini"
  106. type="primary"
  107. plain
  108. @click="exportCourseProperty([scope.row.id])"
  109. >导出
  110. </el-button>
  111. <el-button
  112. size="mini"
  113. type="primary"
  114. plain
  115. @click="editCourseProperty(scope.row)"
  116. >详情
  117. </el-button>
  118. <el-button
  119. size="mini"
  120. type="danger"
  121. plain
  122. @click="toDeleteCourseProperty(scope.row)"
  123. >
  124. 删除
  125. </el-button>
  126. </div>
  127. </template>
  128. </el-table-column>
  129. </el-table>
  130. <div class="part-page">
  131. <el-pagination
  132. :current-page.sync="currentPage"
  133. :page-size="pageSize"
  134. :page-sizes="[10, 20, 50, 100, 200, 300]"
  135. layout="total, sizes, prev, pager, next, jumper"
  136. :total="total"
  137. @current-change="handleCurrentChange"
  138. @size-change="handleSizeChange"
  139. >
  140. </el-pagination>
  141. </div>
  142. </div>
  143. <el-dialog
  144. title="新增课程属性名称"
  145. :visible.sync="coursePropertyDialog"
  146. width="520px"
  147. :modal="true"
  148. append-to-body
  149. custom-class="side-dialog"
  150. >
  151. <el-form
  152. ref="coursePropertyForm"
  153. :model="coursePropertyForm"
  154. :rules="rules"
  155. label-position="right"
  156. label-width="90px"
  157. inline-message
  158. class="form-tight"
  159. >
  160. <el-form-item label="属性名称" prop="name">
  161. <el-input
  162. v-model="coursePropertyForm.name"
  163. class="dialog-input-width"
  164. maxlength="100"
  165. placeholder="请输入"
  166. ></el-input>
  167. </el-form-item>
  168. <el-form-item label="课程名称" prop="courseId">
  169. <el-select
  170. v-model="coursePropertyForm.courseId"
  171. :remote-method="getCoursesForAdd"
  172. :loading="courseAddSearch"
  173. remote
  174. filterable
  175. clearable
  176. class="dialog-input-width"
  177. placeholder="请选择课程"
  178. @clear="getCoursesForAdd('')"
  179. >
  180. <el-option
  181. v-for="item in courseAddList"
  182. :key="item.id"
  183. :label="item.name + '(' + item.code + ')'"
  184. :value="item.id"
  185. >
  186. </el-option>
  187. </el-select>
  188. </el-form-item>
  189. </el-form>
  190. <div slot="footer">
  191. <el-button type="primary" @click="submit('coursePropertyForm')"
  192. >保存</el-button
  193. >
  194. <el-button type="danger" plain @click="resetForm('coursePropertyForm')"
  195. >重置</el-button
  196. >
  197. <el-button type="danger" plain @click="back('coursePropertyForm')"
  198. >返回</el-button
  199. >
  200. </div>
  201. </el-dialog>
  202. <!-- 导入弹窗 -->
  203. <import-file-dialog
  204. ref="ImportCourseDialog"
  205. dialog-title="导入课程"
  206. :template-url="courseTemplateUrl"
  207. :upload-url="uploadCourseUrl"
  208. @uploaded="uploadSuccess"
  209. ></import-file-dialog>
  210. <!-- 导入错误信息列表 -->
  211. <el-dialog title="错误提示" :visible.sync="errDialog" append-to-body>
  212. <div
  213. v-for="errMessage in errMessages"
  214. :key="errMessage.lineNum"
  215. class="text-danger"
  216. >
  217. 第{{ errMessage.lineNum }}行:{{ errMessage.msg }}
  218. </div>
  219. <span slot="footer" class="dialog-footer">
  220. <el-button @click="errDialog = false">确定</el-button>
  221. </span>
  222. </el-dialog>
  223. </section>
  224. </template>
  225. <script>
  226. import { QUESTION_API } from "@/constants/constants";
  227. import { mapState } from "vuex";
  228. import { downloadByApi } from "@/plugins/download";
  229. import ImportFileDialog from "@/components/ImportFileDialog.vue";
  230. export default {
  231. components: { ImportFileDialog },
  232. data() {
  233. return {
  234. courseAddSearch: false,
  235. courseLoading4Search: false,
  236. formSearch: {
  237. name: "",
  238. courseId: "",
  239. },
  240. uploadCourseUrl: `${QUESTION_API}/courseProperty/import`,
  241. courseTemplateUrl: `${QUESTION_API}/courseProperty/importTemplate`,
  242. errMessages: [],
  243. errDialog: false,
  244. courseList: [],
  245. courseAddList: [],
  246. loading: false,
  247. tableData: [],
  248. currentPage: 1,
  249. pageSize: 10,
  250. total: 10,
  251. coursePropertyForm: {
  252. name: "",
  253. courseId: "",
  254. },
  255. coursePropertyDialog: false,
  256. selectedList: [],
  257. rules: {
  258. name: [{ required: true, message: "请输入属性名称", trigger: "blur" }],
  259. courseId: [
  260. { required: true, message: "请选择课程名称", trigger: "change" },
  261. ],
  262. },
  263. downloading: false,
  264. };
  265. },
  266. computed: {
  267. ...mapState({
  268. user: (state) => state.user,
  269. }),
  270. selectedIds() {
  271. var selectedIdsStr = "";
  272. for (let id of this.selectedList) {
  273. if (!selectedIdsStr) {
  274. selectedIdsStr += id;
  275. } else {
  276. selectedIdsStr += "," + id;
  277. }
  278. }
  279. return selectedIdsStr;
  280. },
  281. courseInfoSelect() {
  282. var courseList = [];
  283. for (var i = 0; i < this.courseList.length; i++) {
  284. var courseInfo = {
  285. courseInfo:
  286. this.courseList[i].name + "(" + this.courseList[i].code + ")",
  287. courseId: this.courseList[i].id,
  288. };
  289. courseList.push(courseInfo);
  290. }
  291. return courseList;
  292. },
  293. noBatchSelected() {
  294. return this.selectedList.length === 0;
  295. },
  296. },
  297. watch: {
  298. $route: "initValue",
  299. },
  300. created() {
  301. this.initValue();
  302. this.uploadHeaders = {
  303. key: this.user.key,
  304. token: this.user.token,
  305. };
  306. this.getCourses("");
  307. this.getCoursesForAdd("");
  308. },
  309. methods: {
  310. // 导出
  311. async exportCourseProperty(coursePropertyIds) {
  312. if (!coursePropertyIds.length) {
  313. this.$message.error("请选择要导出的属性");
  314. return;
  315. }
  316. if (this.downloading) return;
  317. this.downloading = true;
  318. const res = await downloadByApi(() => {
  319. return this.$httpWithMsg.get(
  320. `${QUESTION_API}/courseProperty/detail/export`,
  321. {
  322. params: { coursePropertyIds: coursePropertyIds.join() },
  323. responseType: "blob",
  324. }
  325. );
  326. }).catch((e) => {
  327. this.$message.error(e || "导出失败,请重新尝试!");
  328. });
  329. this.downloading = false;
  330. if (!res) return;
  331. this.$message.success("导出成功!");
  332. },
  333. //导入
  334. impCourseProperty() {
  335. this.$refs.ImportCourseDialog.open();
  336. },
  337. uploadSuccess(response) {
  338. const { hasError, failRecords } = response.data;
  339. if (!hasError) {
  340. this.$notify({
  341. message: "上传成功",
  342. type: "success",
  343. });
  344. this.searchCourProperty();
  345. } else {
  346. this.errMessages = failRecords;
  347. this.errDialog = true;
  348. }
  349. },
  350. //查询所有课程属性
  351. searchFrom() {
  352. this.currentPage = 1;
  353. this.searchCourProperty();
  354. },
  355. searchCourProperty() {
  356. var pageNo = Number(this.currentPage);
  357. this.loading = true;
  358. var url =
  359. QUESTION_API +
  360. "/courseProperty/all/" +
  361. this.currentPage +
  362. "/" +
  363. this.pageSize;
  364. this.$http.get(url, { params: this.formSearch }).then((response) => {
  365. this.tableData = response.data.content;
  366. this.total = response.data.totalElements;
  367. this.currentPage = pageNo;
  368. this.loading = false;
  369. });
  370. },
  371. //新增
  372. addCourseProperty() {
  373. this.coursePropertyDialog = true;
  374. this.coursePropertyForm.name = "";
  375. this.coursePropertyForm.courseId = "";
  376. this.getCoursesForAdd("");
  377. },
  378. //重置
  379. resetForm(formData) {
  380. this.coursePropertyForm.name = "";
  381. this.coursePropertyForm.courseId = "";
  382. this.$refs[formData].clearValidate();
  383. },
  384. //返回
  385. back(formData) {
  386. this.resetForm(formData);
  387. this.coursePropertyDialog = false;
  388. },
  389. //修改
  390. editCourseProperty(row) {
  391. sessionStorage.setItem("course_property_name", this.formSearch.name);
  392. sessionStorage.setItem(
  393. "course_property_courseId",
  394. this.formSearch.courseId
  395. );
  396. sessionStorage.setItem("course_property_currentPage", this.currentPage);
  397. sessionStorage.setItem("courseProperty", JSON.stringify(row));
  398. this.$router.push({
  399. path: "/questions/property_info/" + row.id,
  400. });
  401. },
  402. // 删除
  403. async deleteCourseProperty(ids) {
  404. if (this.loading) return;
  405. this.loading = true;
  406. const res = await this.$httpWithMsg
  407. .post(
  408. QUESTION_API + "/courseProperty/delete",
  409. {},
  410. { params: { coursePropertyIdList: ids } }
  411. )
  412. .catch(() => {});
  413. this.loading = false;
  414. if (!res) return;
  415. this.$message.success("操作成功!");
  416. this.searchCourProperty();
  417. },
  418. async toDeleteCourseProperty(row) {
  419. const confirm = await this.$confirm("确认删除?", "提示", {
  420. type: "warning",
  421. }).catch(() => {});
  422. if (confirm !== "confirm") return;
  423. await this.deleteCourseProperty(row.id);
  424. },
  425. //批量关闭
  426. async toBatchDeleteCourseProperty() {
  427. if (!this.selectedIds.length) {
  428. this.$message.error("请选择要删除数据");
  429. return;
  430. }
  431. const confirm = await this.$confirm("确认删除?", "提示", {
  432. type: "warning",
  433. }).catch(() => {});
  434. if (confirm !== "confirm") return;
  435. await this.deleteCourseProperty(this.selectedIds);
  436. },
  437. //分页
  438. handleCurrentChange(val) {
  439. this.currentPage = val;
  440. this.searchCourProperty();
  441. },
  442. handleSizeChange(val) {
  443. this.pageSize = val;
  444. this.currentPage = 1;
  445. this.searchCourProperty();
  446. },
  447. //确定
  448. submit(formData) {
  449. this.$refs[formData].validate((valid) => {
  450. if (valid) {
  451. this.$http
  452. .post(
  453. QUESTION_API + "/courseProperty/save",
  454. this.coursePropertyForm
  455. )
  456. .then(() => {
  457. this.$notify({
  458. message: "新增成功",
  459. type: "success",
  460. });
  461. this.coursePropertyDialog = false;
  462. this.searchCourProperty();
  463. })
  464. .catch((error) => {
  465. this.$notify({
  466. type: "error",
  467. message: error.response.data.desc,
  468. });
  469. });
  470. } else {
  471. return false;
  472. }
  473. });
  474. },
  475. //查询所有课程
  476. getCourses(query) {
  477. this.courseLoading4Search = true;
  478. this.$httpWithMsg
  479. .get(QUESTION_API + "/course/query?name=" + query)
  480. .then((response) => {
  481. this.courseList = response.data;
  482. this.courseLoading4Search = false;
  483. });
  484. },
  485. getCoursesForAdd(query) {
  486. this.courseAddSearch = true;
  487. this.$httpWithMsg
  488. .get(QUESTION_API + "/course/query?name=" + query + "&enable=true")
  489. .then((response) => {
  490. this.courseAddList = response.data;
  491. this.courseAddSearch = false;
  492. });
  493. },
  494. removeItem() {
  495. sessionStorage.removeItem("course_property_name");
  496. sessionStorage.removeItem("course_property_courseId");
  497. sessionStorage.removeItem("course_property_currentPage");
  498. },
  499. //页面回填值
  500. initValue() {
  501. this.isClear = this.$route.params.isClear;
  502. if (this.isClear == 0 || !this.isClear) {
  503. this.removeItem();
  504. this.formSearch = {
  505. name: "",
  506. courseId: "",
  507. };
  508. } else {
  509. this.formSearch.name =
  510. sessionStorage.getItem("course_property_name") == "null"
  511. ? ""
  512. : sessionStorage.getItem("course_property_name");
  513. this.formSearch.courseId =
  514. sessionStorage.getItem("course_property_courseId") == ""
  515. ? ""
  516. : parseInt(sessionStorage.getItem("course_property_courseId"));
  517. this.currentPage =
  518. sessionStorage.getItem("course_property_currentPage") == null
  519. ? 1
  520. : parseInt(sessionStorage.getItem("course_property_currentPage"));
  521. }
  522. this.getOneCourse(this.formSearch.courseId);
  523. this.handleCurrentChange(this.currentPage);
  524. },
  525. //查询单个课程
  526. getOneCourse(courseId) {
  527. if (courseId) {
  528. this.$http
  529. .get(QUESTION_API + "/course/" + courseId)
  530. .then((response) => {
  531. this.courseList.push(response.data);
  532. });
  533. } else {
  534. this.courseList = [];
  535. }
  536. },
  537. //全选
  538. selectionChange(val) {
  539. this.selectedList = [];
  540. var selectedList = this.selectedList;
  541. val.forEach((element) => {
  542. selectedList.push(element.id);
  543. });
  544. this.selectedList = selectedList;
  545. },
  546. },
  547. };
  548. </script>