refactor(M08-D-R1): 后台改用权限路由与懒加载
This commit is contained in:
@@ -19,7 +19,10 @@ const vite = read('admin/vite.config.ts');
|
||||
assert.match(vite, /base: '\/admin\/'/);
|
||||
assert.match(vite, /'\/admin-api'/);
|
||||
|
||||
const app = read('admin/src/App.vue');
|
||||
const app = [
|
||||
read('admin/src/App.vue'),
|
||||
read('admin/src/components/CleaningWorkspace.vue')
|
||||
].join('\n');
|
||||
for (const pattern of [
|
||||
'CleaningTasksPanel',
|
||||
'CleaningSettlementsPanel',
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
||||
import { gzipSync } from 'node:zlib';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = fileURLToPath(new URL('..', import.meta.url));
|
||||
const read = (path) => readFileSync(join(root, path), 'utf8');
|
||||
const sourceOnly = process.argv.includes('--source-only');
|
||||
const distOnly = process.argv.includes('--dist-only');
|
||||
|
||||
if (!distOnly) {
|
||||
const packageJson = JSON.parse(read('admin/package.json'));
|
||||
assert.ok(packageJson.dependencies['vue-router']);
|
||||
assert.ok(packageJson.devDependencies['unplugin-vue-components']);
|
||||
|
||||
const main = read('admin/src/main.ts');
|
||||
assert.match(main, /use\(router\)/);
|
||||
assert.doesNotMatch(main, /ElementPlus|element-plus\/dist\/index\.css/);
|
||||
|
||||
const app = read('admin/src/App.vue');
|
||||
for (const pattern of ['RouterLink', 'RouterView', 'Suspense', 'routeLoadError',
|
||||
'retryLazyRoute', 'restoreSession', 'qipai:admin-refreshed']) assert.match(app, new RegExp(pattern));
|
||||
assert.doesNotMatch(app, /import\s+(?!AdminLoginPanel\b)\w+Panel\s+from/);
|
||||
|
||||
const router = read('admin/src/router.ts');
|
||||
for (const path of ['/overview', '/stores', '/orders', '/payments', '/third-party',
|
||||
'/people', '/cleaning', '/devices', '/apps', '/content', '/franchise', '/system']) {
|
||||
assert.match(read('admin/src/navigation.mjs'), new RegExp(`path: '${path.replace('/', '\\/')}'`));
|
||||
}
|
||||
assert.equal((router.match(/\(\) => import\('/g) || []).length, 12);
|
||||
assert.match(router, /router\.beforeEach/);
|
||||
assert.match(router, /isNavigationAllowed/);
|
||||
|
||||
const api = read('admin/src/api.ts');
|
||||
assert.match(api, /let refreshInFlight: Promise<AdminSessionPayload> \| null = null/);
|
||||
assert.match(api, /if \(!refreshInFlight\)/);
|
||||
assert.match(api, /refreshInFlight = publicRequest<AdminSessionPayload>\('\/auth\/refresh'/);
|
||||
assert.match(api, /\.finally\(\(\) => \{ refreshInFlight = null; \}\)/);
|
||||
assert.match(api, /return refreshInFlight/);
|
||||
|
||||
const vite = read('admin/vite.config.ts');
|
||||
assert.match(vite, /ElementPlusResolver/);
|
||||
assert.doesNotMatch(vite, /chunkSizeWarningLimit/);
|
||||
assert.doesNotMatch(vite, /element:\s*\['element-plus'\]/);
|
||||
|
||||
const styles = read('admin/src/styles.css');
|
||||
for (const pattern of ['@media (max-width: 980px)', '@media (max-width: 768px)',
|
||||
'@media (max-width: 560px)', '.workspace .data-table .el-table__row',
|
||||
'.workspace .el-dialog', '.session-recovery', '.route-state']) assert.ok(styles.includes(pattern));
|
||||
}
|
||||
|
||||
if (!sourceOnly) {
|
||||
const dist = join(root, 'admin/dist');
|
||||
assert.ok(existsSync(join(dist, 'index.html')), 'admin production build is missing');
|
||||
const assets = join(dist, 'assets');
|
||||
const javascript = readdirSync(assets).filter((name) => name.endsWith('.js'));
|
||||
const largest = javascript
|
||||
.map((name) => ({ name, bytes: statSync(join(assets, name)).size }))
|
||||
.sort((left, right) => right.bytes - left.bytes)[0];
|
||||
assert.ok(largest.bytes < 500 * 1024, `chunk ${largest.name} exceeds 500 KiB`);
|
||||
for (const chunk of ['OperationsOverviewPanel', 'StoresRoomsPanel', 'OrdersPanel',
|
||||
'PaymentsPanel', 'ThirdPartyPanel', 'MembersStaffPanel', 'CleaningWorkspace',
|
||||
'DevicesPanel', 'PlatformAppsPanel', 'ContentManagementPanel', 'FranchisePanel',
|
||||
'LogsSystemPanel']) assert.ok(javascript.some((name) => name.startsWith(`${chunk}-`)), `${chunk} is not lazy`);
|
||||
const entry = javascript.find((name) => name.startsWith('index-'));
|
||||
assert.ok(entry);
|
||||
assert.ok(gzipSync(readFileSync(join(assets, entry))).length < 120 * 1024, 'entry gzip exceeds 120 KiB');
|
||||
assert.doesNotMatch(read('admin/dist/index.html'), /CleaningWorkspace|StoresRoomsPanel|OrdersPanel/);
|
||||
console.log(`PASS: M08-D-R1 lazy chunks are below 500 KiB; largest=${largest.name}:${largest.bytes}.`);
|
||||
} else {
|
||||
console.log('PASS: M08-D-R1 route, permission, recovery and responsive source gates are present.');
|
||||
}
|
||||
@@ -8,39 +8,31 @@ 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'",
|
||||
"activeModule = 'platformApps'",
|
||||
"activeModule = 'content'",
|
||||
"activeModule = 'franchise'",
|
||||
"activeModule = 'system'",
|
||||
'平台运营总览',
|
||||
'StoresRoomsPanel',
|
||||
'OrdersPanel',
|
||||
'PaymentsPanel',
|
||||
'ThirdPartyPanel',
|
||||
'MembersStaffPanel',
|
||||
'DevicesPanel',
|
||||
'PlatformAppsPanel',
|
||||
'ContentManagementPanel',
|
||||
'FranchisePanel',
|
||||
'LogsSystemPanel',
|
||||
'RouterLink',
|
||||
'RouterView',
|
||||
'visibleNavigation',
|
||||
'isNavigationAllowed',
|
||||
'restoreSession',
|
||||
'routeLoadError',
|
||||
'AdminLoginPanel',
|
||||
'运营总览',
|
||||
'savedToken',
|
||||
'handleAuthenticated',
|
||||
'handleLogout',
|
||||
'loadCleaningWorkspace'
|
||||
'openCleaning'
|
||||
]) {
|
||||
assert.match(app, new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
||||
}
|
||||
assert.doesNotMatch(app, /import\s+(?!AdminLoginPanel\b)\w+Panel\s+from/);
|
||||
|
||||
const router = read('admin/src/router.ts');
|
||||
assert.equal((router.match(/\(\) => import\('/g) || []).length, 12);
|
||||
assert.match(router, /router\.beforeEach/);
|
||||
const navigation = read('admin/src/navigation.mjs');
|
||||
for (const path of ['/overview', '/stores', '/orders', '/payments', '/third-party', '/people',
|
||||
'/cleaning', '/devices', '/apps', '/content', '/franchise', '/system']) assert.ok(navigation.includes(`path: '${path}'`));
|
||||
|
||||
const cleaningWorkspace = read('admin/src/components/CleaningWorkspace.vue');
|
||||
for (const pattern of ['CleaningTasksPanel', 'CleaningSettlementsPanel', 'CleaningStatisticsPanel',
|
||||
'CleanersPanel', 'CleaningFieldHandoffPanel', 'loadCleaningWorkspace']) assert.match(cleaningWorkspace, new RegExp(pattern));
|
||||
|
||||
const overview = read('admin/src/components/OperationsOverviewPanel.vue');
|
||||
for (const pattern of [
|
||||
@@ -301,10 +293,13 @@ for (const pattern of [
|
||||
'.audit-filters',
|
||||
'.login-shell',
|
||||
'.session-box',
|
||||
'.session-recovery',
|
||||
'.route-state',
|
||||
'@media (max-width: 980px)',
|
||||
'@media (max-width: 768px)',
|
||||
'@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.');
|
||||
console.log('PASS: M08-D admin operations and M08-D-R1 route architecture are present.');
|
||||
|
||||
@@ -1,28 +1,59 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Assert-NativeSuccess([string]$Step) {
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$Step failed with exit code $LASTEXITCODE."
|
||||
}
|
||||
}
|
||||
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-workspace.ps1
|
||||
Assert-NativeSuccess "check-workspace"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-reference.ps1
|
||||
Assert-NativeSuccess "check-reference"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-line-endings.ps1
|
||||
Assert-NativeSuccess "check-line-endings"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-large-files.ps1
|
||||
Assert-NativeSuccess "check-large-files"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-repo-completeness.ps1
|
||||
Assert-NativeSuccess "check-repo-completeness"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-release-manifest.ps1
|
||||
Assert-NativeSuccess "check-release-manifest"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-status-docs.ps1
|
||||
Assert-NativeSuccess "check-status-docs"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-readme-config.ps1
|
||||
Assert-NativeSuccess "check-readme-config"
|
||||
& powershell -ExecutionPolicy Bypass -File scripts/dev/windows/check-backend.ps1
|
||||
Assert-NativeSuccess "check-backend"
|
||||
node scripts/check-admin-m08-b.mjs
|
||||
Assert-NativeSuccess "check-admin-m08-b"
|
||||
node scripts/check-admin-m08-d.mjs
|
||||
Assert-NativeSuccess "check-admin-m08-d"
|
||||
node scripts/check-admin-m08-d-r1.mjs --source-only
|
||||
Assert-NativeSuccess "check-admin-m08-d-r1 source"
|
||||
node scripts/check-miniapp-m08-c.mjs
|
||||
Assert-NativeSuccess "check-miniapp-m08-c"
|
||||
|
||||
if (Test-Path "admin/package.json") {
|
||||
Push-Location admin
|
||||
npm run build
|
||||
Pop-Location
|
||||
try {
|
||||
npm run build
|
||||
Assert-NativeSuccess "admin build"
|
||||
npm test
|
||||
Assert-NativeSuccess "admin test"
|
||||
node ../scripts/check-admin-m08-d-r1.mjs --dist-only
|
||||
Assert-NativeSuccess "check-admin-m08-d-r1 dist"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path "package.json") {
|
||||
npm run lint --if-present
|
||||
Assert-NativeSuccess "root lint"
|
||||
npm test --if-present
|
||||
Assert-NativeSuccess "root test"
|
||||
npm run build --if-present
|
||||
Assert-NativeSuccess "root build"
|
||||
}
|
||||
|
||||
Write-Host "PASS: M00 local checks completed."
|
||||
|
||||
Reference in New Issue
Block a user