314 lines
7.7 KiB
JavaScript
314 lines
7.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
|
|
const root = new URL('..', import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, '$1');
|
|
const read = (path) => readFileSync(join(root, path), 'utf8');
|
|
|
|
const packageJson = JSON.parse(read('admin/package.json'));
|
|
assert.equal(packageJson.dependencies.vue.startsWith('^3.'), true);
|
|
assert.ok(packageJson.dependencies['element-plus']);
|
|
assert.ok(packageJson.dependencies['@lucide/vue']);
|
|
|
|
const envExample = read('admin/.env.example');
|
|
assert.match(envExample, /https:\/\/api\.txyundm\.cn\/admin-api/);
|
|
assert.doesNotMatch(envExample, /localhost|127\.0\.0\.1|http:\/\//);
|
|
|
|
const vite = read('admin/vite.config.ts');
|
|
assert.match(vite, /base: '\/admin\/'/);
|
|
assert.match(vite, /'\/admin-api'/);
|
|
|
|
const app = read('admin/src/App.vue');
|
|
for (const pattern of [
|
|
'CleaningTasksPanel',
|
|
'CleaningSettlementsPanel',
|
|
'CleaningStatisticsPanel',
|
|
'CleanersPanel',
|
|
'qipai.admin.token',
|
|
'loadTasks',
|
|
'loadSettlements',
|
|
'loadStatistics',
|
|
'loadCleaners',
|
|
'handleSyncTransfer',
|
|
'handleSyncTransferMany',
|
|
'handleCompleteMany',
|
|
'handleRejectMany',
|
|
'运营待处理',
|
|
'jumpToTaskStatus',
|
|
'jumpToSettlementStatus',
|
|
'draftSettlementTotal',
|
|
'settlementFilters.payoutState',
|
|
'待确认结算',
|
|
'待发放金额',
|
|
'CleaningFieldHandoffPanel',
|
|
'联调'
|
|
]) {
|
|
assert.match(app, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const api = read('admin/src/api.ts');
|
|
for (const route of [
|
|
'/cleaning/tasks?',
|
|
'/cleaning/statistics',
|
|
'storeId',
|
|
'cleanerUserId',
|
|
'/users?',
|
|
'/staff',
|
|
'/reset-sessions',
|
|
'/assign',
|
|
'/complete',
|
|
'/reject',
|
|
'/members',
|
|
'/cleaning/reclaim-timeouts',
|
|
'/cleaning/settlements?',
|
|
'/cleaning/settlements',
|
|
'payoutState',
|
|
'/wechat-transfer',
|
|
'/wechat-transfer/preflight',
|
|
'/wechat-transfer/sync',
|
|
'/payout-failure'
|
|
]) {
|
|
assert.match(api, new RegExp(route.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const tasks = read('admin/src/components/CleaningTasksPanel.vue');
|
|
for (const pattern of [
|
|
'指派',
|
|
'验收',
|
|
'驳回',
|
|
'回收',
|
|
'成员',
|
|
'保洁任务详情',
|
|
'操作流水',
|
|
'协作分账',
|
|
'listCleaningTaskEvents',
|
|
'listCleaningTaskMembers',
|
|
'loadingEvents',
|
|
'loadingMembers',
|
|
'批量验收',
|
|
'批量驳回',
|
|
'selectedSubmittedTasks',
|
|
'complete-many',
|
|
'reject-many',
|
|
'photo-grid',
|
|
'timeline-grid',
|
|
'el-image',
|
|
'协作者管理',
|
|
'photoUrls',
|
|
'el-select',
|
|
'cleanerLabel',
|
|
'filterDraft',
|
|
'门店 ID',
|
|
'筛选',
|
|
'导出',
|
|
'exportTasks',
|
|
'exportTaskDetail',
|
|
'exportTaskEvents',
|
|
'cleaning-tasks',
|
|
'cleaning-task-detail',
|
|
'cleaning-task-events',
|
|
'导出详情',
|
|
'downloadCsv',
|
|
'csvCell',
|
|
'photoUrls?.length'
|
|
]) {
|
|
assert.match(tasks, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const settlements = read('admin/src/components/CleaningSettlementsPanel.vue');
|
|
for (const pattern of [
|
|
'详情',
|
|
'生成',
|
|
'确认',
|
|
'转账',
|
|
'同步',
|
|
'批量同步',
|
|
'selectedSyncableSettlements',
|
|
'sync-transfer-many',
|
|
'失败',
|
|
'结算单详情',
|
|
'微信确认参数',
|
|
'payoutPackageInfo',
|
|
'getCleaningSettlementDetail',
|
|
'微信转账预检',
|
|
'preflightWechatTransfer',
|
|
'凭据引用',
|
|
'授权状态',
|
|
'通知URL',
|
|
'平台证书',
|
|
'保洁员OpenID',
|
|
'credentialRefMasked',
|
|
'platformCertificateCount',
|
|
'configuredText',
|
|
'导出预检',
|
|
'exportPreflight',
|
|
'cleaning-transfer-preflight',
|
|
'transferPreflightTitle',
|
|
'transferCanSubmit',
|
|
'preflightLoading',
|
|
'listCleaningSettlementCandidates',
|
|
'candidateDialog',
|
|
'useCandidateFilters',
|
|
'exportSettlements',
|
|
'exportCandidates',
|
|
'downloadCsv',
|
|
'MOCK',
|
|
'el-select',
|
|
'cleanerLabel',
|
|
'filterDraft',
|
|
'payoutStateOptions',
|
|
'转账状态',
|
|
'WAIT_USER_CONFIRM',
|
|
'门店 ID',
|
|
'筛选'
|
|
]) {
|
|
assert.match(settlements, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const statistics = read('admin/src/components/CleaningStatisticsPanel.vue');
|
|
for (const pattern of [
|
|
'今日',
|
|
'近7天',
|
|
'本月',
|
|
'任务状态',
|
|
'结算口径',
|
|
'每日趋势',
|
|
'trendWidth',
|
|
'paidSettlementCents',
|
|
'门店明细',
|
|
'成员分账',
|
|
'pendingSettlementCents',
|
|
'filterDraft.cleanerUserId',
|
|
'cleanerLabel',
|
|
'exportStatistics',
|
|
'cleaning-statistics',
|
|
'downloadCsv',
|
|
'csvCell',
|
|
'el-select'
|
|
]) {
|
|
assert.match(statistics, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const cleaners = read('admin/src/components/CleanersPanel.vue');
|
|
for (const pattern of [
|
|
'新增保洁员',
|
|
'门店 ID,逗号分隔',
|
|
'已绑微信',
|
|
'待补资料',
|
|
'profileComplete',
|
|
'exportCleaners',
|
|
'cleaning-cleaners',
|
|
'downloadCsv',
|
|
'csvCell',
|
|
'会话',
|
|
'status-toggle',
|
|
'reset-sessions'
|
|
]) {
|
|
assert.match(cleaners, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const handoff = read('admin/src/components/CleaningFieldHandoffPanel.vue');
|
|
for (const pattern of [
|
|
'现场联调进度',
|
|
'qipai.cleaning.field-handoff',
|
|
'qipai.cleaning.field-handoff.session',
|
|
'联调批次',
|
|
'现场/门店',
|
|
'验收人',
|
|
'收口结论',
|
|
'下一步',
|
|
'acceptor',
|
|
'closeoutVerdict',
|
|
'nextAction',
|
|
'createEmptySessionMeta',
|
|
'最后更新',
|
|
'证据记录',
|
|
'evidenceRecordedCount',
|
|
'待补证据',
|
|
'evidenceMissingItems',
|
|
'evidenceMissingCount',
|
|
'copyEvidenceSummary',
|
|
'待补证据清单已复制',
|
|
'现场交接报告已复制',
|
|
'copyHandoffReport',
|
|
'exportHandoffReport',
|
|
'buildHandoffReport',
|
|
'formatReportItem',
|
|
'statusText',
|
|
'cleaning-field-handoff-report',
|
|
'evidenceRef',
|
|
'normalizeDraft',
|
|
'sessionMeta',
|
|
'updatedAt',
|
|
'persistSessionMeta',
|
|
'formatLocalMinute',
|
|
'快照',
|
|
'导入',
|
|
'exportSnapshot',
|
|
'importSnapshot',
|
|
'qipai.cleaning.field-handoff.snapshot.v1',
|
|
'cleaning-field-handoff-snapshot',
|
|
'categoryProgress',
|
|
'passPercent',
|
|
'handoff-category-progress',
|
|
'可进入现场验收收口',
|
|
'handoffReady',
|
|
'missingCloseoutFields',
|
|
'closeoutReady',
|
|
'copyVerdict',
|
|
'copyCloseoutGate',
|
|
'收口门禁已复制',
|
|
'归档门禁',
|
|
'现场记录可归档',
|
|
'收口资料待补齐',
|
|
'检查项状态',
|
|
'现场证据',
|
|
'联调结论已复制',
|
|
'商户凭据引用',
|
|
'小程序合法域名',
|
|
'小额真实转账',
|
|
'订单权限开门',
|
|
'控电和插座联动',
|
|
'BLOCKED',
|
|
'statusFilter',
|
|
'handoff-status-select',
|
|
'全部状态',
|
|
'批量标记',
|
|
'bulkForm',
|
|
'applyBulkMark',
|
|
'应用到当前筛选',
|
|
'阻断摘要',
|
|
'blockedItems',
|
|
'copyBlockedSummary',
|
|
'navigator.clipboard.writeText',
|
|
'exportChecklist',
|
|
'cleaning-field-handoff',
|
|
'localStorage',
|
|
'downloadCsv'
|
|
]) {
|
|
assert.match(handoff, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
}
|
|
|
|
const styles = read('admin/src/styles.css');
|
|
assert.match(styles, /\.cleaner-select/);
|
|
assert.match(styles, /\.option-row/);
|
|
assert.match(styles, /\.filter-select/);
|
|
assert.match(styles, /\.narrow-input/);
|
|
assert.match(styles, /\.action-board/);
|
|
assert.match(styles, /\.action-tile/);
|
|
assert.match(styles, /\.handoff-summary/);
|
|
assert.match(styles, /\.handoff-body/);
|
|
assert.match(styles, /\.handoff-session/);
|
|
assert.match(styles, /\.handoff-category-progress/);
|
|
assert.match(styles, /\.handoff-category-row/);
|
|
assert.match(styles, /\.handoff-verdict/);
|
|
assert.match(styles, /\.handoff-status-select/);
|
|
assert.match(styles, /\.handoff-bulk-form/);
|
|
assert.match(styles, /\.handoff-blockers/);
|
|
assert.match(styles, /\.hidden-file-input/);
|
|
assert.match(styles, /\.transfer-preflight-alert/);
|
|
assert.match(styles, /@media \(max-width: 980px\)/);
|
|
assert.match(styles, /@media \(max-width: 560px\)/);
|
|
|
|
console.log('PASS: M08-B admin cleaning workspace covers task, settlement, transfer and preflight controls.');
|