import fs from 'node:fs'; import path from 'node:path'; const baseline = process.argv.includes('--baseline'); const expectedResources = [ ['gas', 'gas_basic', 'list'], ['gas', 'gas_account', 'list'], ['delivery', 'delivery_basic', 'list'], ['delivery', 'delivery_account', 'list'], ['delivery', 'delivery_task', 'list'], ['delivery', 'delivery_track', 'list'], ['delivery', 'delivery_track_point', 'list'], ['staff', 'staff_account', 'list'], ['staff', 'staff_credential', 'list'], ['user', 'user_account', 'list'], ['user', 'user_address', 'list'], ['user', 'user_service_relation', 'list'], ['device', 'dev_smart_cylinder_valve', 'list'], ['device', 'dev_device_binding', 'list'], ['device', 'dev_telemetry', 'list'], ['device', 'saf_rule', 'list'], ['device', 'saf_event', 'list'], ['device', 'saf_event_disposal', 'list'], ['device', 'saf_inspection', 'list'], ['commerce', 'ec_category', 'list'], ['commerce', 'ec_product', 'list'], ['commerce', 'ec_product_attribute', 'list'], ['commerce', 'ec_product_image', 'list'], ['commerce', 'ec_cart', 'list'], ['commerce', 'ec_order', 'list'], ['commerce', 'ec_review', 'list'], ['finance', 'fin_payment', 'list'], ['finance', 'fin_settlement', 'list'], ['finance', 'fin_reconciliation', 'list'], ['content', 'cnt_content', 'list'], ['notification', 'ntf_template', 'list'], ['customer_service', 'cs_ticket', 'list'], ['platform', 'platfrom_account', 'list'], ['platform', 'platform_role', 'list'], ['platform', 'platform_menu', 'tree'], ['wallet', 'wallet', 'list'], ['wallet', 'wallet_ledger', 'list'], ['wallet', 'wallet_recharge', 'list'], ['wallet', 'wallet_withdrawal', 'list'], ['report', 'report', 'list'], ['report', 'report_item', 'list'], ['report', 'report_metric_snapshot', 'list'], ['audit', 'aud_operation_log', 'list'], ['audit', 'aud_export_log', 'list'], ['audit', 'aud_approval', 'list'], ]; function fileIncludes(file, value) { return fs.existsSync(file) && fs.readFileSync(file, 'utf8').includes(value); } function checkResourceLayers() { const missing = []; for (const [domain, name, pageKind] of expectedResources) { if (!fileIncludes('src/api/resources.ts', name)) missing.push(`${domain}/${name}: missing api`); if (!fileIncludes(path.join('src/router/routes/modules', `${domain}.ts`), name)) missing.push(`${domain}/${name}: missing route`); const page = pageKind === 'tree' ? 'TreePage.vue' : 'ListPage.vue'; if (!fs.existsSync(path.join('src/views', domain, name, page))) missing.push(`${domain}/${name}: missing view`); } return missing; } function walk(dir, acc = []) { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory() && entry.name !== 'node_modules') { walk(full, acc); } else if (/\.(ts|vue)$/.test(entry.name)) { acc.push(full); } } return acc; } const srcFiles = walk('src'); const badPlaceholder = []; const zhLocales = srcFiles.filter((f) => f.includes(`${path.sep}locale${path.sep}zh-CN.ts`)); for (const file of srcFiles) { const text = fs.readFileSync(file, 'utf8'); if (text.includes("'???'") || /'(\?\?[^']*)'/.test(text)) { badPlaceholder.push(file); } } let zhOk = 0; for (const file of zhLocales) { if (/[\u4e00-\u9fff]/.test(fs.readFileSync(file, 'utf8'))) zhOk += 1; } let mockInDist = false; if (fs.existsSync('dist/assets')) { for (const name of fs.readdirSync('dist/assets')) { if (!name.endsWith('.js')) continue; const chunk = fs.readFileSync(path.join('dist/assets', name), 'utf8'); if (chunk.includes('mockjs') || chunk.includes('Mock.mock')) { mockInDist = true; break; } } } console.log(JSON.stringify({ badPlaceholder: badPlaceholder.length, zhLocales: `${zhOk}/${zhLocales.length}`, mockInDist, hasGit: fs.existsSync('.env.development') && fs.readFileSync('.env.development', 'utf8').includes('VITE_API_BASE_URL=http'), settingsHttp: fs.readFileSync('src/locale/zh-CN/settings.ts', 'utf8').includes('http.logout.title'), rootMenu: fs.readFileSync('src/locale/zh-CN.ts', 'utf8').includes('仪表盘'), }, null, 2)); const missingLayers = checkResourceLayers(); for (const missing of missingLayers) console.log(missing); if (missingLayers.length > 0 && !baseline) { process.exitCode = 1; }