import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, OnInit, computed, inject, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { CheckCircle2, CircleAlert, CloudCog, Database, LoaderCircle, LucideAngularModule } from 'lucide-angular'; import { AppMigrationStatus } from '../admin.models'; import { CloudFunctionsService } from '../cloud-functions.service'; import { LEGACY_ADMIN_COVERAGE, LegacyAdminCoverageStatus } from '../legacy-admin-coverage.generated'; interface MigrationMeta { classes: number; cloudFunctions: number; identity: { company?: unknown; isSuperAdmin: boolean }; } @Component({ selector: 'app-admin-migration', standalone: true, imports: [CommonModule, FormsModule, LucideAngularModule], templateUrl: './admin-migration.component.html', styleUrl: './admin-migration.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class AdminMigrationComponent implements OnInit { readonly meta = signal(null); readonly appStatus = signal(null); readonly blockedEntries = computed(() => Object.entries(this.appStatus()?.blocked ?? {}).sort(([left], [right]) => left.localeCompare(right))); readonly adminSearch = signal(''); readonly adminStatusFilter = signal<'all' | LegacyAdminCoverageStatus>('all'); readonly adminCounts = computed(() => LEGACY_ADMIN_COVERAGE.reduce((counts, entry) => { counts[entry.status] += 1; return counts; }, { implemented: 0, partial: 0, 'blocked-data': 0, 'blocked-infrastructure': 0, pending: 0 } as Record)); readonly filteredAdminCoverage = computed(() => { const keyword = this.adminSearch().trim().toLocaleLowerCase(); const status = this.adminStatusFilter(); return LEGACY_ADMIN_COVERAGE.filter((entry) => (status === 'all' || entry.status === status) && (!keyword || `${entry.module} ${entry.action} ${entry.reason}`.toLocaleLowerCase().includes(keyword))); }); readonly error = signal(''); readonly icons = { CheckCircle2, CircleAlert, CloudCog, Database, LoaderCircle }; readonly rewrites = [ ['内容 HTML 规范化', 'cms.content-normalizer', 'implemented'], ['购物车投影', '/xiaoshu/cms/cart/items', 'blocked'], ['用户扩展资料', '/xiaoshu/cms/users/extended', 'implemented'], ['考试班级投影', '/xiaoshu/cms/exams/classes', 'implemented'], ['互动社区投影', '/xiaoshu/cms/guest/bar', 'implemented'], ['已支付订单', '/xiaoshu/cms/orders/paid', 'blocked'], ['商品销售投影', '/xiaoshu/cms/orders/product-sales', 'blocked'], ['订单分享投影', '/xiaoshu/cms/orders/share', 'blocked'], ['博客列表', '/xiaoshu/cms/blogs', 'blocked'], ['统一内容搜索', '/xiaoshu/cms/search', 'implemented'], ['用户平台资料', '/xiaoshu/cms/users/platform', 'implemented'], ['用户微信资料', '/xiaoshu/cms/users/wechat', 'implemented'], ] as const; private readonly functions = inject(CloudFunctionsService); adminStatusLabel(status: LegacyAdminCoverageStatus): string { return ({ implemented: '已实现', partial: '部分实现', 'blocked-data': '数据阻塞', 'blocked-infrastructure': '基础设施阻塞', pending: '待核验' })[status]; } async ngOnInit(): Promise { try { const [meta, appStatus] = await Promise.all([ this.functions.admin('meta'), this.functions.app('migration_status'), ]); this.meta.set(meta); this.appStatus.set(appStatus); } catch (error) { this.error.set(error instanceof Error ? error.message : '迁移状态加载失败'); } } }