import { request, uploadFile, NOT_LOGIN_CODE } from '../../utils/request' import { ProcessStatus } from '../../utils/config' Page({ data: { state: 'idle' as 'idle' | 'processing' | 'failed', imagePath: '', clothesUuid: '', failReason: '', step: 0, }, onChoose() { wx.showActionSheet({ itemList: ['拍照', '从相册选择'], success: (res) => { const sourceType: Array<'camera' | 'album'> = res.tapIndex === 0 ? ['camera'] : ['album'] this.chooseImage(sourceType) }, fail: () => {}, // 取消选择属正常操作,不必抛错日志 }) }, chooseImage(sourceType: Array<'camera' | 'album'>) { wx.chooseMedia({ count: 1, mediaType: ['image'], sourceType, success: (res) => { const file = res.tempFiles[0] this.startUpload(file.tempFilePath) }, }) }, startUpload(filePath: string) { this.setData({ state: 'processing', imagePath: filePath, step: 0, failReason: '' }) uploadFile<{ clothes_uuid: string; image_process_status: number }>(filePath) .then((res) => { this.setData({ clothesUuid: res.clothes_uuid }) this.askNextAction() }) .catch((e: any) => { this.setData({ state: 'idle' }) if (e && e.code === 80000) { this.showQuotaModal() return } // uploadFile 已统一 toast 业务错误与网络错误;未登录时请求并未发出,需补一次提示 if (e && e.code === NOT_LOGIN_CODE) { wx.showToast({ title: '请先登录', icon: 'none' }) } }) }, askNextAction() { // 后台继续轮询,仅用于更新步骤进度(不再自动跳详情) this.pollStatus(this.data.clothesUuid) // 立即弹窗让用户选择下一步,避免干等 wx.showModal({ title: '衣物已上传', content: 'AI 正在识别中,可在衣橱查看进度', confirmText: '继续上传', cancelText: '回到衣橱', success: (res) => { this.clearTimer() if (res.confirm) { this.setData({ state: 'idle', imagePath: '', clothesUuid: '', step: 0, failReason: '' }) } else { wx.navigateBack({ delta: 1, fail: () => wx.switchTab({ url: '/pages/wardrobe/wardrobe' }), }) } }, }) }, pollStatus(uuid: string) { let count = 0 ;(this as any).pollTimer = setInterval(() => { count++ request<{ image_process_status: number; fail_reason: string }>({ url: `/clothes/${uuid}/status`, showError: false, }) .then((res) => { const status = res.image_process_status if (status === ProcessStatus.MATTING) { this.setData({ step: 1 }) } else if (status === ProcessStatus.CLASSIFYING) { this.setData({ step: 2 }) } else if (status === ProcessStatus.SUCCESS) { // 处理成功不再自动跳转,由用户自行从衣橱进入详情 this.clearTimer() } else if (status === ProcessStatus.FAILED) { this.clearTimer() this.setData({ state: 'failed', failReason: res.fail_reason || '识别失败' }) } }) .catch(() => {}) if (count >= 60) { this.clearTimer() this.setData({ state: 'failed', failReason: '处理超时,请重试' }) } }, 1500) }, clearTimer() { const t = (this as any).pollTimer if (t) { clearInterval(t) ;(this as any).pollTimer = null } }, onUnload() { this.clearTimer() }, showQuotaModal() { wx.showModal({ title: '上传额度不足', content: '当前剩余 0 次,购买额度包后可继续上传', confirmText: '去购买', cancelText: '取消', success: (res) => { if (res.confirm) wx.navigateTo({ url: '/pages/mall/mall' }) }, }) }, onRetry() { this.setData({ state: 'idle', imagePath: '', clothesUuid: '', failReason: '' }) }, onManualEdit() { if (!this.data.clothesUuid) return wx.redirectTo({ url: `/pages/clothes-detail/clothes-detail?uuid=${this.data.clothesUuid}` }) }, })