/** * 小程序拍照凭证上传(OpenSpec 基线) * chooseImage → uni.uploadFile → 收集 URL → 业务接口再传 imageUrls */ import { API_BASE, TOKEN_KEY, UPLOAD_API } from '@/config/api' function parseUploadBody(raw) { try { return JSON.parse(typeof raw === 'string' ? raw : String(raw || '')) } catch { return {} } } function extractUrl(body) { const data = body && body.data if (!data || typeof data !== 'object') return '' const url = data.url || data.fileUrl || data.file_url return url != null ? String(url).trim() : '' } function getToken() { const raw = uni.getStorageSync(TOKEN_KEY) return typeof raw === 'string' ? raw.trim() : raw ? String(raw).trim() : '' } /** * @param {{ folder?: string, maxCount?: number, currentUrls?: string[], uploadUrl?: string }} opts * @returns {Promise} 本次新上传成功的 URL 列表 */ export async function chooseAndUploadImages(opts = {}) { const folder = opts.folder || 'mini-evidence' const maxCount = opts.maxCount != null ? opts.maxCount : 6 const currentUrls = Array.isArray(opts.currentUrls) ? opts.currentUrls : [] const uploadUrl = opts.uploadUrl || `${API_BASE}${UPLOAD_API.IMAGE}` const remain = maxCount - currentUrls.length if (remain <= 0) { uni.showToast({ title: `最多上传${maxCount}张`, icon: 'none' }) return [] } const choose = await new Promise((resolve) => { uni.chooseImage({ count: remain, sizeType: ['compressed'], sourceType: ['album', 'camera'], success: (res) => resolve(res), fail: () => resolve(null) }) }) if (!choose?.tempFilePaths?.length) return [] const token = getToken() const urls = [] uni.showLoading({ title: '上传中...' }) try { for (const filePath of choose.tempFilePaths) { const uploadRes = await new Promise((ok, fail) => { uni.uploadFile({ url: uploadUrl, filePath, name: 'file', header: { Authorization: token ? `Bearer ${token}` : '' }, formData: { folder }, success: ok, fail }) }) if (uploadRes.statusCode === 401) { uni.showToast({ title: '登录已失效,请重新登录', icon: 'none' }) break } const body = parseUploadBody(uploadRes.data) const url = extractUrl(body) if (body.code !== 200 || !url) { uni.showToast({ title: body.message || '上传失败', icon: 'none' }) break } urls.push(url) } } catch (e) { uni.showToast({ title: e instanceof Error ? e.message : '上传失败', icon: 'none' }) } finally { uni.hideLoading() } return urls } export function previewImages(urls, current) { const list = (urls || []).map((u) => String(u || '').trim()).filter(Boolean) if (!list.length) return uni.previewImage({ urls: list, current: current || list[0] }) }