download.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <template>
  2. <!-- hideFloor: state === State.package -->
  3. <div>
  4. <div class="title">
  5. {{ stateTitle[state] }}
  6. </div>
  7. <div v-if="state === State.package">
  8. <div
  9. class="text"
  10. style="display: flex; justify-content: space-between; margin-top: 15px"
  11. >
  12. <span>{{ filename }}</span>
  13. <span>{{ percent }}%</span>
  14. </div>
  15. <div style="pointer-events: none">
  16. <el-slider v-model="percent" :show-tooltip="false" />
  17. </div>
  18. </div>
  19. <div v-else-if="state === State.readDown">
  20. <span>正在下载中……</span>
  21. </div>
  22. </div>
  23. </template>
  24. <script setup lang="ts">
  25. import { computed, onMounted, onUnmounted, ref } from "vue";
  26. import saveAs from "@/util/file-serve";
  27. import {
  28. checkCaseHasDownload as checkHasDownload,
  29. getCaseHasDownloadProcess as getDownloadProcess,
  30. downloadCaseScene as downloadScene,
  31. axios,
  32. } from "@/request";
  33. import { ElLoading, ElMessage } from "element-plus";
  34. import { QuoteScene, SceneType } from "@/store/scene";
  35. import { QuiskExpose } from "@/helper/mount";
  36. const props = defineProps<{ caseId: number; title: string }>();
  37. enum State {
  38. uncreate,
  39. package,
  40. readDown,
  41. }
  42. const getState = (type: number) => {
  43. const stateTypes = [
  44. { codes: [0, 2], state: State.uncreate },
  45. { codes: [1], state: State.package },
  46. { codes: [3], state: State.readDown },
  47. ];
  48. return (
  49. stateTypes.find((stateType) => stateType.codes.includes(type))?.state ||
  50. State.uncreate
  51. );
  52. };
  53. const state = ref<State>(State.uncreate);
  54. const count = ref<number>(0);
  55. const filename = ref<string>(props.title + ".zip");
  56. const downloadURL = ref<string>();
  57. const percent = ref(0);
  58. const stateTitle = {
  59. [State.uncreate]: "下载案件离线数据包,可在本地运行查看。",
  60. [State.package]: "正在打包案件离线数据",
  61. [State.readDown]: filename.value,
  62. };
  63. const params = {
  64. caseId: props.caseId,
  65. };
  66. // 初始化
  67. const initial = async () => {
  68. const res = await axios.get(checkHasDownload, { params });
  69. state.value = getState(res.data.downloadStatus);
  70. count.value = res.data.count;
  71. downloadURL.value = res.data.downloadUrl;
  72. if (state.value === State.uncreate) {
  73. const downRes = await axios.get(downloadScene, { params });
  74. state.value = getState(downRes.data.downloadStatus);
  75. // const unCountFlag =
  76. // count.value == 0 ||(await axios.get(downloadScene, { params })).data.downloadStatus !== 1;
  77. if (state.value === State.uncreate) {
  78. ElMessage.error("下载失败,请联系管理员");
  79. throw "暂无剩余下载次数";
  80. }
  81. }
  82. if (state.value === State.package) {
  83. await new Promise<void>((resolve) => requestUpdateURL(resolve));
  84. } else {
  85. downloadURL.value = res.data.downloadUrl;
  86. }
  87. };
  88. // 下载
  89. const download = () => {
  90. if (!downloadURL.value) {
  91. ElMessage.error("下载链接未生成,请稍等!");
  92. throw "下载链接未生成,请稍等!";
  93. } else {
  94. if (!downloadURL.value.startsWith("/")) {
  95. downloadURL.value = "/" + downloadURL.value;
  96. }
  97. console.error("downloadURL.value", downloadURL.value);
  98. return saveAs(downloadURL.value, filename.value);
  99. }
  100. };
  101. // 进度请求
  102. let timer: any;
  103. const requestUpdateURL = async (callback: () => void) => {
  104. const res = await axios.get(getDownloadProcess, { params });
  105. percent.value = parseInt(res.data.percent);
  106. downloadURL.value = percent.value === 100 ? res.data.url : null;
  107. if (downloadURL.value) {
  108. state.value = State.readDown;
  109. callback();
  110. } else {
  111. timer = setTimeout(() => requestUpdateURL(callback), 1000);
  112. }
  113. };
  114. onUnmounted(() => clearTimeout(timer));
  115. defineExpose<QuiskExpose>({
  116. submit: async () => {
  117. await initial();
  118. const loading = ElLoading.service({
  119. lock: true,
  120. text: "下载中",
  121. background: "rgba(255, 255, 255, 0.4)",
  122. });
  123. await download();
  124. loading.close();
  125. ElMessage.success("下载完成");
  126. },
  127. });
  128. </script>