// 已读取AGENTS.md import * as fs from 'fs'; import * as path from 'path'; /** * 第九十五批:平台派单(发需求单)闭环闸门。 * 背景:抢单池只查 status='待接单',但下单流程全是「指定大神 → 支付 → 履约中」, * 没有任何流程产出待接单订单,导致雷达/接单大厅永远是空池。 */ describe('第九十五批平台派单闭环', () => { const root = path.resolve(__dirname, '../../'); const read = (rel: string) => fs.readFileSync(path.join(root, rel), 'utf-8'); const repo = read('server/src/db/repository.ts'); const indexCode = read('server/src/index.ts'); const createPage = read('pwuniapp/pages/order/create.vue'); it('平台派单订单 expertId=0,余额支付后直接进入待接单池', () => { expect(repo).toContain('const isMarketplace = !Number(data.expertId)'); expect(repo).toContain("const expertId = isMarketplace ? 0 : Number(data.expertId)"); expect(repo).toContain("isMarketplace ? '待接单' : '履约中'"); }); it('平台派单预算由买家出价但受服务端上下限约束', () => { expect(repo).toContain('hourlyRate = Math.min(2000, Math.max(1, Number(data.hourlyRate) || 35))'); }); it('微信支付确认后:无大神订单转入待接单而不是履约中', () => { expect(indexCode).toContain("const paidStatus = isMarketplace ? '待接单' : '履约中'"); expect(indexCode).toContain('已进入派单池,等待附近大神接单'); expect(indexCode).toContain('30 分钟内无人接单将自动全额退款'); }); it('抢单后由认领大神写入 expert_id 并进入履约中', () => { expect(repo).toContain("SET status = '履约中', expert_id = ?, companion_name = ?"); expect(repo).toContain("AND status = '待接单'"); }); it('下单页提供「平台派单」模式并提交 expertId=0', () => { expect(createPage).toContain("const orderMode = ref('EXPERT')"); expect(createPage).toContain('platformCategories'); expect(createPage).toContain('expertId: isPlatform ? 0 : expert.value.id'); expect(createPage).toContain('平台派单需求'); }); it('平台派单时不会沿用指定大神页的默认地点', () => { expect(createPage).toContain('const switchMode = (mode) =>'); expect(createPage).toContain("meetVenue.value = '';"); }); it('订单 INSERT 的列数必须与占位符数量一致(含 paid_at/created_at 两个表达式值)', () => { const start = repo.indexOf('INSERT INTO orders'); const end = repo.indexOf('`, [', start); const seg = repo.slice(start, end); const columns = seg .slice(seg.indexOf('(') + 1, seg.indexOf(')')) .split(',') .filter((s) => s.trim()).length; const values = seg.slice(seg.indexOf('VALUES')); const placeholders = (values.replace(/\$\{[^}]*\}/g, '').match(/\?/g) || []).length; expect(columns).toBe(24); expect(placeholders + 2).toBe(columns); }); it('禁止自己接自己发布的订单,派单池也不展示自己的单', () => { expect(repo).toContain('不能接自己发布的订单'); expect(repo).toContain('const actorUserId = Number(comp && comp.user_id) || expertId;'); expect(repo).toContain('AND buyer_id <> ?'); expect(indexCode).toContain('excludeBuyerId'); }); });