| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- #!/usr/bin/env node
- 'use strict';
- // 导出店铺运营数据为 JSON(用于 SQLite ↔ PostgreSQL 搬迁)
- // 用法:
- // node scripts/db-export.js # 导出到 ops-export.json(不含原件)
- // node scripts/db-export.js out.json --with-files # 连原件一起导出(base64)
- //
- // 说明:不带 --with-files 时只导出元数据与数据行;导入端要求每个上传都有原件,
- // 因此完整搬迁务必加 --with-files。
- const fs = require('fs');
- const path = require('path');
- const { createContext } = require('../server/context.js');
- const { createOpsStore } = require('../ops-store.js');
- (async () => {
- const args = process.argv.slice(2);
- const withFiles = args.includes('--with-files');
- const outPath = path.resolve(args.find((a) => !a.startsWith('--')) || 'ops-export.json');
- const ctx = createContext();
- const store = createOpsStore(ctx.config);
- const health = await store.health();
- if (!health.ok) {
- console.error(`读取失败:${health.reason || 'storage-unreachable'} ${health.detail || ''}`);
- process.exit(1);
- }
- const uploads = await store.listUploads();
- if (withFiles) {
- for (const upload of uploads) {
- const record = await store.getContent(upload.id);
- upload.contentBase64 = record ? record.content.toString('base64') : '';
- }
- }
- const rows = await store.queryRows({});
- const platformRows = await store.queryPlatformRows({});
- const summary = await store.summary();
- // 经营报告历史(完整快照),迁移后仍可回看/下载
- const reports = [];
- for (const item of await store.listReports()) {
- const full = await store.getReport(item.id);
- if (full) reports.push({ ...item, report: full });
- }
- const payload = {
- version: 1,
- exportedAt: new Date().toISOString(),
- driver: store.kind,
- withFiles,
- uploads,
- shops: summary.shops,
- platformRows,
- reports,
- rows: rows.map((r) => ({
- date: r.date,
- shopKey: r.shopKey,
- uploadId: r.uploadId,
- shopId: r.shopId,
- shopName: r.shopName,
- school: r.school,
- status: r.status,
- order_cnt: r.order_cnt,
- revenue: r.revenue,
- exposure: r.exposure,
- click_rate: r.click_rate,
- raw: r.raw,
- quality: r.quality,
- })),
- };
- fs.writeFileSync(outPath, JSON.stringify(payload, null, 2));
- console.log(`已导出 ${uploads.length} 次上传、${rows.length} 行人工数据、${platformRows.length} 行平台明细、${reports.length} 份报告 → ${outPath}${withFiles ? '(含原件)' : '(不含原件)'}`);
- await store.close();
- })();
|