// components/jifen-list/jifen-list.js import request from '../../../../utils/request.js'; const app = getApp(); const MEIYE_TIAOSHU = 5; Component({ properties: { status: { type: Number, value: 0, observer: 'reload' }, trigger: { type: Number, value: 0, observer: 'reload' } }, data: { chufaList: [], dangqianye: 1, haiyougengduo: true, jiazhaozhong: false, jiazhaigengduo: false, ossImageUrl: app.globalData.ossImageUrl || '', showXiangqing: false, xuanzhongChufa: {}, showShensuModal: false, shensuLiyou: '', shensuTupian: [], shangchuanJindu: 0, shangchuanZongshu: 0, jinduWidth: '0%', isShangchuanzhong: false, fangdouTimer: null }, lifetimes: { attached() { this.reload(); }, detached() { if (this.data.fangdouTimer) clearTimeout(this.data.fangdouTimer); } }, methods: { reload() { this.setData({ dangqianye: 1, chufaList: [], haiyougengduo: true }); this.loadJifenList(); }, async loadJifenList(isLoadMore = false) { if (this.data.jiazhaozhong || this.data.jiazhaigengduo) return; if (isLoadMore && !this.data.haiyougengduo) return; if (isLoadMore) this.setData({ jiazhaigengduo: true }); else this.setData({ jiazhaozhong: true }); try { const params = { page: this.data.dangqianye, page_size: MEIYE_TIAOSHU, zhuangtai: this.data.status }; const res = await request({ url: '/yonghu/dshqcfjl', method: 'POST', data: params }); if (res.statusCode === 200 && res.data.code === 0) { const data = res.data.data; if (data.list && Array.isArray(data.list)) { const processedList = data.list.map(item => { let displayTime = '--'; if (item.create_time) displayTime = item.create_time; let displayStatus = '未知状态', statusClass = 'zhuangtai-weizhi'; const n = Number(item.sqzhuangtai); if (!isNaN(n)) { if (n === 0) { displayStatus = '待处理'; statusClass = 'zhuangtai-daichuli'; } else if (n === 1) { displayStatus = '已处罚'; statusClass = 'zhuangtai-yichufa'; } else if (n === 2) { displayStatus = '处罚已撤销'; statusClass = 'zhuangtai-yibohui'; } else if (n === 3) { displayStatus = '申诉中'; statusClass = 'zhuangtai-shensuzhong'; } } return { ...item, display_time: displayTime, display_status: displayStatus, status_class: statusClass, full_zhengju_tupian: (item.zhengju_tupian || []).map(url => this.getFullImageUrl(url)), full_shensu_tupian: (item.shensu_tupian || []).map(url => this.getFullImageUrl(url)) }; }); const newList = isLoadMore ? [...this.data.chufaList, ...processedList] : processedList; this.setData({ chufaList: newList, haiyougengduo: data.has_more === true, dangqianye: this.data.dangqianye + 1 }); } else this.setData({ haiyougengduo: false }); } } catch (e) { wx.showToast({ title: '加载失败', icon: 'none' }); this.setData({ haiyougengduo: false }); } finally { if (isLoadMore) this.setData({ jiazhaigengduo: false }); else this.setData({ jiazhaozhong: false }); } }, onReachBottom() { if (this.data.fangdouTimer) clearTimeout(this.data.fangdouTimer); const timer = setTimeout(() => { if (this.data.jiazhaozhong || this.data.jiazhaigengduo) return; if (!this.data.haiyougengduo) return; this.loadJifenList(true); }, 300); this.setData({ fangdouTimer: timer }); }, chakanXiangqing(e) { this.setData({ showXiangqing: true, xuanzhongChufa: e.currentTarget.dataset.item }); }, guanbiXiangqing() { this.setData({ showXiangqing: false, xuanzhongChufa: {} }); }, openShensuModal() { const { xuanzhongChufa } = this.data; if (xuanzhongChufa.ssliyou || (xuanzhongChufa.shensu_tupian && xuanzhongChufa.shensu_tupian.length > 0)) { wx.showToast({ title: '您已经提交过申诉,请等待处理结果', icon: 'none' }); return; } this.setData({ showShensuModal: true, shensuLiyou: '', shensuTupian: [], shangchuanJindu: 0, shangchuanZongshu: 0, jinduWidth: '0%', isShangchuanzhong: false }); }, closeShensuModal() { this.setData({ showShensuModal: false }); }, onShensuLiyouInput(e) { this.setData({ shensuLiyou: e.detail.value.slice(0, 500) }); }, chooseShensuTupian() { if (this.data.isShangchuanzhong) return; const shengyu = 9 - this.data.shensuTupian.length; if (shengyu <= 0) { wx.showToast({ title: '最多只能上传9张图片', icon: 'none' }); return; } wx.chooseMedia({ count: shengyu, mediaType: ['image'], sourceType: ['album', 'camera'], success: (res) => { const newTupian = [...this.data.shensuTupian, ...res.tempFiles.map(f => f.tempFilePath)]; this.setData({ shensuTupian: newTupian.slice(0, 9) }); }}); }, deleteShensuTupian(e) { const arr = [...this.data.shensuTupian]; arr.splice(e.currentTarget.dataset.index, 1); this.setData({ shensuTupian: arr }); }, yulanShensuTupian(e) { const idx = e.currentTarget.dataset.index; const urls = this.data.shensuTupian; if (!urls[idx]) return; wx.previewImage({ current: urls[idx], urls }); }, yulanTupian(e) { const current = e.currentTarget.dataset.url; const urls = e.currentTarget.dataset.urls || []; const fullCurrent = current.startsWith('http') ? current : this.getFullImageUrl(current); const fullUrls = urls.map(url => url.startsWith('http') ? url : this.getFullImageUrl(url)); wx.previewImage({ current: fullCurrent, urls: fullUrls.length ? fullUrls : [fullCurrent] }); }, /* ========== 图片上传(完全照抄原 cfss.js) ========== */ // 【仅替换此方法,其余代码一个字别动】 getFullImageUrl(relativeUrl) { if (!relativeUrl) return ''; if (relativeUrl.startsWith('http')) return relativeUrl; const ossUrl = this.data.ossImageUrl; if (!ossUrl) return relativeUrl; // 确保拼接时只有一个斜杠 const base = ossUrl.replace(/\/+$/, ''); const rel = relativeUrl.replace(/^\/+/, ''); return base + '/' + rel; }, getFileExtension(filePath) { const lastDot = filePath.lastIndexOf('.'); if (lastDot === -1) return '.jpg'; const ext = filePath.substring(lastDot).toLowerCase(); return ['.jpg','.jpeg','.png','.gif','.bmp','.webp'].includes(ext) ? ext : '.jpg'; }, async getCOSZhengshu() { const res = await request({ url: '/dingdan/dsscpz', method: 'POST', data: { dingdan_id: this.data.xuanzhongChufa.dingdan_id || '', yongtu: 'chufa' } }); if (res.statusCode === 200 && res.data.code === 0 && res.data.data) return res.data.data; throw new Error(res?.data?.msg || '获取上传凭证失败'); }, initCOSClient(tokenData) { const COS = require('../../../../utils/cos-wx-sdk-v5.min.js'); const credentials = tokenData.credentials || tokenData; const bucket = tokenData.bucket || 'julebu-1361527063'; const region = tokenData.region || 'ap-shanghai'; const cos = new COS({ SimpleUploadMethod: 'putObject', getAuthorization: (options, callback) => { callback({ TmpSecretId: credentials.tmpSecretId, TmpSecretKey: credentials.tmpSecretKey, SecurityToken: credentials.sessionToken || '', StartTime: tokenData.startTime || Math.floor(Date.now() / 1000), ExpiredTime: tokenData.expiredTime || (Math.floor(Date.now() / 1000) + 7200) }); } }); return { cos, bucket, region }; }, shangchuanDanZhangTupian(filePath, cosKey, cosClient, bucket, region) { return new Promise(resolve => { const timeoutId = setTimeout(() => resolve({ status: 'optimistic_success', key: cosKey }), 2000); cosClient.uploadFile({ Bucket: bucket, Region: region, Key: cosKey, FilePath: filePath, onProgress: (info) => { if (Math.round(info.percent * 100) === 100) { clearTimeout(timeoutId); resolve({ status: 'optimistic_success', key: cosKey }); } } }); }); }, async piliangShangchuanShensuTupian() { const total = this.data.shensuTupian.length; if (total === 0) return []; this.setData({ shangchuanZongshu: total, shangchuanJindu: 0, jinduWidth: '0%', isShangchuanzhong: true }); let yonghuid = ''; const uid = wx.getStorageSync('uid'); if (uid) yonghuid = String(uid).padStart(7, '0'); else if (app.globalData.userInfo?.yonghuid) yonghuid = String(app.globalData.userInfo.yonghuid).padStart(7, '0'); if (!yonghuid) { wx.showToast({ title: '请先登录', icon: 'none' }); this.setData({ isShangchuanzhong: false }); return []; } const preGeneratedUrls = []; for (let i = 0; i < total; i++) { const timestamp = Date.now() + i, random = Math.floor(Math.random() * 10000); preGeneratedUrls.push(`a_long/chfajltp/dssstp/${yonghuid}_${timestamp}_${random}${this.getFileExtension(this.data.shensuTupian[i])}`); } let cosClient, bucket, region; try { const tokenData = await this.getCOSZhengshu(); const c = this.initCOSClient(tokenData); cosClient = c.cos; bucket = c.bucket; region = c.region; } catch (e) { wx.showToast({ title: '上传初始化失败', icon: 'none' }); this.setData({ isShangchuanzhong: false }); return []; } for (let i = 0; i < total; i++) { await this.shangchuanDanZhangTupian(this.data.shensuTupian[i], preGeneratedUrls[i], cosClient, bucket, region); const done = i + 1; this.setData({ shangchuanJindu: done, jinduWidth: `${((done / total) * 100).toFixed(0)}%` }); } this.setData({ isShangchuanzhong: false }); return preGeneratedUrls; }, async submitShensu() { if (!this.data.shensuLiyou.trim()) { wx.showToast({ title: '请输入申诉理由', icon: 'none' }); return; } if (this.data.shensuTupian.length === 0) { wx.showModal({ title: '提示', content: '未上传任何图片,确定要提交申诉吗?', success: async (res) => { if (res.confirm) await this.tijiaoShensuData([]); } }); return; } wx.showToast({ title: '开始上传图片...', icon: 'none' }); try { const urls = await this.piliangShangchuanShensuTupian(); if (!urls || urls.length === 0) throw new Error('图片上传失败'); await this.tijiaoShensuData(urls); } catch (e) { wx.showToast({ title: e.message || '提交失败', icon: 'none' }); } }, async tijiaoShensuData(tupianUrls) { wx.showToast({ title: '提交申诉中...', icon: 'none' }); try { const res = await request({ url: '/yonghu/dscfss', method: 'POST', data: { chufa_id: this.data.xuanzhongChufa.id, shensu_liyou: this.data.shensuLiyou, shensu_tupian_urls: tupianUrls } }); if (res.statusCode === 200 && res.data.code === 0) { const newList = this.data.chufaList.map(item => { if (item.id === this.data.xuanzhongChufa.id) { return { ...item, sqzhuangtai: 3, ssliyou: this.data.shensuLiyou, display_status: '申诉中', status_class: 'zhuangtai-shensuzhong', full_shensu_tupian: tupianUrls.map(url => this.getFullImageUrl(url)) }; } return item; }); this.setData({ chufaList: newList, showShensuModal: false, showXiangqing: false }); wx.showToast({ title: '申诉提交成功,请等待处理', icon: 'success' }); } else throw new Error(res.data?.msg || '提交申诉失败'); } catch (e) { wx.showToast({ title: e.message || '提交失败', icon: 'none' }); } } } });