/** * 导出 QiWe 项目相关的所有表 Schema(供文档编写用) * * 用法: cd backend && npx tsx scripts/dump-qiwe-schema.ts */ import 'dotenv/config'; import Parse from '../src/db/parse-client.js'; async function showTable(className: string): Promise { const q = new Parse.Query(className); q.limit(1); q.descending('updatedAt'); let rows: Parse.Object[] = []; try { rows = await q.find({ useMasterKey: true }); } catch { /* skip */ } let schema: Parse.Schema; try { schema = await new Parse.Schema(className).get({ useMasterKey: true }); } catch (err: any) { console.log(`\n📦 ${className} — 表不存在 (${err.message})`); return; } const fields = schema.fields as Record; const entries = Object.entries(fields) .filter(([n]) => !n.startsWith('_') && n !== 'ACL') .sort(([a], [b]) => a.localeCompare(b)); const hasData = rows.length > 0; console.log(`\n📦 ${className}${hasData ? ' (有数据)' : ' (空)'}`); console.log('-'.repeat(65)); for (const [name, def] of entries) { const typeStr = def.type === 'Pointer' ? `Pointer → ${def.targetClass || '?'}` : def.type; console.log(` ${name.padEnd(30)} ${typeStr}`); } if (hasData) { console.log('\n 示例字段值:'); const r = rows[0] as any; for (const [name] of entries.slice(0, 12)) { const v = r.get(name); if (v === undefined || v === null || v === '') continue; let s: string; if (typeof v === 'object') { if (v.className) { s = `Pointer(${v.className}:${v.id?.slice(0, 8)}...)`; } else { s = JSON.stringify(v).substring(0, 100); } } else { s = String(v).substring(0, 100); } console.log(` ${name.padEnd(28)} ${s}`); } } } async function main(): Promise { console.log('=== QiWe 项目数据库 Schema 完整导出 ==='); console.log(`Server: ${Parse.serverURL}`); console.log(`App ID: ${Parse.applicationId}\n`); // 测试连接 try { const n = await new Parse.Query('_User').count({ useMasterKey: true }); console.log(`✅ Parse 连接正常 (_User: ${n} 条)\n`); } catch (err: any) { console.error('❌ Parse 连接失败:', err.message); process.exit(1); } // QiWe 核心表 const qiweTables = [ 'GroupChat', 'GroupMember', 'Message', 'MessageSyncCursor', 'WebhookLog', 'Contact', ]; // 风控相关表 const riskTables = [ 'RiskEvent', 'RiskKeyword', 'AppNotification', 'ResponsibilityAssignment', ]; // 组织结构表 const orgTables = [ 'Store', 'District', 'Community', ]; // 其他 const otherTables = [ '_User', 'QiWeAccount', ]; console.log('══════ QiWe 核心表 ══════'); for (const t of qiweTables) await showTable(t); console.log('\n══════ 风控系统表 ══════'); for (const t of riskTables) await showTable(t); console.log('\n══════ 组织结构表 ══════'); for (const t of orgTables) await showTable(t); console.log('\n══════ 其他 ══════'); for (const t of otherTables) await showTable(t); console.log('\n\n✅ 导出完成!\n'); } main().catch((err) => { console.error('失败:', err.message); process.exit(1); });