MarkSettingMain.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. <template>
  2. <div>
  3. <LinkTitlesCustom :current-paths="['评卷工作', '评卷设置', '设置列表']" />
  4. <section class="content">
  5. <div
  6. v-loading="fileLoading"
  7. class="box box-info"
  8. element-loading-text="导入需要较长时间,请耐心等候"
  9. >
  10. <div class="box-body">
  11. <el-form
  12. :inline="true"
  13. :model="formSearch"
  14. label-position="right"
  15. label-width="40px"
  16. >
  17. <el-form-item label="课程" class="pull-left">
  18. <el-select
  19. v-model="formSearch.courseCode"
  20. clearable
  21. filterable
  22. class="input"
  23. placeholder="请选择"
  24. >
  25. <el-option
  26. v-for="item in courseAllListSelect"
  27. :key="item.code"
  28. :label="item.courseInfo"
  29. :value="item.code"
  30. ></el-option>
  31. </el-select>
  32. </el-form-item>
  33. <el-form-item>
  34. <el-button
  35. size="small"
  36. type="primary"
  37. icon="el-icon-search"
  38. @click="initSetting"
  39. >查询</el-button
  40. >
  41. <el-button
  42. size="small"
  43. type="primary"
  44. icon="el-icon-arrow-left"
  45. @click="back"
  46. >返回</el-button
  47. >
  48. <el-dropdown
  49. style="margin-left: 10px"
  50. placement="bottom-start"
  51. @command="handleCommand"
  52. >
  53. <el-button size="small" type="primary">
  54. 更多 <i class="el-icon-arrow-down el-icon--right"></i>
  55. </el-button>
  56. <el-dropdown-menu slot="dropdown">
  57. <el-dropdown-item command="in">
  58. <el-button
  59. size="small"
  60. type="primary"
  61. icon="el-icon-upload2"
  62. >导入</el-button
  63. >
  64. </el-dropdown-item>
  65. <el-dropdown-item command="out">
  66. <el-button
  67. size="small"
  68. type="primary"
  69. icon="el-icon-download"
  70. >导出</el-button
  71. >
  72. </el-dropdown-item>
  73. </el-dropdown-menu>
  74. </el-dropdown>
  75. </el-form-item>
  76. </el-form>
  77. <!-- 导入弹窗 -->
  78. <el-dialog title="导入窗口" size="tiny" :visible.sync="impDialog">
  79. <el-form>
  80. <el-row>
  81. <el-form-item>
  82. <el-upload
  83. ref="upload"
  84. class="form_left"
  85. accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  86. :action="uploadAction"
  87. :headers="uploadHeaders"
  88. :data="uploadData"
  89. :before-upload="beforeUpload"
  90. :on-progress="uploadProgress"
  91. :on-success="uploadSuccess"
  92. :on-error="uploadError"
  93. :file-list="fileList"
  94. :auto-upload="false"
  95. :multiple="false"
  96. >
  97. <el-button slot="trigger" type="primary" size="small"
  98. >选择文件</el-button
  99. >
  100. <el-button
  101. size="small"
  102. style="margin-left: 5px"
  103. type="success"
  104. @click="submitUpload"
  105. >确认上传</el-button
  106. >
  107. <el-button
  108. size="small"
  109. style="margin-left: 5px"
  110. type="danger"
  111. @click="removeFile"
  112. >清空文件</el-button
  113. >
  114. <el-button
  115. size="small"
  116. style="margin-left: 5px"
  117. type="info"
  118. @click="exportFile"
  119. >下载模板</el-button
  120. >
  121. <div slot="tip" class="el-upload__tip">
  122. 只能上传xlsx文件
  123. </div>
  124. </el-upload>
  125. </el-form-item>
  126. </el-row>
  127. </el-form>
  128. </el-dialog>
  129. <!-- 导入错误信息列表 -->
  130. <el-dialog title="错误提示" :visible.sync="errDialog">
  131. <div
  132. v-for="errMessage in errMessages"
  133. :key="errMessage.row"
  134. class="text-danger"
  135. >
  136. 第{{ errMessage.row }}行:{{ errMessage.excelErrorType }}
  137. </div>
  138. <span slot="footer" class="dialog-footer">
  139. <el-button @click="errDialog = false">确定</el-button>
  140. </span>
  141. </el-dialog>
  142. <div class="block-seperator"></div>
  143. <!-- 页面列表 -->
  144. <el-table
  145. v-loading="loading"
  146. stripe
  147. element-loading-text="拼命加载中"
  148. :data="tableData"
  149. border
  150. style="width: 100%"
  151. >
  152. <el-table-column
  153. label="课程名称"
  154. width="200"
  155. prop="name"
  156. ></el-table-column>
  157. <el-table-column
  158. label="课程代码"
  159. min-width="100"
  160. prop="code"
  161. ></el-table-column>
  162. <el-table-column
  163. label="试卷数"
  164. min-width="100"
  165. prop="totalCount"
  166. ></el-table-column>
  167. <el-table-column
  168. label="评卷员数"
  169. min-width="100"
  170. prop="markerCount"
  171. ></el-table-column>
  172. <el-table-column
  173. label="给分间隔"
  174. min-width="100"
  175. prop="scoreStep"
  176. ></el-table-column>
  177. <el-table-column :context="_self" width="250" label="操作">
  178. <template slot-scope="scope">
  179. <div class="pull-left">
  180. <el-button
  181. v-if="scope.row.totalCount > 0"
  182. type="primary"
  183. size="mini"
  184. plain
  185. @click="fastSetting(scope.$index, scope.row)"
  186. >快速设置</el-button
  187. >
  188. <el-button
  189. type="primary"
  190. size="mini"
  191. plain
  192. @click="openStepModel(scope.row)"
  193. >给分间隔设置</el-button
  194. >
  195. </div>
  196. </template>
  197. </el-table-column>
  198. </el-table>
  199. <div class="page pull-right">
  200. <el-pagination
  201. background
  202. :current-page="currentPage"
  203. :page-size="pageSize"
  204. :page-sizes="[10, 20, 50, 100, 200, 300]"
  205. layout="total, sizes, prev, pager, next, jumper"
  206. :total="total"
  207. @current-change="handleSettingCurrentChange"
  208. @size-change="handleSizeChange"
  209. ></el-pagination>
  210. </div>
  211. </div>
  212. <el-dialog
  213. title="设置给分间隔"
  214. width="500px"
  215. :visible.sync="stepModel"
  216. :close-on-click-modal="false"
  217. @close="closeStepModel"
  218. >
  219. <el-form
  220. ref="stepForm"
  221. :key="stepModelKey"
  222. :inline="true"
  223. :model="stepForm"
  224. :rules="stepRules"
  225. label-width="90px"
  226. >
  227. <el-row>
  228. <el-form-item label="给分间隔" prop="step">
  229. <el-input-number
  230. v-model="stepForm.step"
  231. size="mini"
  232. :precision="1"
  233. :step="0.1"
  234. :min="0.1"
  235. :max="100"
  236. ></el-input-number>
  237. </el-form-item>
  238. </el-row>
  239. <el-row class="pull-center">
  240. <el-button
  241. type="primary"
  242. :loading="stepForm.loading"
  243. @click="subStep"
  244. >确定</el-button
  245. >
  246. <el-button @click="closeStepModel">取消</el-button>
  247. </el-row>
  248. </el-form>
  249. </el-dialog>
  250. </div>
  251. </section>
  252. </div>
  253. </template>
  254. <script>
  255. import { MARKING_API, DATA_PROCESS_API } from "@/constants/constants";
  256. import { mapState } from "vuex";
  257. import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
  258. export default {
  259. components: {
  260. LinkTitlesCustom,
  261. },
  262. data() {
  263. return {
  264. formSearch: {
  265. courseCode: "",
  266. courseName: "",
  267. specialtyLevel: "",
  268. specialtyName: "",
  269. leader: "",
  270. },
  271. courseList: [],
  272. tableData: [],
  273. oldData: [],
  274. currentPage: 1,
  275. pageSize: 10,
  276. total: 10,
  277. loading: true,
  278. workId: "",
  279. markTasks: {
  280. workId: "",
  281. userId: [],
  282. paperId: "",
  283. },
  284. stepModel: false,
  285. stepModelKey: Math.random(),
  286. stepForm: {
  287. workId: null,
  288. courseCode: null,
  289. step: null,
  290. loading: false,
  291. },
  292. paperId: "",
  293. impDialog: false,
  294. uploadAction: DATA_PROCESS_API + "/markTasks/import",
  295. uploadHeaders: {},
  296. uploadData: { workId: "" },
  297. errMessages: [],
  298. errDialog: false,
  299. fileLoading: false,
  300. fileList: [],
  301. stepRules: {
  302. step: [
  303. { required: true, message: "请输入给分间隔", trigger: "change" },
  304. ],
  305. },
  306. };
  307. },
  308. computed: {
  309. ...mapState({ user: (state) => state.user }),
  310. courseAllListSelect() {
  311. let courseSelect = [];
  312. for (let course of this.courseList) {
  313. let courseInfo = course.name + "(" + course.code + ")";
  314. courseSelect.push({ code: course.code, courseInfo: courseInfo });
  315. }
  316. return courseSelect;
  317. },
  318. },
  319. created() {
  320. this.workId = this.$route.params.workId;
  321. this.uploadData.workId = this.workId;
  322. this.uploadHeaders = {
  323. key: this.user.key,
  324. token: this.user.token,
  325. };
  326. this.initSetting();
  327. this.getCourses();
  328. },
  329. methods: {
  330. openStepModel(row) {
  331. this.stepForm.step = row.scoreStep || 0.5;
  332. this.stepForm.workId = row.workId;
  333. this.stepForm.courseCode = row.code;
  334. this.stepModel = true;
  335. },
  336. closeStepModel() {
  337. this.stepModel = false;
  338. this.stepModelKey = Math.random();
  339. },
  340. async subStep() {
  341. let res = await this.$refs.stepForm.validate();
  342. if (!res) {
  343. return;
  344. }
  345. this.stepForm.loading = true;
  346. var url =
  347. MARKING_API +
  348. "/markCourses/score-step?workId=" +
  349. this.stepForm.workId +
  350. "&courseCode=" +
  351. this.stepForm.courseCode +
  352. "&scoreStep=" +
  353. this.stepForm.step;
  354. this.$httpWithMsg
  355. .put(url)
  356. .then(() => {
  357. this.$notify({
  358. type: "success",
  359. message: "设置成功!",
  360. });
  361. this.closeStepModel();
  362. this.initSetting();
  363. })
  364. .finally(() => (this.stepForm.loading = false));
  365. },
  366. //查询课程
  367. getCourses() {
  368. this.$http
  369. .get(
  370. MARKING_API +
  371. "/markResults/queryExamCourseList?workId=" +
  372. this.$route.params.workId
  373. )
  374. .then((response) => {
  375. this.courseList = response.data;
  376. });
  377. },
  378. fastSetting(index, row) {
  379. this.paperId = row.pk;
  380. var url =
  381. "/marking/mark_setting_fast/" +
  382. this.$route.params.workId +
  383. "/" +
  384. this.$route.params.name +
  385. "/" +
  386. row.code +
  387. "/" +
  388. row.name;
  389. this.$router.push({
  390. path: url,
  391. });
  392. },
  393. filterSetting() {
  394. if (!this.formSearch.courseCode && !this.formSearch.courseName) {
  395. return;
  396. }
  397. var tempData = this.tableData.filter((element) => {
  398. var flag = true;
  399. if (this.formSearch.courseCode || this.formSearch.courseName) {
  400. if (this.formSearch.courseCode) {
  401. flag =
  402. flag && element.courseCode.includes(this.formSearch.courseCode);
  403. }
  404. if (this.formSearch.courseName) {
  405. flag =
  406. flag && element.courseName.includes(this.formSearch.courseName);
  407. }
  408. return flag;
  409. } else {
  410. return true;
  411. }
  412. });
  413. this.tableData = tempData;
  414. this.total = tempData.length;
  415. },
  416. handleSettingCurrentChange(val) {
  417. this.currentPage = val;
  418. this.initSetting();
  419. },
  420. handleSizeChange(val) {
  421. this.pageSize = val;
  422. this.initSetting();
  423. },
  424. pagingSetting() {
  425. var start = (this.currentPage - 1) * this.pageSize;
  426. var end =
  427. this.currentPage * this.pageSize < this.total
  428. ? this.currentPage * this.pageSize
  429. : this.total;
  430. var tempData = [];
  431. console.log(`当前页: ${this.currentPage},开始:${start},结束:${end}`);
  432. for (let i = start; i < end; i++) {
  433. tempData.push(this.tableData[i]);
  434. }
  435. console.log(tempData);
  436. this.tableData = tempData;
  437. },
  438. initSetting() {
  439. this.loading = true;
  440. this.$http
  441. .get(
  442. MARKING_API +
  443. "/markCourses/all/" +
  444. (this.currentPage - 1) +
  445. "/" +
  446. this.pageSize +
  447. "?workId=" +
  448. this.workId,
  449. { params: this.formSearch }
  450. )
  451. .then((response) => {
  452. console.log(response.data);
  453. this.tableData = response.data.content;
  454. this.total = response.data.totalElements;
  455. this.oldData = this.tableData.slice(0);
  456. this.loading = false;
  457. });
  458. },
  459. searchSetting() {
  460. this.loading = true;
  461. this.tableData = this.oldData.slice(0);
  462. this.total = this.tableData.length;
  463. this.filterSetting();
  464. this.pagingSetting();
  465. this.loading = false;
  466. },
  467. back() {
  468. this.$router.push({
  469. path: "/marking/mark_work",
  470. });
  471. },
  472. //导入
  473. imp() {
  474. this.impDialog = true;
  475. this.initUpload();
  476. },
  477. initUpload() {
  478. this.fileList = [];
  479. },
  480. beforeUpload(file) {
  481. console.log(file);
  482. },
  483. uploadProgress() {
  484. console.log("uploadProgress");
  485. },
  486. uploadSuccess(response) {
  487. console.log("uploadSuccess");
  488. console.log(response);
  489. if (!response || response.length == 0) {
  490. this.$notify({
  491. message: "上传成功",
  492. type: "success",
  493. });
  494. this.fileLoading = false;
  495. this.impDialog = false;
  496. window.location.reload();
  497. } else {
  498. this.errMessages = response;
  499. this.errDialog = true;
  500. this.fileLoading = false;
  501. this.impDialog = false;
  502. }
  503. },
  504. uploadError(err) {
  505. var result = err.message.match(/\{.+}/);
  506. var errMessage = JSON.parse(result[0]).desc;
  507. this.$notify({
  508. message: errMessage,
  509. type: "error",
  510. });
  511. this.fileLoading = false;
  512. },
  513. //确定上传
  514. submitUpload() {
  515. if (!this.checkUpload()) {
  516. return false;
  517. }
  518. this.$refs.upload.submit();
  519. this.fileLoading = true;
  520. },
  521. checkUpload() {
  522. var fileList = this.$refs.upload.uploadFiles;
  523. if (fileList.length == 0) {
  524. this.$notify({
  525. message: "上传文件不能为空",
  526. type: "error",
  527. });
  528. return false;
  529. }
  530. if (fileList.length > 1) {
  531. this.$notify({
  532. message: "每次只能上传一个文件",
  533. type: "error",
  534. });
  535. return false;
  536. }
  537. for (let file of fileList) {
  538. if (!file.name.endsWith(".xlsx")) {
  539. this.$notify({
  540. message: "上传文件必须为xlsx格式",
  541. type: "error",
  542. });
  543. this.initUpload();
  544. return false;
  545. }
  546. }
  547. return true;
  548. },
  549. //清空文件
  550. removeFile() {
  551. this.fileList = [];
  552. },
  553. //下载模板
  554. exportFile() {
  555. var key = this.user.key;
  556. var token = this.user.token;
  557. window.location.href =
  558. "/api/ecs_data_process/markTasks/export?$key=" +
  559. key +
  560. "&$token=" +
  561. token;
  562. },
  563. //下载课程列表
  564. exportCourse() {
  565. var key = this.user.key;
  566. var token = this.user.token;
  567. let url =
  568. "/api/ecs_marking/markCourses/export?workId=" +
  569. this.workId +
  570. "&$key=" +
  571. key +
  572. "&$token=" +
  573. token;
  574. let courseCode = this.formSearch.courseCode;
  575. if (courseCode) {
  576. url = url + "&courseCode=" + courseCode;
  577. }
  578. window.location.href = url;
  579. },
  580. handleCommand(buttonType) {
  581. if (buttonType == "in") this.imp();
  582. else if (buttonType == "out") this.exportCourse();
  583. },
  584. },
  585. };
  586. </script>
  587. <style lang="css" scoped>
  588. li {
  589. list-style-type: none;
  590. }
  591. .searchFrame {
  592. margin-right: 10px;
  593. margin-bottom: 10px;
  594. }
  595. .page {
  596. margin-top: 10px;
  597. }
  598. .f_button {
  599. display: block;
  600. width: 57px;
  601. height: 20px;
  602. border: 1px solid #ccc;
  603. background: #fff;
  604. font-size: small;
  605. }
  606. </style>