From 5279816452a12df2a6ce6e966f0f4528a75cd934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=AD=A3=E8=88=AA?= <1915581435@qq.com> Date: Tue, 21 Apr 2026 23:31:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=89=B9=E9=87=8F=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E5=AF=BC=E5=87=BACSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增导出CSV文件功能,包含文本、判定结果、置信度、风险关键词 - 新增复制CSV内容到剪贴板功能 - CSV字段:文本、判定结果、置信度、垃圾概率、正常概率、风险关键词 Co-Authored-By: Claude Opus 4.7 --- miniprogram/pages/batch/index.js | 78 ++++++++++++++++++++++++++++++ miniprogram/pages/batch/index.wxml | 4 ++ 2 files changed, 82 insertions(+) diff --git a/miniprogram/pages/batch/index.js b/miniprogram/pages/batch/index.js index 79bba95..3c4d090 100644 --- a/miniprogram/pages/batch/index.js +++ b/miniprogram/pages/batch/index.js @@ -79,5 +79,83 @@ Page({ showCancel: false, confirmText: '关闭' }) + }, + + generateCSV() { + const items = this.data.items + if (!items.length) return '' + + const headers = ['文本', '判定结果', '置信度', '垃圾概率', '正常概率', '风险关键词'] + const rows = items.map((item) => { + const prediction = item.prediction === 'spam' ? '垃圾信息' : '正常信息' + const confidence = item.confidence_text || '0%' + const spamProb = this.formatPercent(item.spam_probability, 4) + const hamProb = this.formatPercent(item.ham_probability, 4) + const tokens = (item.reason_tokens || []).map((t) => t.token || t).join('; ') + // CSV 转义:文本中的逗号和换行需要处理 + const text = (item.text || '').replace(/"/g, '""') + const tokensEscaped = tokens.replace(/"/g, '""') + return `"${text}","${prediction}","${confidence}","${spamProb}","${hamProb}","${tokensEscaped}"` + }) + + return [headers.join(','), ...rows].join('\n') + }, + + exportCSV() { + const items = this.data.items + if (!items.length) { + wx.showToast({ title: '暂无识别结果可导出', icon: 'none' }) + return + } + + const csvContent = this.generateCSV() + const timestamp = new Date().toISOString().slice(0, 19).replace(/[T:]/g, '-') + const filename = `batch_detect_${timestamp}.csv` + + // 写入临时文件 + const fs = wx.getFileSystemManager() + const tempPath = `${wx.env.USER_DATA_PATH}/${filename}` + + try { + fs.writeFileSync(tempPath, csvContent, 'utf8') + wx.showModal({ + title: '导出成功', + content: `CSV文件已生成,是否打开查看?\n文件名:${filename}`, + confirmText: '打开', + cancelText: '关闭', + success: (res) => { + if (res.confirm) { + wx.openDocument({ + filePath: tempPath, + fileType: 'csv', + showMenu: true, + fail: (err) => { + console.error('打开文件失败', err) + wx.showToast({ title: '打开失败,请检查文件管理器', icon: 'none' }) + } + }) + } + } + }) + } catch (err) { + console.error('写入文件失败', err) + wx.showToast({ title: '导出失败', icon: 'none' }) + } + }, + + copyCSVToClipboard() { + const items = this.data.items + if (!items.length) { + wx.showToast({ title: '暂无识别结果可复制', icon: 'none' }) + return + } + + const csvContent = this.generateCSV() + wx.setClipboardData({ + data: csvContent, + success: () => { + wx.showToast({ title: 'CSV内容已复制到剪贴板', icon: 'success' }) + } + }) } }) diff --git a/miniprogram/pages/batch/index.wxml b/miniprogram/pages/batch/index.wxml index 9475202..ea6d8e0 100644 --- a/miniprogram/pages/batch/index.wxml +++ b/miniprogram/pages/batch/index.wxml @@ -56,6 +56,10 @@ 明细结果 + + + + {{item.text}}