| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /**
- * 种子测试用户数据脚本
- *
- * 1. 清理现有非总监用户
- * 2. 确保 Store/District 数据存在
- * 3. 创建 3 个已分配测试用户(使用 Pointer 关联)
- *
- * 用法: cd backend && npx tsx scripts/seed-test-users.ts
- */
- import 'dotenv/config';
- import Parse from '../src/db/parse-client.js';
- async function main(): Promise<void> {
- console.log('=== 种子测试用户数据 ===\n');
- console.log(`Server: ${Parse.serverURL}`);
- console.log(`App ID: ${Parse.applicationId}\n`);
- // 测试连接
- try {
- await new Parse.Query('_User').limit(1).find({ useMasterKey: true });
- console.log('✅ Parse 连接正常\n');
- } catch (err: any) {
- console.error('❌ Parse 连接失败:', err.message);
- process.exit(1);
- }
- // ── 1. 查看当前数据 ──
- console.log('--- 当前数据 ---');
- const existingUsers = await new Parse.Query('_User').find({ useMasterKey: true }) as any[];
- console.log(`_User: ${existingUsers.length} 个用户`);
- for (const u of existingUsers) {
- console.log(` - ${u.get('name')} (${u.get('phone')}) role=${u.get('role')} storeId=${u.get('storeId') || '无'} districtId=${u.get('districtId') || '无'}`);
- }
- const existingStores = await new Parse.Query('Store').find({ useMasterKey: true }) as any[];
- console.log(`\nStore: ${existingStores.length} 个门店`);
- for (const s of existingStores) {
- console.log(` - ${s.id}: ${s.get('name')}`);
- }
- const existingDistricts = await new Parse.Query('District').find({ useMasterKey: true }) as any[];
- console.log(`\nDistrict: ${existingDistricts.length} 个区域`);
- for (const d of existingDistricts) {
- console.log(` - ${d.id}: ${d.get('name')}`);
- }
- // ── 2. 清理非总监用户 ──
- console.log('\n--- 清理非总监用户 ---');
- for (const u of existingUsers) {
- const role = u.get('role');
- if (role !== 'director') {
- console.log(` 删除: ${u.get('name')} (${u.get('phone')})`);
- await u.destroy({ useMasterKey: true });
- }
- }
- // ── 3. 确保 _User 表有 store/district Pointer 列 ──
- console.log('\n--- 检查 _User Schema ---');
- const userSchema = new Parse.Schema('_User');
- try { await userSchema.get({ useMasterKey: true }); } catch { /* 首次 */ }
- try { await userSchema.addField('store', 'Pointer', { targetClass: 'Store' }); console.log(' ✅ store Pointer 列已添加'); } catch { console.log(' ✅ store 列已存在'); }
- try { await userSchema.addField('district', 'Pointer', { targetClass: 'District' }); console.log(' ✅ district Pointer 列已添加'); } catch { console.log(' ✅ district 列已存在'); }
- await userSchema.update({ useMasterKey: true });
- // ── 4. 确保 Store 和 District 存在 ──
- let storeId: string;
- let storeName: string;
- let districtId: string;
- let districtName: string;
- if (existingDistricts.length > 0) {
- districtId = existingDistricts[0].id;
- districtName = existingDistricts[0].get('name');
- console.log(`\n✅ 使用已有区域: ${districtName} (${districtId})`);
- } else {
- const d = new Parse.Object('District');
- d.set('name', '华东区');
- d.set('sortOrder', 1);
- await d.save(null, { useMasterKey: true });
- districtId = d.id;
- districtName = '华东区';
- console.log(`\n✅ 创建区域: ${districtName} (${districtId})`);
- }
- if (existingStores.length > 0) {
- storeId = existingStores[0].id;
- storeName = existingStores[0].get('name');
- console.log(`✅ 使用已有门店: ${storeName} (${storeId})`);
- // 确保门店关联了区域
- const store = existingStores[0];
- if (!store.get('district')) {
- store.set('district', Parse.Object.createWithoutData('District', districtId));
- await store.save(null, { useMasterKey: true });
- console.log(` 已更新门店区域关联`);
- }
- } else {
- const s = new Parse.Object('Store');
- s.set('name', '上海旗舰店');
- s.set('district', Parse.Object.createWithoutData('District', districtId));
- await s.save(null, { useMasterKey: true });
- storeId = s.id;
- storeName = '上海旗舰店';
- console.log(`✅ 创建门店: ${storeName} (${storeId})`);
- }
- // ── 5. 创建 3 个测试用户(使用 Pointer) ──
- console.log('\n--- 创建测试用户 ---');
- // 先获取完整的 Store/District 对象(用于构建有效 Pointer)
- const storeObj = await new Parse.Query('Store').get(storeId, { useMasterKey: true });
- const districtObj = await new Parse.Query('District').get(districtId, { useMasterKey: true });
- const testUsers = [
- {
- name: '张总监',
- phone: '13800000001',
- password: '123456',
- role: 'director',
- store: null as any,
- district: null as any,
- },
- {
- name: '王督导',
- phone: '13800000002',
- password: '123456',
- role: 'regional_supervisor',
- store: null as any,
- district: districtObj,
- },
- {
- name: '李店长',
- phone: '13800000003',
- password: '123456',
- role: 'store_manager',
- store: storeObj,
- district: districtObj,
- },
- ];
- for (const tu of testUsers) {
- const username = `shequn:${tu.phone}`;
- // 先删除已存在的同名用户(确保干净重建)
- const existingQ = new Parse.Query('_User');
- existingQ.equalTo('username', username);
- const existingUser = await existingQ.first({ useMasterKey: true });
- if (existingUser) {
- await existingUser.destroy({ useMasterKey: true });
- console.log(` 删除旧用户: ${tu.phone}`);
- }
- try {
- await Parse.User.signUp(username, tu.password, {
- phone: tu.phone,
- appSource: 'shequn',
- name: tu.name,
- role: tu.role,
- department: tu.role === 'director' ? '总部' : '运营部',
- position: tu.role === 'director' ? 'director' : 'general_staff',
- });
- } catch (err: any) {
- console.error(` ❌ 创建用户 ${tu.phone} 失败:`, err.message);
- throw err;
- }
- // signUp 后重新查询并设置 Pointer 字段
- const q = new Parse.Query('_User');
- q.equalTo('username', username);
- const user = await q.first({ useMasterKey: true });
- if (!user) {
- console.error(` ❌ 找不到用户 ${tu.phone}`);
- continue;
- }
- if (tu.store) user.set('store', tu.store);
- if (tu.district) user.set('district', tu.district);
- await user.save(null, { useMasterKey: true });
- console.log(` ✅ ${tu.name} (${tu.phone}) role=${tu.role} store=${tu.store ? storeName : '—'} district=${tu.district ? districtName : '—'}`);
- }
- // ── 6. 验证 ──
- console.log('\n--- 验证 ---');
- const q = new Parse.Query('_User');
- q.include('store');
- q.include('district');
- q.ascending('phone');
- const finalUsers = await q.find({ useMasterKey: true }) as any[];
- for (const u of finalUsers) {
- const store = u.get('store');
- const district = u.get('district');
- console.log(` ${u.get('name')} | ${u.get('phone')} | ${u.get('role')} | store=${store?.get?.('name') || '—'} | district=${district?.get?.('name') || '—'}`);
- }
- console.log('\n✅ 种子数据完成!');
- console.log('一键测试账号:');
- console.log(' 总监: 13800000001 / 123456');
- console.log(' 区域督导: 13800000002 / 123456');
- console.log(' 店长: 13800000003 / 123456');
- }
- main().catch((err) => {
- console.error('失败:', err.message, err.stack);
- process.exit(1);
- });
|