Blame view

common/utils/useUploadImgs.js 7.78 KB
c7df828a   刘淇   快速工单 样式优化
1
  import { ref } from 'vue'
7b1f488f   刘淇   封装下图片上传
2
  import { uploadImages } from '@/common/utils/upload'
7b1f488f   刘淇   封装下图片上传
3
4
  
  /**
c7df828a   刘淇   快速工单 样式优化
5
   * 图片上传组合式函数(兼容非TS环境,纯数组格式)
7b1f488f   刘淇   封装下图片上传
6
7
8
   * @param config 上传配置
   * @returns 上传相关方法和状态
   */
c7df828a   刘淇   快速工单 样式优化
9
  export function useUploadImgs(config) {
7b1f488f   刘淇   封装下图片上传
10
11
12
13
      // 默认配置
      const defaultConfig = {
          maxCount: 3,
          uploadText: '选择图片',
c7df828a   刘淇   快速工单 样式优化
14
          sizeType: ['compressed'],
7b1f488f   刘淇   封装下图片上传
15
16
17
          ...config
      }
  
c7df828a   刘淇   快速工单 样式优化
18
19
      // 核心修复:初始化为纯数组,且格式适配u-upload
      const imgList = ref([])
4c54ad5d   刘淇   转工单 选择是 传紧急程度和...
20
21
      // 确保 rawImgList 响应式对象的初始值也是空数组
      // const rawImgList = ref([]);
7b1f488f   刘淇   封装下图片上传
22
23
  
      /**
dacff5e3   刘淇   养护员退回
24
25
26
27
28
29
30
31
32
33
34
35
36
       * 新增:清空所有图片
       * 功能:重置图片列表为空,并触发表单字段校验(如果有表单Ref
       */
      const clearImgs = () => {
          imgList.value = [];
          // 优化:先判断 formRef 存在,再判断 formRef.value 存在
          if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
              defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
          }
      };
  
  
      /**
7b1f488f   刘淇   封装下图片上传
37
38
       * 删除图片
       */
c7df828a   刘淇   快速工单 样式优化
39
      const deleteImg = (event) => {
dacff5e3   刘淇   养护员退回
40
41
42
43
44
45
46
47
48
49
        const index = Number(event.index);
        if (isNaN(index) || index < 0 || index >= imgList.value.length) return;
  
        imgList.value.splice(index, 1);
        // 修复:先判断 formRef 存在,再访问 value
        if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
          defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
        }
        uni.showToast({ title: '图片删除成功', icon: 'success' });
      };
7b1f488f   刘淇   封装下图片上传
50
51
  
      /**
c7df828a   刘淇   快速工单 样式优化
52
       * 上传图片(适配u-uploadfile格式)
7b1f488f   刘淇   封装下图片上传
53
       */
