index.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <template>
  2. <a-upload :show-file-list="true" :custom-request="handelUpload == null ? customRequest : handelUpload"
  3. :list-type="listType" :file-list="fileList" :limit="minx" @before-remove="beforeRemove" :show-remove-button="showRemoveButton" :show-cancel-button="false"
  4. :image-preview="imagePreview" :accept="accept" @before-upload="beforeUpload" />
  5. </template>
  6. <script setup>
  7. import { toRef, ref, watch, watchEffect, onMounted } from 'vue';
  8. import { useSystemStore } from '@/store/modules/systemStore';
  9. import { Modal } from "@arco-design/web-vue";
  10. import { useI18n } from 'vue-i18n';
  11. import { Message } from "@arco-design/web-vue";
  12. const systemStore = useSystemStore();
  13. const { t } = useI18n();
  14. // 自定义请求:上传文件的处理逻辑
  15. const customRequest = async (option) => {
  16. const { file } = option.fileItem;
  17. const fileName = `thumbnail_${file.name}`;
  18. const key = `test/${fileName}`;
  19. // 获取上传客户端(假设 systemStore 已经定义了上传接口)
  20. const client = await systemStore.getSTSClient();
  21. const resClient = await client.putObject({
  22. key: key,
  23. body: file
  24. });
  25. // 上传成功后,更新 fileList 和 modelValue
  26. if (resClient.statusCode === 200) {
  27. const uploadedFileUrl = resClient.url;
  28. fileList.value.push({ url: uploadedFileUrl, name: fileName, status: resClient.statusCode, uid: '0' });
  29. // 更新父组件的 modelValue
  30. if (minx.value === 1) {
  31. emit('update:modelValue', uploadedFileUrl);
  32. } else {
  33. emit('update:modelValue', fileList.value.map(res => res.url).join(','));
  34. }
  35. }
  36. };
  37. // 接收外部传入的 props:modelValue 和 minx
  38. const props = defineProps({
  39. modelValue: {
  40. type: [String, Array],
  41. default: "",
  42. },
  43. minx: {
  44. type: Number,
  45. default: 1
  46. },
  47. listType: {
  48. type: String,
  49. default: 'picture-card'
  50. },// 上传样式
  51. imagePreview: {
  52. type: Boolean,
  53. default: true
  54. }, // 是否支持预览
  55. accept: {
  56. type: String,
  57. default: ''
  58. }, // 上传文件类型
  59. handelUpload: {
  60. type: Function,
  61. default: null // 外部传入的自定义上传方法
  62. },
  63. showRemoveButton:{
  64. type: Boolean,
  65. default: true // 是否显示删除按钮
  66. },
  67. beforeUpload: {
  68. type: Boolean,
  69. default: false,
  70. },
  71. });
  72. // 使用 toRef 确保对 props 的访问是响应式的
  73. const minx = toRef(props, 'minx');
  74. const modelValue = toRef(props, 'modelValue');
  75. const listType = toRef(props, 'listType');
  76. const imagePreview = toRef(props, 'imagePreview');
  77. const handelUpload = toRef(props, 'handelUpload');
  78. // 定义 emit,用于向外抛出事件
  79. const emit = defineEmits(["update:modelValue"]);
  80. // 用于存储文件列表,初始化时显示传递给子组件的值
  81. const fileList = ref([]);
  82. // 删除文件处理逻辑
  83. const beforeRemove = (file) => {
  84. return new Promise((resolve, reject) => {
  85. Modal.confirm({
  86. title: $t("customer.confirmRemoveUpload"),
  87. onOk: () => {
  88. // 更新 fileList 和 modelValue,移除删除的文件
  89. fileList.value = fileList.value.filter((item) => item.url !== file.url);
  90. if (minx.value === 1) {
  91. emit(
  92. "update:modelValue",
  93. fileList.value.length > 0 ? fileList.value[0].url : ""
  94. );
  95. } else {
  96. emit(
  97. "update:modelValue",
  98. fileList.value.map((res) => res.url).join(",")
  99. );
  100. }
  101. resolve(true); // 确认删除
  102. },
  103. onCancel: () => reject("cancel"), // 取消删除
  104. });
  105. });
  106. };
  107. watchEffect(() => {
  108. if (modelValue.value) {
  109. if (Array.isArray(modelValue.value)) {
  110. // 如果传递的是数组,则直接使用
  111. fileList.value = modelValue.value.map(item => ({ url: item, status: item.status, name: item.name }));
  112. } else if (typeof modelValue.value === 'string') {
  113. // 如果传递的是字符串,则将字符串按逗号分割成数组
  114. const urlList = modelValue.value.split(',').map(url => ({ url: url.trim() }));
  115. fileList.value = urlList;
  116. }
  117. } else {
  118. fileList.value = [];
  119. }
  120. })
  121. onMounted(() => {
  122. })
  123. // 上传前校验
  124. const beforeUpload = (rawFile) => {
  125. if(!props.beforeUpload) return true
  126. const isAllowType =
  127. rawFile.type === "image/png" ||
  128. rawFile.type === "image/jpg" ||
  129. rawFile.type === "image/jpeg";
  130. if (!isAllowType) {
  131. Message.error("图片仅支持jpg或png");
  132. return false;
  133. } else if (rawFile.size / 1024 / 1024 > 2) {
  134. Message.error("图片不能大于2M");
  135. return false;
  136. }
  137. return true;
  138. };
  139. </script>
  140. <style scoped>
  141. /* 可自定义样式 */
  142. </style>