/** * 举报页 U26(重构:用 safetyService.submitReport + ui-nav-bar + ui-textarea) * * 流程:原因选择 → 补充说明(高风险必填)→ 证据截图(选填)→ 提交 * * 不变量(AGENTS.md): * - 第 8 条:敏感数据默认拒绝——本页只接收 reason + 证据截图,不接受身份证/手机号等敏感字段。 * - 第 4 条:Block 优先级最高——举报不会自动 Block,是否拉黑由用户主动操作;举报后由运营人工处置。 * - 第 6 条:单向意向不泄露——举报内容仅提交给运营,不向对方透露。 * 幂等:safetyService.submitReport 内部以 targetUserId+reportType+秒级时间生成 Idempotency-Key。 */ const { appStore } = require('../../stores'); const { safetyService } = require('../../services'); // 举报原因选项(reportType 对齐后端枚举) const REPORT_REASONS = [ { value: 'fake_profile', label: '虚假资料' }, { value: 'fake_marital_status', label: '婚姻状态疑似虚假' }, { value: 'harassment', label: '骚扰' }, { value: 'pornography', label: '色情低俗' }, { value: 'advertising', label: '广告营销' }, { value: 'fraud', label: '诈骗' }, { value: 'money_inducement', label: '金钱诱导' }, { value: 'impersonation', label: '冒充他人' }, { value: 'other', label: '其他' }, ]; // 高风险举报需必填说明 const HIGH_RISK_REASONS = new Set(['fraud', 'money_inducement', 'impersonation', 'fake_marital_status']); const MAX_EVIDENCE = 9; Page({ data: { targetUserId: '', targetName: '', reportType: '', description: '', evidenceFiles: [], submitting: false, submitted: false, reportReasons: REPORT_REASONS, highRiskReason: false, descError: '', statusBarHeight: 20, navBarHeight: 44, }, onLoad(options) { try { const info = (wx.getWindowInfo && wx.getWindowInfo()) || wx.getSystemInfoSync(); this.setData({ statusBarHeight: info.statusBarHeight || 20, navBarHeight: info.platform === 'android' ? 48 : 44, }); } catch (e) { /* 使用默认值 */ } if (options.userId) this.setData({ targetUserId: decodeURIComponent(options.userId) }); if (options.name) this.setData({ targetName: decodeURIComponent(options.name) }); }, onReasonChange(e) { const value = e.currentTarget.dataset.value; const isHighRisk = HIGH_RISK_REASONS.has(value); this.setData({ reportType: value, highRiskReason: isHighRisk, descError: '', }); }, onDescInput(e) { const value = e.detail.value; this.setData({ description: value, descError: '' }); }, // ============ 证据截图 ============ chooseImage() { const remain = MAX_EVIDENCE - this.data.evidenceFiles.length; if (remain <= 0) { appStore.toast('最多上传 9 张截图'); return; } wx.chooseMedia({ count: remain, mediaType: ['image'], sourceType: ['album', 'camera'], success: (res) => { const files = res.tempFiles.map((f) => f.tempFilePath); this.setData({ evidenceFiles: [...this.data.evidenceFiles, ...files] }); }, }); }, previewImage(e) { wx.previewImage({ current: e.currentTarget.dataset.url, urls: this.data.evidenceFiles, }); }, removeImage(e) { const idx = e.currentTarget.dataset.index; const files = this.data.evidenceFiles; files.splice(idx, 1); this.setData({ evidenceFiles: files }); }, // ============ 提交 ============ async submitReport() { const { targetUserId, reportType, description, highRiskReason } = this.data; if (!targetUserId) { appStore.toast('缺少举报对象'); return; } if (!reportType) { appStore.toast('请选择举报原因'); return; } const desc = (description || '').trim(); if (highRiskReason && !desc) { this.setData({ descError: '该类举报需补充说明(必填)' }); return; } this.setData({ submitting: true }); try { await safetyService.submitReport({ targetUserId, reportType, description: desc, // 证据上传至 OSS 后回填 fileId;当前阶段先以本地路径占位,由后端证据服务接入后补全 evidenceFileIds: [], }); this.setData({ submitted: true, submitting: false }); appStore.toastSuccess('举报已提交'); } catch (err) { appStore.toastError(err); this.setData({ submitting: false }); } }, goBack() { if (this.data.submitted) { wx.navigateBack(); } else { wx.navigateBack(); } }, onBack() { wx.navigateBack(); }, });