c7df828a   刘淇   快速工单 样式优化
54
55
56
57
58
59
60
61
62
63
64
65
      const uploadImgs = async (event) => {
          // 核心修复:标准化file数据格式
          const rawFile = event.file || {}
          const fileList = Array.isArray(rawFile) ? rawFile : [rawFile]
  
          // 过滤无效文件
          const validFiles = fileList.filter(file => file && file.url)
          if (validFiles.length === 0) {
              uni.showToast({ title: '请选择有效图片', icon: 'none' })
              return
          }
  
7b1f488f   刘淇   封装下图片上传
66
67
          const targetImgList = imgList.value
  
c7df828a   刘淇   快速工单 样式优化
68
69
          // 校验最大数量
          if (targetImgList.length + validFiles.length > defaultConfig.maxCount) {
7b1f488f   刘淇   封装下图片上传
70
71
72
73
              uni.showToast({ title: `最多只能上传${defaultConfig.maxCount}张图片`, icon: 'none' })
              return
          }
  
c7df828a   刘淇   快速工单 样式优化
74
75
76
77
78
79
80
81
          // 核心修复:转换为u-upload兼容的格式
          const filePaths = validFiles.map(item => item.url)
          const tempItems = validFiles.map(item => ({
              url: item.url,
              status: 'uploading',
              message: '上传中',
              name: item.name || '',
              size: item.size || 0
7b1f488f   刘淇   封装下图片上传
82
83
84
85
86
87
88
89
90
91
92
93
94
95
          }))
          const startIndex = targetImgList.length
          targetImgList.push(...tempItems)
  
          try {
              const uploadResultUrls = await uploadImages({
                  filePaths: filePaths,
                  ignoreError: true
              })
  
              // 更新上传成功的图片
              uploadResultUrls.forEach((url, index) => {
                  if (targetImgList[startIndex + index]) {
                      targetImgList.splice(startIndex + index, 1, {
c7df828a   刘淇   快速工单 样式优化
96
97
                          url: url,
                          status: 'success',
7b1f488f   刘淇   封装下图片上传
98
                          message: '',
c7df828a   刘淇   快速工单 样式优化
99
100
                          name: validFiles[index].name || '',
                          size: validFiles[index].size || 0
7b1f488f   刘淇   封装下图片上传
101
102
103
104
105
                      })
                  }
              })
  
              // 处理上传失败的图片
c7df828a   刘淇   快速工单 样式优化
106
107
108
              if (uploadResultUrls.length < validFiles.length) {
                  const failCount = validFiles.length - uploadResultUrls.length
                  for (let i = uploadResultUrls.length; i < validFiles.length; i++) {
7b1f488f   刘淇   封装下图片上传
109
110
                      if (targetImgList[startIndex + i]) {
                          targetImgList.splice(startIndex + i, 1, {
c7df828a   刘淇   快速工单 样式优化
111
112
113
114
115
                              url: validFiles[i].url,
                              status: 'failed',
                              message: '上传失败',
                              name: validFiles[i].name || '',
                              size: validFiles[i].size || 0
7b1f488f   刘淇   封装下图片上传
116
117
118
119
120
                          })
                      }
                  }
                  uni.showToast({ title: `成功上传${uploadResultUrls.length}张,失败${failCount}张`, icon: 'none' })
              } else {
c7df828a   刘淇   快速工单 样式优化
121
                  uni.showToast({ title: `成功上传${validFiles.length}张图片`, icon: 'success' })
7b1f488f   刘淇   封装下图片上传
122
123
124
              }
  
              // 上传完成后校验
dacff5e3   刘淇   养护员退回
125
126
127
              if (defaultConfig.formRef && defaultConfig.formRef.value && defaultConfig.fieldName) {
                  defaultConfig.formRef.value.validateField(defaultConfig.fieldName);
              }
7b1f488f   刘淇   封装下图片上传
128
129
130
          } catch (err) {
              console.error(`【${defaultConfig.fieldName}】图片上传失败:`, err)
              // 标记所有上传失败
c7df828a   刘淇   快速工单 样式优化
131
              for (let i = 0; i < validFiles.length; i++) {
7b1f488f   刘淇   封装下图片上传
132
133
                  if (targetImgList[startIndex + i]) {
                      targetImgList.splice(startIndex + i, 1, {
c7df828a   刘淇   快速工单 样式优化
134
135
136
137
138
                          url: validFiles[i].url,
                          status: 'failed',
                          message: '上传失败',
                          name: validFiles[i].name || '',
                          size: validFiles[i].size || 0
7b1f488f   刘淇   封装下图片上传
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
                      })
                  }
              }
              uni.showToast({ title: '图片上传失败,请重试', icon: 'none' })
              // 上传失败后校验
              defaultConfig.formRef.value?.validateField(defaultConfig.fieldName)
          }
      }
  
      /**
       * 获取成功上传的图片URL列表
       */
      const getSuccessImgUrls = () => {
          return imgList.value.filter(item => item.status === 'success').map(item => item.url)
      }
  
      /**
       * 图片校验规则(供表单使用)
       */
      const imgValidateRule = {
          required: true,
          message: `请上传${defaultConfig.uploadText.replace('选择', '')}`,
          trigger: 'change',
c7df828a   刘淇   快速工单 样式优化
162
          validator: (rule, value, callback) => {
7b1f488f   刘淇   封装下图片上传
163
164
165
166
167
              const hasSuccessImg = imgList.value.some(item => item.status === 'success')
              hasSuccessImg ? callback() : callback(new Error(`请上传至少1${defaultConfig.uploadText.replace('选择', '')}`))
          }
      }
  
dacff5e3   刘淇   养护员退回
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
      /**
       * 新增:批量设置图片列表(图片回显核心方法,替代业务页面的setUploadImgsList
       * @param imgUrls 图片URL数组(如:['https://xxx.jpg', 'https://yyy.png']
       * 功能:将纯URL数组转换为u-upload兼容格式,实现静默回显,无数据时不提示
       */
      const setImgList = (imgUrls = []) => {
          // 容错处理:校验参数有效性,非数组/空数组直接重置
          if (!Array.isArray(imgUrls) || imgUrls.length === 0) {
              imgList.value = []
              return
          }
  
          // 转换为u-upload兼容的格式(status: success 标记为已成功上传,可正常显示/删除)
          const formatImgList = imgUrls.map(url => ({
              url: url,
              status: 'success', // 关键:标记为成功状态,兼容后续删除/校验逻辑
              message: '',
              name: url.substring(url.lastIndexOf('/') + 1), // 从URL截取文件名,优化显示
              size: 0 // 历史图片无大小信息,默认0不影响使用
          }))
  
          // 额外优化:限制回显数量不超过maxCount,避免异常
          const finalImgList = formatImgList.slice(0, defaultConfig.maxCount)
          imgList.value = finalImgList
      }
  
7b1f488f   刘淇   封装下图片上传
194
      return {
dacff5e3   刘淇   养护员退回
195
          imgList: imgList, // 核心修复:返回纯数组(解除响应式代理)
c7df828a   刘淇   快速工单 样式优化
196
          rawImgList: imgList,    // 保留响应式引用(内部使用)
7b1f488f   刘淇   封装下图片上传
197
198
          uploadImgs,
          deleteImg,
dacff5e3   刘淇   养护员退回
199
200
          clearImgs,
          setImgList,
7b1f488f   刘淇   封装下图片上传
201
202
203
204
205
          getSuccessImgUrls,
          imgValidateRule,
          uploadConfig: defaultConfig
      }
  }