addPhotoFileAll.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <el-form
  3. ref="form"
  4. :model="caseFile"
  5. label-width="90px"
  6. class="camera-from dispatch-file-from"
  7. >
  8. <el-form-item label="照片:" class="mandatory">
  9. <el-upload
  10. class="upload-demo"
  11. :multiple="true"
  12. :limit="10"
  13. :before-upload="upload"
  14. v-model:file-list="fileList"
  15. :http-request="httpsApi"
  16. :on-preview="previewFile"
  17. :on-exceed="handleExceed"
  18. :accept="photoFormats.join(',')"
  19. :on-remove="handleRemove"
  20. >
  21. <el-button type="primary" :disabled="!!file">
  22. <el-icon><Upload /></el-icon>上传
  23. </el-button>
  24. <template v-slot:tip>
  25. <div class="el-upload__tip">
  26. 注:可上传{{ size }}以内的{{ photoFormatDesc }}
  27. </div>
  28. </template>
  29. <template v-slot:file="{ file }">
  30. <div class="file" @click.stop="previewFile()">
  31. <div>
  32. <el-icon><Document /></el-icon>
  33. <span class="name">{{ file.name }}</span>
  34. </div>
  35. <el-icon @click.stop="removeFile(file)"><Close /></el-icon>
  36. </div>
  37. </template>
  38. </el-upload>
  39. </el-form-item>
  40. <!-- <el-form-item label="附件标题:" class="mandatory">
  41. <el-input
  42. v-model="caseFile.imgInfo"
  43. placeholder="请输入最多不能超过50字"
  44. maxlength="50"
  45. show-word-limit
  46. ></el-input>
  47. </el-form-item> -->
  48. </el-form>
  49. </template>
  50. <script setup lang="ts">
  51. import {
  52. DrawFormatDesc,
  53. DrawFormats,
  54. photoFormats,
  55. photoFormatDesc,
  56. FileDrawType,
  57. OtherFormatDesc,
  58. OtherFormats,
  59. } from "@/constant/caseFile";
  60. import { uploadFile } from "@/store/system";
  61. import { maxFileSize } from "@/constant/caseFile";
  62. import { useUpload } from "@/hook/upload";
  63. import { saveOrAndSave, CaseImg } from "@/store/case";
  64. import { ElMessage } from "element-plus";
  65. import { computed, ref, watch, watchEffect } from "vue";
  66. import { QuiskExpose } from "@/helper/mount";
  67. import type { UploadProps } from "element-plus";
  68. const props = defineProps<{
  69. caseId: number;
  70. data: CaseImg;
  71. }>();
  72. const defaultUpload = (
  73. file: File,
  74. onPercentage: (percentage: number) => void
  75. ) => {
  76. onPercentage(100);
  77. };
  78. const caseFile = ref<CaseImg>({
  79. caseId: props.caseId,
  80. id: props.data?.id,
  81. imgUrl: props.data.imgUrl,
  82. imgInfo: props.data.imgInfo,
  83. sort: props.data?.sort || "",
  84. } as any);
  85. const { size, previewFile, file, accept, percentage, format } = useUpload({
  86. maxSize: maxFileSize,
  87. formats: DrawFormats,
  88. });
  89. const handleExceed = () => {
  90. return ElMessage.error(`最大上传数量为10个`);
  91. };
  92. const upload = async (file: File) => {
  93. const fileType = file.name
  94. .substring(file.name.lastIndexOf("."))
  95. .toUpperCase();
  96. if (!photoFormats.some((type) => type.toUpperCase() === fileType)) {
  97. ElMessage.error(`请上传${photoFormatDesc}`);
  98. return false;
  99. } else if (file.size > maxFileSize) {
  100. ElMessage.error(`请上传${size.value}以内的文件`);
  101. return false;
  102. } else {
  103. console.log("file", file);
  104. fileList.value.push(file);
  105. await defaultUpload(file, (val) => (percentage.value = val));
  106. if (fileType === ".RAW") {
  107. }
  108. percentage.value = undefined;
  109. return true;
  110. }
  111. };
  112. const fileList = ref([]);
  113. const formatDesc = computed(() => DrawFormatDesc);
  114. watch(
  115. props,
  116. (newValue) => {
  117. caseFile.value.id = newValue.data.id;
  118. caseFile.value.imgInfo = newValue.data.imgInfo;
  119. caseFile.value.imgUrl = newValue.data.imgUrl;
  120. caseFile.value.sort = newValue.data.sort;
  121. if (newValue.data.imgUrl) {
  122. file.value = {
  123. name: newValue.data.imgInfo || "",
  124. url: newValue.data.imgUrl || "",
  125. };
  126. }
  127. },
  128. { immediate: true }
  129. );
  130. watchEffect(() => {
  131. if (file.value?.name) {
  132. caseFile.value.imgInfo = file.value?.name.substring(0, 50);
  133. }
  134. });
  135. const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  136. console.log(uploadFile, uploadFiles);
  137. };
  138. const removeFile = (file) => {
  139. fileList.value = fileList.value.filter(
  140. (item) => item.raw.url !== file.raw.url
  141. );
  142. };
  143. const httpsApi = async ({ file }) => {
  144. console.log("httpsApi", file);
  145. let fileUrl = await uploadFile(file);
  146. file.url = fileUrl;
  147. console.log("httpsApi", file, fileUrl);
  148. };
  149. defineExpose<QuiskExpose>({
  150. async submit() {
  151. console.log("defineExpose", fileList.value);
  152. if (!fileList.value.length) {
  153. ElMessage.error("请上传照片");
  154. throw "请上传照片";
  155. }
  156. // console.log("defineExpose", caseFile.value, file.value);
  157. const af = fileList.value.filter(
  158. (item) => item.raw && item.raw?.url && item.raw?.url.length > 0
  159. );
  160. const isAllupload = af.length === fileList.value.length;
  161. if (isAllupload) {
  162. let imgUrls = fileList.value.map((item) => {
  163. return {
  164. imgUrl: item.raw && item.raw.url,
  165. imgInfo: item.name.replace(/\.[^/.]+$/, ""),
  166. caseId: props.caseId,
  167. };
  168. });
  169. await saveOrAndSave({ imgUrls });
  170. } else {
  171. ElMessage.warning("上传中,请等候!");
  172. throw "上传中,请等候!";
  173. }
  174. // return caseFile.value;
  175. },
  176. });
  177. </script>
  178. <style scoped lang="scss">
  179. .upload-demo {
  180. overflow: hidden;
  181. }
  182. .file {
  183. display: flex;
  184. justify-content: space-between;
  185. align-items: center;
  186. > div {
  187. display: flex;
  188. align-items: center;
  189. }
  190. .name {
  191. margin-left: 10px;
  192. }
  193. }
  194. </style>