CropperTaskDetailDialog.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <Modal
  3. class="cropper-task-detail-dialog"
  4. v-model="modalIsShow"
  5. :title="title"
  6. :mask-closable="false"
  7. fullscreen
  8. footer-hide
  9. @on-visible-change="visibleChange"
  10. >
  11. <div class="cropper-task-detail">
  12. <div class="task-list" id="task-list">
  13. <div class="task-list-body" v-if="taskList.length">
  14. <div
  15. v-for="(task, index) in taskList"
  16. :key="index"
  17. :id="`task-${task.id}`"
  18. :class="[
  19. 'task-item',
  20. {
  21. 'task-current': task.id === curTask.id,
  22. 'task-over': task.isFinished
  23. }
  24. ]"
  25. @click="toDo(task)"
  26. >
  27. <div class="task-item-icon">
  28. <Icon type="ios-document" />
  29. </div>
  30. <p>{{ task.filename }}</p>
  31. </div>
  32. </div>
  33. </div>
  34. <div class="task-main">
  35. <div class="task-progress">
  36. <div class="task-progress-tips">
  37. <span>{{ finishedCount }}</span
  38. ><span>/</span><span>{{ taskCount }}</span>
  39. </div>
  40. <div class="task-progress-body">
  41. <Progress :percent="taskProgress" />
  42. </div>
  43. </div>
  44. <div class="task-body">
  45. <div class="task-body-item task-org">
  46. <scan-area-steps
  47. v-if="curTask.originImgPath && modalIsShow && curCollectConfig"
  48. :image-url="curTask.originImgPath"
  49. :cur-setting="curCollectConfig"
  50. :key="curTask.key"
  51. @on-finished="finished"
  52. ></scan-area-steps>
  53. <div v-else><p class="task-none">暂无数据</p></div>
  54. </div>
  55. <div class="task-body-item task-finally">
  56. <div class="task-finally-body">
  57. <img
  58. v-if="curTask.sliceImgPath"
  59. class="img-contain"
  60. :src="curTask.sliceImgPath"
  61. alt="裁切图"
  62. />
  63. </div>
  64. <div v-if="curTask.sliceImgPath" class="task-action box-justify">
  65. <h5>处理结果</h5>
  66. <Button
  67. type="primary"
  68. :disabled="loading"
  69. @click="toComfirmAndNext"
  70. >
  71. 确认并下一个
  72. </Button>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </Modal>
  79. </template>
  80. <script>
  81. import ScanAreaSteps from "../client/components/ScanAreaSteps";
  82. import {
  83. getCropperTaskDetailList,
  84. getCropperTaskFinishCount,
  85. updateCropperTaskDetail,
  86. updateCropperTaskFinishedCount
  87. } from "../../plugins/db";
  88. import { saveCropperImage, downloadOriginImg } from "./taskUtils";
  89. import { formatDate, randomCode } from "../../plugins/utils";
  90. import { getPaperInfo } from "./api";
  91. // const path = require("path");
  92. // const fs = require("fs");
  93. export default {
  94. name: "cropper-task-detail-dialog",
  95. components: { ScanAreaSteps },
  96. props: {
  97. cropperTask: {
  98. type: Object,
  99. default() {
  100. return {};
  101. }
  102. }
  103. },
  104. computed: {
  105. title() {
  106. return this.cropperTask.name;
  107. }
  108. },
  109. data() {
  110. return {
  111. modalIsShow: false,
  112. curTask: {},
  113. taskList: [],
  114. curCollectConfig: {},
  115. taskCount: 0,
  116. finishedCount: 0,
  117. taskProgress: 0,
  118. loading: false
  119. };
  120. },
  121. methods: {
  122. visibleChange(visible) {
  123. if (visible) {
  124. this.initData();
  125. } else {
  126. this.$emit("modified");
  127. }
  128. },
  129. cancel() {
  130. this.modalIsShow = false;
  131. },
  132. open() {
  133. this.modalIsShow = true;
  134. },
  135. async initData() {
  136. await this.getTasks();
  137. this.taskCount = this.cropperTask.taskCount;
  138. this.finishedCount = this.cropperTask.finishedCount;
  139. this.taskProgress =
  140. ((100 * this.finishedCount) / this.taskCount).toFixed(2) * 1;
  141. const nextTaskIndex = this.taskList.findIndex(item => !item.isFinished);
  142. if (nextTaskIndex === -1) {
  143. this.$Message.success("当前任务已全部结束");
  144. } else {
  145. this.curCollectConfig =
  146. nextTaskIndex === 0
  147. ? {}
  148. : JSON.parse(this.taskList[nextTaskIndex - 1].cropperSet);
  149. this.toDo(this.taskList[nextTaskIndex]);
  150. this.scrollTaskList(this.curTask.id);
  151. }
  152. },
  153. async getTasks() {
  154. const data = await getCropperTaskDetailList(this.cropperTask.id);
  155. this.taskList = data || [];
  156. },
  157. async updateProgress() {
  158. this.finishedCount = await getCropperTaskFinishCount(this.cropperTask.id);
  159. await updateCropperTaskFinishedCount({
  160. id: this.cropperTask.id,
  161. finishedCount: this.finishedCount
  162. });
  163. this.taskProgress =
  164. ((100 * this.finishedCount) / this.taskCount).toFixed(2) * 1;
  165. },
  166. scrollTaskList(taskId) {
  167. const taskDom = document.getElementById(`task-${taskId}`);
  168. const scrollTop = Math.max(0, taskDom.offsetTop - 84);
  169. document.getElementById("task-list").scrollTop = scrollTop;
  170. },
  171. async getOriginImg(paperInfo) {
  172. if (paperInfo.originImgPath) return paperInfo.originImgPath;
  173. const pInfo = await getPaperInfo({
  174. workId: paperInfo.workId,
  175. subjectId: paperInfo.subjectId,
  176. examNumber: paperInfo.examNumber
  177. }).catch(() => {});
  178. if (!pInfo) {
  179. this.$Message.error("获取原图失败,请重新尝试!");
  180. return;
  181. }
  182. this.curTask.paperId = paperInfo.id;
  183. const outputOriginPath = await downloadOriginImg({
  184. ...paperInfo,
  185. url: pInfo.imgSrc
  186. }).catch(() => {});
  187. if (!outputOriginPath) {
  188. this.$Message.error("下载原图失败,请重新尝试!");
  189. return;
  190. }
  191. this.curTask.originImgPath = outputOriginPath;
  192. },
  193. async toDo(task) {
  194. this.curTask = {
  195. ...task,
  196. key: randomCode()
  197. };
  198. await this.getOriginImg(task);
  199. // 在没有裁切图的情况下,自动根据已保存的设置信息生成裁切图。
  200. if (!this.curTask.sliceImgPath && this.curCollectConfig["codeArea"]) {
  201. this.loading = true;
  202. let res = await this.saveCurImage().catch(() => {});
  203. this.loading = false;
  204. if (!res) return;
  205. }
  206. },
  207. async curTaskFinished(setting) {
  208. await updateCropperTaskDetail({
  209. id: this.curTask.id,
  210. cropperSet: JSON.stringify(setting),
  211. originImgPath: this.curTask.originImgPath,
  212. formalImgPath: this.curTask.formalImgPath,
  213. sliceImgPath: this.curTask.sliceImgPath,
  214. isFinished: 1,
  215. isUpload: 0,
  216. updateTime: formatDate()
  217. });
  218. await this.updateProgress();
  219. const curTask = this.taskList.find(item => item.id === this.curTask.id);
  220. curTask.isFinished = true;
  221. return true;
  222. },
  223. async saveCurImage() {
  224. let res = await saveCropperImage(
  225. this.curTask,
  226. this.curCollectConfig
  227. ).catch(() => {});
  228. if (!res) {
  229. return Promise.reject();
  230. }
  231. this.curTask.sliceImgPath = res.outputSlicelPath;
  232. this.curTask.formalImgPath = res.outputFormalPath;
  233. return true;
  234. },
  235. async finished(setting) {
  236. if (this.loading) return;
  237. this.loading = true;
  238. this.curCollectConfig = setting;
  239. let res = await this.saveCurImage().catch(() => {
  240. this.loading = false;
  241. });
  242. if (!res) {
  243. this.$Message.error("保存图片失败,请重新尝试!");
  244. return;
  245. }
  246. res = await this.curTaskFinished(setting).catch(() => {});
  247. this.loading = false;
  248. if (!res) {
  249. this.$Message.error("更新图片失败,请重新尝试!");
  250. return;
  251. }
  252. this.toNextTask();
  253. },
  254. async toComfirmAndNext() {
  255. if (this.loading) return;
  256. this.loading = true;
  257. const res = await this.curTaskFinished(
  258. this.curCollectConfig
  259. ).catch(() => {});
  260. this.loading = false;
  261. if (!res) {
  262. this.$Message.error("更新图片失败,请重新尝试!");
  263. return;
  264. }
  265. this.toNextTask();
  266. },
  267. toNextTask() {
  268. const nextTask = this.taskList.find(item => !item.isFinished);
  269. if (!nextTask) {
  270. this.$Message.success("当前任务已全部结束");
  271. return;
  272. }
  273. this.toDo(nextTask);
  274. this.scrollTaskList(this.curTask.id);
  275. }
  276. }
  277. };
  278. </script>