'use strict'; const assert = require('assert/strict'); const fs = require('fs'); const os = require('os'); const path = require('path'); const { readSheet } = require('read-excel-file/node'); const writeXlsxFile = require('write-excel-file/node'); async function assertWorkbook(filePath, expectedSheet, expectedRows) { assert(fs.existsSync(filePath), `未生成 Excel 文件: ${filePath}`); const rows = await readSheet(filePath, expectedSheet); assert.equal(rows.length, expectedRows + 1); assert(rows[0].length > 0, `工作表 ${expectedSheet} 缺少表头`); } async function main() { const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'qiwei-excel-smoke-')); process.env.QIWEI_OUTPUTS_DIR = path.join(tempRoot, 'outputs'); try { const inputFile = path.join(tempRoot, 'customers.xlsx'); const inputRows = [ ['手机号', '姓名', '验证消息', '群名称'], ['13800138000', '客户甲', '您好', '体验群'], ['13800138000', '重复客户', '', ''], ['not-a-phone', '无效客户', '', ''], ].map(row => row.map(value => ({ value }))); await writeXlsxFile(inputRows, { sheet: 'customers' }).toFile(inputFile); const { normalizeCustomers } = require('../mcp/src/tools/qiwei-customer-ops-run'); const imported = await normalizeCustomers({ filePath: inputFile }); assert.equal(imported.customers.length, 1); assert.equal(imported.customers[0].phone, '13800138000'); assert.equal(imported.customers[0].name, '客户甲'); assert.equal(imported.duplicateRemoved, 1); assert.equal(imported.invalidRemoved, 1); const portraitDir = path.join(process.env.QIWEI_OUTPUTS_DIR, 'portraits'); const playbookDir = path.join(process.env.QIWEI_OUTPUTS_DIR, 'broker-playbooks'); fs.mkdirSync(portraitDir, { recursive: true }); fs.mkdirSync(playbookDir, { recursive: true }); fs.writeFileSync(path.join(portraitDir, 'customer-1.json'), JSON.stringify({ externalUserId: 'customer-1', portrait: { intent: '咨询', confidence: 0.9 }, updatedAt: new Date().toISOString(), }), 'utf8'); fs.writeFileSync(path.join(playbookDir, 'broker-1.json'), JSON.stringify({ brokerUserId: 'broker-1', playbook: { opening: '先确认需求', followUp: '次日回访' }, updatedAt: new Date().toISOString(), }), 'utf8'); const { qiweiExportCustomerPortraits } = require('../mcp/src/tools/qiwei-portrait-tags-run'); const { qiweiExportBrokerPlaybooks } = require('../mcp/src/tools/qiwei-broker-playbook-run'); const portraitResult = await qiweiExportCustomerPortraits({ externalUserIds: ['customer-1'] }); const playbookResult = await qiweiExportBrokerPlaybooks({ brokerUserIds: ['broker-1'] }); assert.equal(portraitResult.status, 'ok'); assert.equal(playbookResult.status, 'ok'); await assertWorkbook(portraitResult.files[0], 'portraits', 1); await assertWorkbook(playbookResult.files[0], 'playbooks', 1); process.stdout.write(`${JSON.stringify({ status: 'ok', importedCustomers: imported.customers.length, duplicateRemoved: imported.duplicateRemoved, invalidRemoved: imported.invalidRemoved, exportsVerified: 2, }, null, 2)}\n`); } finally { fs.rmSync(tempRoot, { recursive: true, force: true }); } } main().catch(error => { process.stderr.write(`${error.stack || error.message}\n`); process.exit(1); });