222 lines
6.0 KiB
JavaScript
222 lines
6.0 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 app = read('admin/src/App.vue');
|
||
for (const pattern of [
|
||
'OperationsOverviewPanel',
|
||
"activeModule = 'overview'",
|
||
"activeModule = 'cleaning'",
|
||
"activeModule = 'stores'",
|
||
"activeModule = 'orders'",
|
||
"activeModule = 'payments'",
|
||
"activeModule = 'thirdParty'",
|
||
"activeModule = 'people'",
|
||
"activeModule = 'devices'",
|
||
'平台运营总览',
|
||
'StoresRoomsPanel',
|
||
'OrdersPanel',
|
||
'PaymentsPanel',
|
||
'ThirdPartyPanel',
|
||
'MembersStaffPanel',
|
||
'DevicesPanel',
|
||
'运营总览',
|
||
'savedToken',
|
||
'loadCleaningWorkspace'
|
||
]) {
|
||
assert.match(app, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
||
}
|
||
|
||
const overview = read('admin/src/components/OperationsOverviewPanel.vue');
|
||
for (const pattern of [
|
||
'listManagedStores',
|
||
'getBusinessStatistics',
|
||
'近 7 日',
|
||
'近 30 日',
|
||
'近 90 日',
|
||
'成功实收',
|
||
'预订金额',
|
||
'下单会员',
|
||
'验券成功',
|
||
'当前房态',
|
||
'支付渠道',
|
||
'每日收入趋势',
|
||
'核心业务导航',
|
||
'open-cleaning',
|
||
'后续增量',
|
||
'collectedAmountCents',
|
||
'availableRoomTotal',
|
||
'paymentChannels',
|
||
'dailyRevenue',
|
||
'errorMessage'
|
||
]) {
|
||
assert.match(overview, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
||
}
|
||
|
||
const api = read('admin/src/api.ts');
|
||
assert.match(api, /request<ManagedStore\[]>\(session, '\/stores'\)/);
|
||
assert.match(api, /request<BusinessStatistics>\(session, `\/statistics\?\$\{params\}`\)/);
|
||
for (const pattern of [
|
||
'createManagedStore',
|
||
'updateManagedStore',
|
||
'archiveManagedStore',
|
||
'listManagedRooms',
|
||
'createManagedRoom',
|
||
'updateManagedRoom',
|
||
'updateManagedRoomStatus',
|
||
'addManagedRoomDisabledPeriod'
|
||
]) {
|
||
assert.match(api, new RegExp(pattern));
|
||
}
|
||
|
||
const stores = read('admin/src/components/StoresRoomsPanel.vue');
|
||
for (const pattern of [
|
||
'门店与房间管理',
|
||
'搜索门店、城市或地址',
|
||
'每周营业时间',
|
||
'wifiPassword',
|
||
'listManagedStores',
|
||
'listManagedRooms',
|
||
'updateManagedRoomStatus',
|
||
'新增房间',
|
||
'停用时段',
|
||
'configurationStatus',
|
||
'operationalStatus',
|
||
'archiveManagedRoom'
|
||
]) {
|
||
assert.match(stores, new RegExp(pattern));
|
||
}
|
||
|
||
const orders = read('admin/src/components/OrdersPanel.vue');
|
||
for (const pattern of [
|
||
'订单筛选与处置',
|
||
'listManagedOrders',
|
||
'getManagedOrder',
|
||
'listManagedOrderHistory',
|
||
'executeManagedOrderAction',
|
||
'addManagedOrderNote',
|
||
'adjustManagedOrderTime',
|
||
'renewManagedOrder',
|
||
'changeManagedOrderRoom',
|
||
'导出当前页',
|
||
'状态流水',
|
||
'allowedActions'
|
||
]) {
|
||
assert.match(orders, new RegExp(pattern));
|
||
}
|
||
|
||
const payments = read('admin/src/components/PaymentsPanel.vue');
|
||
for (const pattern of [
|
||
'支付、退款与分账',
|
||
'getProfitSharingSnapshot',
|
||
'saveCollectionAccount',
|
||
'saveProfitShareReceiver',
|
||
'saveProfitSharePolicy',
|
||
'createWechatRefund',
|
||
'requestWechatReconciliation',
|
||
'executeProfitSharing',
|
||
'凭据只保存环境引用',
|
||
'clientRequestId',
|
||
'生产 API',
|
||
'非生产 Mock'
|
||
]) {
|
||
assert.match(payments, new RegExp(pattern));
|
||
}
|
||
|
||
const thirdParty = read('admin/src/components/ThirdPartyPanel.vue');
|
||
for (const pattern of [
|
||
'listThirdPartyRecords',
|
||
'getThirdPartySetup',
|
||
'redeemGroupVoucher',
|
||
'redeemGroupVoucherManually',
|
||
'saveThirdPartyConfig',
|
||
'saveThirdPartyMapping',
|
||
'voucherCode',
|
||
'PENDING_MAPPING'
|
||
]) {
|
||
assert.match(thirdParty, new RegExp(pattern));
|
||
}
|
||
|
||
const thirdPartyRoutes = read('backend/src/routes/third-party.ts');
|
||
assert.match(thirdPartyRoutes, /'\/admin-api\/third-party\/setup'/);
|
||
assert.match(thirdPartyRoutes, /'\/admin-api\/group-vouchers\/redeem'/);
|
||
|
||
const people = read('admin/src/components/MembersStaffPanel.vue');
|
||
for (const pattern of [
|
||
'listMembers',
|
||
'getMember',
|
||
'listStaffUsers',
|
||
'createStaffUser',
|
||
'updateStaffUser',
|
||
'resetStaffSessions',
|
||
'memberDetail',
|
||
'staffForm'
|
||
]) {
|
||
assert.match(people, new RegExp(pattern));
|
||
}
|
||
|
||
const userRoutes = read('backend/src/routes/user-management.ts');
|
||
assert.match(userRoutes, /userType: z\.enum\(\['STAFF'\]\)\.optional\(\)/);
|
||
|
||
const devices = read('admin/src/components/DevicesPanel.vue');
|
||
for (const pattern of [
|
||
'getDeviceTopology',
|
||
'createDeviceAsset',
|
||
'bindDeviceChannel',
|
||
'bindSubDevice',
|
||
'addDeviceMaintenance',
|
||
'controlDevice',
|
||
'openAlerts',
|
||
'Sub‑1G'
|
||
]) {
|
||
assert.match(devices, new RegExp(pattern));
|
||
}
|
||
|
||
const routes = read('backend/src/routes/business-statistics.ts');
|
||
assert.match(routes, /'\/app-api\/management\/statistics', '\/admin-api\/statistics'/);
|
||
|
||
const routeTest = read('backend/tests/business-statistics.test.mjs');
|
||
assert.match(routeTest, /url: '\/admin-api\/statistics\?/);
|
||
|
||
const storeRepository = read('backend/src/stores/store-room-repository.ts');
|
||
assert.match(storeRepository, /wifi_password = COALESCE\(\?, wifi_password\)/);
|
||
assert.match(storeRepository, /FROM qipai_store_business_hours/);
|
||
assert.match(storeRepository, /wifiConfigured/);
|
||
|
||
const orderQueryRoutes = read('backend/src/routes/order-query.ts');
|
||
assert.match(orderQueryRoutes, /'\/admin-api\/orders'/);
|
||
const orderStateRoutes = read('backend/src/routes/order-state.ts');
|
||
assert.match(orderStateRoutes, /'\/admin-api\/orders\/:orderId\/history'/);
|
||
|
||
const styles = read('admin/src/styles.css');
|
||
for (const pattern of [
|
||
'.overview-page',
|
||
'.overview-toolbar',
|
||
'.overview-metrics',
|
||
'.overview-grid',
|
||
'.revenue-bars',
|
||
'.module-grid',
|
||
'.store-layout',
|
||
'.store-card',
|
||
'.hours-editor',
|
||
'.order-page-summary',
|
||
'.history-card',
|
||
'.payment-metrics',
|
||
'.payment-tools-grid',
|
||
'.third-party-metrics',
|
||
'.settings-preview',
|
||
'.people-metrics',
|
||
'.member-detail-grid',
|
||
'.device-metrics',
|
||
'.device-topology-grid',
|
||
'@media (max-width: 980px)',
|
||
'@media (max-width: 560px)'
|
||
]) {
|
||
assert.match(styles, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
||
}
|
||
|
||
console.log('PASS: M08-D admin operations overview and scoped business statistics are present.');
|