kt-template-online-api/docs/plans/2026-06-15-api-admin-architecture-convergence-v3.md

57 KiB
Raw Permalink Blame History

API/Admin Architecture Convergence V3 Implementation Plan

Execution note: Execute this plan task-by-task with the KT-local workflow and use the checkboxes to track plan state.

Goal: Make the third-phase target architecture true in code by migrating all API legacy roots into src/modules/**, enforcing structure tests, slimming every API/Admin domain, preserving behavior, and deleting src/admin, src/blog, src/minio, src/wordpress, and src/qqbot.

Architecture: Work from hard RED structure gates, then migrate one domain at a time. Each domain task includes three inseparable pieces: move ownership into the target module, remove duplicate/unused transitional code, and run behavior checks that prove existing routes and Admin pages still work. The final task deletes old roots and runs the full convergence gate.

Tech Stack: NestJS 11, TypeORM 0.3, MySQL, Jest, pnpm 9 API workspace, Vben Admin 5, Vue 3 TSX/Vue SFC, Vitest, pnpm 10 Admin workspace, ktWorkflow global review, KT global review.


Scope Check

This plan covers two repos because the approved spec requires API and Admin to converge together:

  • API repo: D:\MyFiles\KT\Node\kt-template-online-api, branch dev-api-architecture-convergence-v3.
  • Admin repo: D:\MyFiles\KT\Vue\kt-template-admin, branch dev-admin-architecture-convergence-v3.
  • Root repo: D:\MyFiles\KT, branch main, used only for TASKS.md record updates.

The work is one architecture-convergence batch, not a new product phase. Do not split into an API-only plan and an Admin-only plan; the Admin caller/page slimming is part of the same completion gate.

Current State Evidence

API old roots currently exist:

Root Files Directories
src/admin 42 11
src/blog 13 0
src/minio 5 0
src/wordpress 9 0
src/qqbot 55 14

src/modules/** currently imports old roots:

Alias Hits
@/admin/ 37
@/blog/ 7
@/minio/ 3
@/wordpress/ 7
@/qqbot/ 50

Admin current touched domains:

  • API callers: apps/web-antdv-next/src/api/system/**, apps/web-antdv-next/src/api/blog/**, apps/web-antdv-next/src/api/qqbot/**.
  • Pages: apps/web-antdv-next/src/views/system/**, apps/web-antdv-next/src/views/blog/**, apps/web-antdv-next/src/views/qqbot/**.

Execution Rules

  • Do not push.
  • Do not deploy.
  • Do not run online database writes.
  • Do not create .worktree.
  • Use apply_patch for manual code edits.
  • Use git mv for file moves when practical so history stays readable.
  • Before deleting a file, run rg for the exported class/function/type and for the relative path stem.
  • Every task must leave the repo status understandable: only paths named by the task should be changed.
  • Every domain migration must record its slimming decisions in docs/refactor-v3/architecture-convergence-inventory.md.
  • If a domain has a feature that is only reachable by reflection, SQL seed, menu route, plugin manifest, or Nest DI, prove it with a test or smoke before deleting it.
  • Keep route paths and response shapes stable unless the task explicitly updates Admin callers and smoke evidence.

File Structure Map

API Files To Create

Path Responsibility
test/refactor-v3/architecture-convergence.spec.ts Hard API structure gate for old roots, forbidden imports, target modules, and app module imports.
docs/refactor-v3/architecture-convergence-inventory.md Per-domain slimming evidence: delete, merge, keep, and uncertain decisions.
docs/refactor-v3/architecture-convergence-verification.md Final command evidence and smoke summary.

API Files To Move Or Rewrite

Source Target
src/admin/auth/** src/modules/admin/identity/auth/**
src/admin/user/** src/modules/admin/identity/user/**
src/admin/role/** src/modules/admin/identity/role/**
src/admin/menu/** src/modules/admin/identity/menu/**
src/admin/dept/** src/modules/admin/identity/dept/**
src/admin/admin.types.ts src/modules/admin/contract/admin.types.ts
src/admin/component/** src/modules/admin/platform-config/component/**
src/admin/dict/** src/modules/admin/platform-config/dict/**
src/admin/notice/** src/modules/admin/platform-config/notice/**
src/admin/system-log/** src/modules/admin/platform-config/system-log/**
src/admin/timezone/** src/modules/admin/platform-config/timezone/**
src/admin/example/** Delete unless route/menu/test evidence proves it is active.
src/blog/** src/modules/blog/**, split controller/DTO/service/entity by local responsibility.
src/wordpress/** src/modules/wordpress/**, split controller/DTO/service/types by local responsibility.
src/minio/** src/modules/asset/**, keep /minio/* routes but remove old source root.
src/qqbot/account/qqbot-napcat-login.service.ts src/modules/qqbot/napcat/login/qqbot-napcat-login.service.ts
src/qqbot/account/qqbot-napcat-watchdog.service.ts src/modules/qqbot/napcat/login/qqbot-napcat-watchdog.service.ts
src/qqbot/napcat/** src/modules/qqbot/napcat/**
src/qqbot/account/** except NapCat login services src/modules/qqbot/core/account/**
src/qqbot/command/** src/modules/qqbot/core/command/**
src/qqbot/config/** src/modules/qqbot/core/config/**
src/qqbot/connection/** src/modules/qqbot/core/connection/**
src/qqbot/dashboard/** src/modules/qqbot/core/dashboard/**
src/qqbot/dedupe/** src/modules/qqbot/core/dedupe/**
src/qqbot/event/** src/modules/qqbot/core/event/**
src/qqbot/message/** src/modules/qqbot/core/message/**
src/qqbot/mqtt/** src/modules/qqbot/core/mqtt/**
src/qqbot/permission/** src/modules/qqbot/core/permission/**
src/qqbot/rule/** src/modules/qqbot/core/rule/**
src/qqbot/send/** src/modules/qqbot/core/send/**
src/qqbot/plugin/** Replace with src/modules/qqbot/plugin-platform/** contracts or delete old registry.
src/qqbot/qqbot.types.ts src/modules/qqbot/core/contract/qqbot.types.ts
src/qqbot/qqbot.constants.ts src/modules/qqbot/core/contract/qqbot.constants.ts
src/qqbot/qqbot-cooldown.policy.ts src/modules/qqbot/core/domain/qqbot-cooldown.policy.ts
src/qqbot/qqbot.module.ts Delete after QqbotCoreModule and QqbotPluginPlatformModule own all providers.

Admin Files To Create Or Modify

Path Responsibility
apps/web-antdv-next/src/api/qqbot/index.ts QQBot core caller/type boundary.
apps/web-antdv-next/src/api/qqbot/plugin.ts Plugin platform caller/type boundary.
apps/web-antdv-next/src/api/qqbot/napcat.ts NapCat device/login/SSE helpers and Chinese progress labels.
apps/web-antdv-next/src/api/system/*.ts System caller cleanup and type de-duplication.
apps/web-antdv-next/src/api/blog/*.ts Blog/WordPress/Asset caller cleanup and type de-duplication.
apps/web-antdv-next/src/views/system/** System page slimming and route/menu consistency.
apps/web-antdv-next/src/views/blog/** Blog/WordPress/Asset page slimming and shared list/upload/import state.
apps/web-antdv-next/src/views/qqbot/modules/status.ts Shared QQBot status/tag/progress mappings.
apps/web-antdv-next/src/views/qqbot/modules/actions.tsx Shared QQBot table and operation actions.
apps/web-antdv-next/src/views/qqbot/** QQBot Core, Plugin Platform, and NapCat page cleanup.
apps/web-antdv-next/src/api/qqbot/napcat.spec.ts Keep and extend NapCat helper tests.

Task 0: Preflight And Inventory Baseline

Files:

  • Create: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Modify: D:\MyFiles\KT\TASKS.md

  • Step 1: Confirm clean repos and branches

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api status --short --branch
git -C D:\MyFiles\KT\Vue\kt-template-admin status --short --branch
git -C D:\MyFiles\KT status --short --branch

Expected:

## dev-api-architecture-convergence-v3
## dev-admin-architecture-convergence-v3
## main
  • Step 2: Confirm package managers

Run:

Get-Content D:\MyFiles\KT\Node\kt-template-online-api\package.json | Select-String '"packageManager"'
Get-Content D:\MyFiles\KT\Vue\kt-template-admin\package.json | Select-String '"packageManager"|"engines"'
Get-Content D:\MyFiles\KT\Vue\kt-template-admin\.node-version

Expected:

"packageManager": "pnpm@9.15.9+sha512
"packageManager": "pnpm@10.28.2"
22.22.0
  • Step 3: Add inventory document

Use apply_patch to create D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md:

# Architecture Convergence Inventory

## Baseline

| Area | Current Evidence | Target Evidence |
| --- | --- | --- |
| API legacy roots | `src/admin`, `src/blog`, `src/minio`, `src/wordpress`, `src/qqbot` exist. | These paths do not exist. |
| API forbidden module imports | `src/modules/**` imports old roots. | No import from `@/admin`, `@/blog`, `@/minio`, `@/wordpress`, or `@/qqbot`. |
| Admin System | System pages and callers exist under `views/system` and `api/system`. | No duplicate caller/type/page state after cleanup. |
| Admin Blog/Asset | Blog, WordPress, and Asset callers/pages exist under `api/blog` and `views/blog`. | Shared list/upload/import state where behavior repeats. |
| Admin QQBot | QQBot callers/pages exist under `api/qqbot` and `views/qqbot`. | Core, Plugin Platform, and NapCat state boundaries are explicit. |

## Domain Decisions

| Domain | Deleted | Merged | Kept | Evidence |
| --- | --- | --- | --- | --- |
| Admin/Auth/Platform Config | none yet | none yet | current files before migration | baseline only |
| Blog/WordPress/Asset | none yet | none yet | current files before migration | baseline only |
| Runtime/Common | none yet | none yet | current files before migration | baseline only |
| QQBot Core/NapCat | none yet | none yet | current files before migration | baseline only |
| Plugin Platform/Plugins | none yet | none yet | current files before migration | baseline only |
| Admin UI | none yet | none yet | current files before migration | baseline only |
  • Step 4: Run baseline scans

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
$roots = @('src/admin','src/blog','src/minio','src/wordpress','src/qqbot')
foreach ($root in $roots) {
  $path = Join-Path $api $root
  if (Test-Path $path) {
    $files = @(rg --files $path)
    Write-Output "$root files=$($files.Count)"
  }
}
rg -n '@/(admin|blog|minio|wordpress|qqbot)/' D:\MyFiles\KT\Node\kt-template-online-api\src\modules

Expected: old roots and forbidden imports are present before migration.

  • Step 5: Commit baseline inventory

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "docs: 建立架构收敛清理清单"

Expected: commit succeeds and includes only the inventory document.

Task 1: API RED Structure Gate

Files:

  • Create: D:\MyFiles\KT\Node\kt-template-online-api\test\refactor-v3\architecture-convergence.spec.ts

  • Step 1: Write failing structure test

Create D:\MyFiles\KT\Node\kt-template-online-api\test\refactor-v3\architecture-convergence.spec.ts with this content:

import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
import { join, relative } from 'node:path';

const repoRoot = join(__dirname, '..', '..');
const srcRoot = join(repoRoot, 'src');

const legacyRoots = ['admin', 'blog', 'minio', 'wordpress', 'qqbot'];
const moduleRoots = ['admin', 'asset', 'blog', 'wordpress', 'qqbot'];
const qqbotRoots = ['core', 'napcat', 'plugin-platform', 'plugins'];

function listFiles(dir: string): string[] {
  if (!existsSync(dir)) return [];
  return readdirSync(dir).flatMap((entry) => {
    const absolute = join(dir, entry);
    const stat = statSync(absolute);
    if (stat.isDirectory()) return listFiles(absolute);
    return [absolute];
  });
}

function readTextFiles(dir: string): Array<{ file: string; text: string }> {
  return listFiles(dir)
    .filter((file) => /\.(ts|tsx|vue|js|mjs|cjs)$/.test(file))
    .map((file) => ({
      file: relative(repoRoot, file).replace(/\\/g, '/'),
      text: readFileSync(file, 'utf8'),
    }));
}

describe('architecture convergence', () => {
  it('does not keep API legacy source roots', () => {
    const existing = legacyRoots.filter((root) =>
      existsSync(join(srcRoot, root)),
    );

    expect(existing).toEqual([]);
  });

  it('keeps all business modules under src/modules', () => {
    const missing = moduleRoots.filter(
      (root) => !existsSync(join(srcRoot, 'modules', root)),
    );

    expect(missing).toEqual([]);
  });

  it('keeps QQBot subdomains under src/modules/qqbot', () => {
    const missing = qqbotRoots.filter(
      (root) => !existsSync(join(srcRoot, 'modules', 'qqbot', root)),
    );

    expect(missing).toEqual([]);
  });

  it('does not import old roots from src/modules', () => {
    const forbidden = /@\/(?:admin|blog|minio|wordpress|qqbot)\//;
    const offenders = readTextFiles(join(srcRoot, 'modules'))
      .filter(({ text }) => forbidden.test(text))
      .map(({ file }) => file);

    expect(offenders).toEqual([]);
  });

  it('does not import old roots from app module', () => {
    const appModule = readFileSync(join(srcRoot, 'app.module.ts'), 'utf8');

    expect(appModule).not.toMatch(/from ['"]\.\/(?:admin|blog|minio|wordpress|qqbot)/);
    expect(appModule).not.toMatch(/from ['"]@\/(?:admin|blog|minio|wordpress|qqbot)\//);
  });
});
  • Step 2: Run the RED test

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/architecture-convergence.spec.ts

Expected: FAIL. The failure must mention existing old roots and forbidden imports.

  • Step 3: Commit the RED gate

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add test/refactor-v3/architecture-convergence.spec.ts
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "test: 增加架构收敛结构门禁"

Expected: commit succeeds with the failing test. The failure is intentional and will turn green after migration.

Task 2: Admin/Auth/Platform Config Migration And Slimming

Files:

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\auth\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\user\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\role\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\menu\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\dept\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\component\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\dict\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\notice\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\system-log\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\admin\timezone\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\identity\admin-identity.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\platform-config\admin-platform-config.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\admin\admin-contract.spec.ts

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\admin\**

  • Step 1: Move Admin identity files

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\identity\auth" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\identity\user" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\identity\role" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\identity\menu" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\identity\dept" | Out-Null
git -C $api mv src/admin/auth/* src/modules/admin/identity/auth/
git -C $api mv src/admin/user/* src/modules/admin/identity/user/
git -C $api mv src/admin/role/* src/modules/admin/identity/role/
git -C $api mv src/admin/menu/* src/modules/admin/identity/menu/
git -C $api mv src/admin/dept/* src/modules/admin/identity/dept/
git -C $api mv src/admin/admin.types.ts src/modules/admin/contract/admin.types.ts

Expected: moved files appear under src/modules/admin/identity/** and src/modules/admin/contract/admin.types.ts.

  • Step 2: Move platform config files

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\platform-config\component" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\platform-config\dict" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\platform-config\notice" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\platform-config\system-log" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\admin\platform-config\timezone" | Out-Null
git -C $api mv src/admin/component/* src/modules/admin/platform-config/component/
git -C $api mv src/admin/dict/* src/modules/admin/platform-config/dict/
git -C $api mv src/admin/notice/* src/modules/admin/platform-config/notice/
git -C $api mv src/admin/system-log/* src/modules/admin/platform-config/system-log/
git -C $api mv src/admin/timezone/* src/modules/admin/platform-config/timezone/

Expected: moved files appear under src/modules/admin/platform-config/**.

  • Step 3: Decide and remove Admin example

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
rg -n 'AdminExampleController|admin/example|example' "$api\src" "$api\sql" "$api\test"

Expected: if the only source entry is src/admin/example/admin-example.controller.ts, delete it. If a menu, SQL seed, or test proves it is active, move it to src/modules/admin/platform-config/example/ and add a contract test for the route.

For the delete path, run:

git -C D:\MyFiles\KT\Node\kt-template-online-api rm -r src/admin/example
  • Step 4: Update imports to target Admin paths

Replace imports using these mappings:

@/admin/auth/ -> @/modules/admin/identity/auth/
@/admin/user/ -> @/modules/admin/identity/user/
@/admin/role/ -> @/modules/admin/identity/role/
@/admin/menu/ -> @/modules/admin/identity/menu/
@/admin/dept/ -> @/modules/admin/identity/dept/
@/admin/component/ -> @/modules/admin/platform-config/component/
@/admin/dict/ -> @/modules/admin/platform-config/dict/
@/admin/notice/ -> @/modules/admin/platform-config/notice/
@/admin/system-log/ -> @/modules/admin/platform-config/system-log/
@/admin/timezone/ -> @/modules/admin/platform-config/timezone/
@/admin/admin.types -> @/modules/admin/contract/admin.types

Run a focused check:

rg -n '@\/admin\/' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: no @/admin/ imports remain in API source or tests.

  • Step 5: Rewrite admin module imports

Update:

D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\identity\admin-identity.module.ts
D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\platform-config\admin-platform-config.module.ts

The module files must import controllers, services, entities, and submodules from @/modules/admin/**, not from @/admin/**.

  • Step 6: Update inventory

Append to docs/refactor-v3/architecture-convergence-inventory.md:

| Admin/Auth/Platform Config | `src/admin/example` if no active route evidence; empty old admin subdirectories | auth/user/role/menu/dept/component/dict/notice/system-log/timezone moved into `src/modules/admin/**`; duplicate old imports removed | route paths and public DTO class names kept | `rg '@/admin/' src test` returns no source hits; admin focused Jest passes |
  • Step 7: Verify Admin API domain

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/admin/admin-contract.spec.ts test/admin/auth/admin-password-crypto.service.spec.ts test/admin/admin-menu.service.spec.ts test/admin/dict/dict.service.spec.ts test/admin/notice/admin-notice.controller.spec.ts test/admin/notice/admin-notice.service.spec.ts test/admin/system-log/system-log.controller.spec.ts test/admin/system-log/system-log.service.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck

Expected: PASS.

  • Step 8: Commit Admin API migration

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/admin test docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api add -u src/admin src/modules/admin test
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 收敛Admin与平台配置模块"

Expected: commit succeeds. src/admin may still exist if non-empty from cross-domain imports, but no code should import @/admin/.

Task 3: Blog, WordPress, And Asset Migration And Slimming

Files:

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\blog\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\wordpress\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\minio\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\blog\blog-content.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\wordpress\wordpress-mirror.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\asset\asset.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\blog\blog-module-contract.spec.ts

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\wordpress\wordpress-module-contract.spec.ts

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\asset\asset-module-contract.spec.ts

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\blog\**

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\wordpress\wordpress.service.spec.ts

  • Step 1: Move Blog files into target subfolders

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
New-Item -ItemType Directory -Force -Path "$api\src\modules\blog\contract" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\blog\application" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\blog\infrastructure\persistence" | Out-Null
git -C $api mv src/blog/*controller.ts src/modules/blog/contract/
git -C $api mv src/blog/*dto.ts src/modules/blog/contract/
git -C $api mv src/blog/*service.ts src/modules/blog/application/
git -C $api mv src/blog/*entity.ts src/modules/blog/infrastructure/persistence/
git -C $api mv src/blog/blog.module.ts src/modules/blog/blog-content.legacy-module.ts

Expected: old src/blog has no files after the move.

  • Step 2: Move WordPress files into target subfolders

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
New-Item -ItemType Directory -Force -Path "$api\src\modules\wordpress\contract" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\wordpress\application" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\wordpress\domain" | Out-Null
git -C $api mv src/wordpress/*controller.ts src/modules/wordpress/contract/
git -C $api mv src/wordpress/*dto.ts src/modules/wordpress/contract/
git -C $api mv src/wordpress/*types.ts src/modules/wordpress/domain/
git -C $api mv src/wordpress/*service.ts src/modules/wordpress/application/
git -C $api mv src/wordpress/wordpress.module.ts src/modules/wordpress/wordpress-mirror.legacy-module.ts

Expected: old src/wordpress has no files after the move.

  • Step 3: Move MinIO files into Asset module

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
New-Item -ItemType Directory -Force -Path "$api\src\modules\asset\contract" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\asset\application" | Out-Null
New-Item -ItemType Directory -Force -Path "$api\src\modules\asset\domain" | Out-Null
git -C $api mv src/minio/minio.controller.ts src/modules/asset/contract/asset-minio.controller.ts
git -C $api mv src/minio/minio.dto.ts src/modules/asset/contract/asset-minio.dto.ts
git -C $api mv src/minio/minio.service.ts src/modules/asset/application/asset-minio.service.ts
git -C $api mv src/minio/minio.types.ts src/modules/asset/domain/asset-minio.types.ts
git -C $api mv src/minio/minio.module.ts src/modules/asset/asset-minio.legacy-module.ts

Expected: old src/minio has no files after the move. Public route decorators may remain /minio/*.

  • Step 4: Update imports for Blog/WordPress/Asset

Replace imports using these mappings:

@/blog/ -> @/modules/blog/
@/wordpress/ -> @/modules/wordpress/
@/minio/minio.controller -> @/modules/asset/contract/asset-minio.controller
@/minio/minio.dto -> @/modules/asset/contract/asset-minio.dto
@/minio/minio.service -> @/modules/asset/application/asset-minio.service
@/minio/minio.types -> @/modules/asset/domain/asset-minio.types
@/minio/minio.module -> @/modules/asset/asset-minio.legacy-module

Run:

rg -n '@\/(blog|wordpress|minio)\/' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: no old Blog, WordPress, or MinIO imports remain.

  • Step 5: Collapse legacy module wrappers

Update these module files so they import local target classes directly and do not import the moved *.legacy-module.ts wrappers:

D:\MyFiles\KT\Node\kt-template-online-api\src\modules\blog\blog-content.module.ts
D:\MyFiles\KT\Node\kt-template-online-api\src\modules\wordpress\wordpress-mirror.module.ts
D:\MyFiles\KT\Node\kt-template-online-api\src\modules\asset\asset.module.ts

After each module imports local controllers/services/entities directly, delete:

git -C D:\MyFiles\KT\Node\kt-template-online-api rm src/modules/blog/blog-content.legacy-module.ts
git -C D:\MyFiles\KT\Node\kt-template-online-api rm src/modules/wordpress/wordpress-mirror.legacy-module.ts
git -C D:\MyFiles\KT\Node\kt-template-online-api rm src/modules/asset/asset-minio.legacy-module.ts
  • Step 6: Run slimming scans for Blog/WordPress/Asset

Run:

rg -n 'BlogModule|WordpressModule|MinioClientModule|MinioClientService|MinioUploadFile' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test
rg -n 'blog-content\.legacy|wordpress-mirror\.legacy|asset-minio\.legacy' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: old module wrapper names have no hits. Public class names may remain only when route behavior or tests depend on them.

  • Step 7: Update inventory

Append:

| Blog/WordPress/Asset | old `src/blog`, `src/wordpress`, `src/minio`; legacy module wrappers after local imports replaced | MinIO internal files renamed into Asset module; Blog and WordPress controller/service/entity files moved under target modules | existing route decorators and response DTO behavior | `rg '@/blog/|@/wordpress/|@/minio/' src test` has no hits; Blog/WordPress/Asset focused tests pass |
  • Step 8: Verify Blog/WordPress/Asset

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/blog/blog-module-contract.spec.ts test/modules/wordpress/wordpress-module-contract.spec.ts test/modules/asset/asset-module-contract.spec.ts test/blog/blog-article.service.spec.ts test/blog/blog-term.service.spec.ts test/blog/blog-theme-config.service.spec.ts test/wordpress/wordpress.service.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck

Expected: PASS.

  • Step 9: Commit Blog/WordPress/Asset migration

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/blog src/modules/wordpress src/modules/asset test docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api add -u src/blog src/wordpress src/minio src/modules/blog src/modules/wordpress src/modules/asset test
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 收敛Blog WordPress Asset模块"

Expected: commit succeeds.

Task 4: QQBot Core And NapCat Migration And Slimming

Files:

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\account\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\command\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\config\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\connection\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\dashboard\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\dedupe\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\event\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\message\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\mqtt\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\permission\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\rule\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\send\**

  • Move: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\napcat\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\core\qqbot-core.module.ts

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\core\**

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\**

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\qqbot\**

  • Step 1: Move QQBot core directories

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
$core = "$api\src\modules\qqbot\core"
foreach ($name in @('account','command','config','connection','dashboard','dedupe','event','message','mqtt','permission','rule','send')) {
  New-Item -ItemType Directory -Force -Path "$core\$name" | Out-Null
  git -C $api mv "src/qqbot/$name/*" "src/modules/qqbot/core/$name/"
}
New-Item -ItemType Directory -Force -Path "$core\contract" | Out-Null
New-Item -ItemType Directory -Force -Path "$core\domain" | Out-Null
git -C $api mv src/qqbot/qqbot.types.ts src/modules/qqbot/core/contract/qqbot.types.ts
git -C $api mv src/qqbot/qqbot.constants.ts src/modules/qqbot/core/contract/qqbot.constants.ts
git -C $api mv src/qqbot/qqbot-cooldown.policy.ts src/modules/qqbot/core/domain/qqbot-cooldown.policy.ts

Expected: core files are under src/modules/qqbot/core/**.

  • Step 2: Move NapCat runtime files

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
$napcat = "$api\src\modules\qqbot\napcat"
New-Item -ItemType Directory -Force -Path "$napcat\login" | Out-Null
New-Item -ItemType Directory -Force -Path "$napcat\infrastructure\persistence" | Out-Null
git -C $api mv src/modules/qqbot/core/account/qqbot-napcat-login.service.ts src/modules/qqbot/napcat/login/qqbot-napcat-login.service.ts
git -C $api mv src/modules/qqbot/core/account/qqbot-napcat-watchdog.service.ts src/modules/qqbot/napcat/login/qqbot-napcat-watchdog.service.ts
git -C $api mv src/qqbot/napcat/qqbot-account-napcat.entity.ts src/modules/qqbot/napcat/infrastructure/persistence/qqbot-account-napcat.entity.ts
git -C $api mv src/qqbot/napcat/qqbot-napcat-container.entity.ts src/modules/qqbot/napcat/infrastructure/persistence/qqbot-napcat-container.entity.ts
git -C $api mv src/qqbot/napcat/qqbot-napcat-container.service.ts src/modules/qqbot/napcat/qqbot-napcat-container.service.ts

Expected: NapCat files are under src/modules/qqbot/napcat/**.

  • Step 3: Remove old QQBot module wrapper after providers are local

Update src/modules/qqbot/core/qqbot-core.module.ts so it imports from @/modules/qqbot/core/** and @/modules/qqbot/napcat/**.

Run:

rg -n '@\/qqbot\/' D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\core D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat

Expected: no hits in core or napcat modules.

After all providers are local, delete old wrapper:

git -C D:\MyFiles\KT\Node\kt-template-online-api rm src/qqbot/qqbot.module.ts
  • Step 4: Update source and test imports

Replace:

@/qqbot/account/ -> @/modules/qqbot/core/account/
@/qqbot/command/ -> @/modules/qqbot/core/command/
@/qqbot/config/ -> @/modules/qqbot/core/config/
@/qqbot/connection/ -> @/modules/qqbot/core/connection/
@/qqbot/dashboard/ -> @/modules/qqbot/core/dashboard/
@/qqbot/dedupe/ -> @/modules/qqbot/core/dedupe/
@/qqbot/event/ -> @/modules/qqbot/core/event/
@/qqbot/message/ -> @/modules/qqbot/core/message/
@/qqbot/mqtt/ -> @/modules/qqbot/core/mqtt/
@/qqbot/permission/ -> @/modules/qqbot/core/permission/
@/qqbot/rule/ -> @/modules/qqbot/core/rule/
@/qqbot/send/ -> @/modules/qqbot/core/send/
@/qqbot/napcat/ -> @/modules/qqbot/napcat/
@/qqbot/qqbot.types -> @/modules/qqbot/core/contract/qqbot.types
@/qqbot/qqbot.constants -> @/modules/qqbot/core/contract/qqbot.constants
@/qqbot/qqbot-cooldown.policy -> @/modules/qqbot/core/domain/qqbot-cooldown.policy

Run:

rg -n '@\/qqbot\/' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: only plugin-platform migration leftovers may remain before Task 5; no core or napcat imports should target old roots.

  • Step 5: Run QQBot core and NapCat slimming scans

Run:

rg -n 'QqbotModule|@\/qqbot\/qqbot\.module|qqbot-napcat-login\.service|qqbot-napcat-watchdog\.service' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test
rg -n 'quick-login|password-login|new-device|CaptchaLogin|GetNewDeviceQRCode|PollNewDeviceQR|NewDeviceLogin' D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat

Expected: old QqbotModule has no hits. NapCat login flow terms remain in target module and tests.

  • Step 6: Update inventory

Append:

| QQBot Core/NapCat | old `src/qqbot/qqbot.module.ts`; old core and napcat roots after moves | account/command/config/connection/dashboard/dedupe/event/message/mqtt/permission/rule/send moved into `src/modules/qqbot/core`; NapCat login/container/persistence moved into `src/modules/qqbot/napcat` | route decorators, command parsing, send queue, device persistence, captcha, new-device, and manual QR semantics | core and NapCat focused Jest pass; `rg '@/qqbot/' src/modules/qqbot/core src/modules/qqbot/napcat` has no hits |
  • Step 7: Verify QQBot core and NapCat

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/core/qqbot-core-module-contract.spec.ts test/modules/qqbot/core/qqbot-core-command-contract.spec.ts test/modules/qqbot/core/qqbot-core-command-smoke.spec.ts test/modules/qqbot/core/qqbot-core-send-contract.spec.ts test/modules/qqbot/core/qqbot-core-status-contract.spec.ts test/modules/qqbot/napcat/device-identity.spec.ts test/modules/qqbot/napcat/login-state-machine.spec.ts test/modules/qqbot/napcat/new-device-flow.spec.ts test/qqbot/connection/qqbot-reverse-ws.service.spec.ts test/qqbot/send/qqbot-send.service.spec.ts test/qqbot/send/qqbot-rate-limit.service.spec.ts test/qqbot/command/qqbot-command-parser.service.spec.ts test/qqbot/account/qqbot-account.service.spec.ts test/qqbot/account/qqbot-napcat-login.service.spec.ts test/qqbot/account/qqbot-napcat-watchdog.service.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck

Expected: PASS.

  • Step 8: Commit QQBot core and NapCat migration

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/core src/modules/qqbot/napcat test docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api add -u src/qqbot src/modules/qqbot/core src/modules/qqbot/napcat test
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 收敛QQBot核心与NapCat模块"

Expected: commit succeeds.

Task 5: Plugin Platform And Existing Plugin Slimming

Files:

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugin-platform\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\**

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot\plugin\**

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugin-platform\**

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugins\**

  • Tests: D:\MyFiles\KT\Node\kt-template-online-api\test\qqbot\plugins\**

  • Step 1: Replace old plugin registry imports

Run:

rg -n '@\/qqbot\/plugin|QqbotPluginRegistryService|QqbotEventPluginRegistryService|QqbotIntegrationPlugin' D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: hits exist before this task.

Update target code so:

QqbotIntegrationPlugin imports come from `@/modules/qqbot/core/contract/qqbot.types`.
Plugin registry behavior comes from `@/modules/qqbot/plugin-platform/**`.
No target module imports `@/qqbot/plugin/**`.
  • Step 2: Delete old plugin registry root

After imports are replaced, run:

rg -n '@\/qqbot\/plugin|QqbotPluginRegistryService|QqbotEventPluginRegistryService' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: no hits that require src/qqbot/plugin/**.

Then run:

git -C D:\MyFiles\KT\Node\kt-template-online-api rm -r src/qqbot/plugin
  • Step 3: Scan existing plugins for full-module slimming

Run:

rg -n 'axios|fetch\(|http\.|@\/admin\/|@\/qqbot\/|legacyKeys|bangDream|ff14Market' D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins

Expected:

  • Direct HTTP clients in FF14 Market and FFLogs are absent or replaced by host runtime HTTP SDK.

  • @/admin/ and @/qqbot/ imports are removed.

  • legacyKeys remain only in plugin metadata objects where external compatibility requires them.

  • bangDream and ff14Market legacy strings remain only in compatibility mappings or tests that prove alias behavior.

  • Step 4: Remove plugin internal dead buckets

Create a candidate list from files that contain old-root imports, direct HTTP calls, or legacy aliases:

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
$candidateFiles = @(
  'src/modules/qqbot/plugins/ff14-market/qqbot-ff14-client.service.ts',
  'src/modules/qqbot/plugins/ff14-market/qqbot-ff14-worlds.ts',
  'src/modules/qqbot/plugins/ff14-market/qqbot-ff14-market.plugin.ts',
  'src/modules/qqbot/plugins/fflogs/qqbot-fflogs-client.service.ts',
  'src/modules/qqbot/plugins/fflogs/qqbot-fflogs.plugin.ts',
  'src/modules/qqbot/plugins/repeater/qqbot-repeater.plugin.ts',
  'src/modules/qqbot/plugins/bangdream/src/application/bangdream-renderer.facade.ts',
  'src/modules/qqbot/plugins/bangdream/src/qqbot-bangdream.plugin.ts'
)
foreach ($file in $candidateFiles) {
  $absolute = Join-Path $api $file
  if (Test-Path $absolute) {
    Write-Output "===== $file ====="
    Select-String -Path $absolute -Pattern 'export (class|function|interface|type|const) ' | ForEach-Object { $_.Line.Trim() }
    $stem = [System.IO.Path]::GetFileNameWithoutExtension($file)
    rg -n --fixed-strings $stem "$api\src" "$api\test"
  }
}

Delete a candidate file only when this scan shows no live references outside the file itself and no manifest or test depends on it. Keep the file when a manifest, registry, or test references it, then remove only the old import/direct-call line.

Record each deletion or keep decision in the inventory table.

  • Step 5: Verify plugin platform and plugin behavior

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/plugin-platform/manifest.spec.ts test/modules/qqbot/plugin-platform/cli.spec.ts test/modules/qqbot/plugin-platform/persistence-contract.spec.ts test/modules/qqbot/plugin-platform/plugin-platform-api-contract.spec.ts test/modules/qqbot/plugin-platform/worker-runtime.spec.ts test/modules/qqbot/plugins/plugin-registry-compat.spec.ts test/modules/qqbot/plugins/plugin-platform-migration.spec.ts test/modules/qqbot/plugins/plugin-controller-http-smoke.spec.ts test/qqbot/plugins/ff14-market/qqbot-ff14-worlds.spec.ts test/qqbot/plugins/fflogs/qqbot-fflogs-client.service.spec.ts test/qqbot/plugins/repeater/qqbot-repeater.plugin.spec.ts test/qqbot/plugins/bangdream/manifest/operation-manifest.spec.ts test/qqbot/plugins/bangdream/manifest/command-sql.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck

Expected: PASS.

  • Step 6: Update inventory

Append:

| Plugin Platform/Plugins | old `src/qqbot/plugin`; plugin files with no external or test references | registry behavior moved to plugin platform; plugin interfaces moved to target contracts; direct old-root imports removed | plugin manifest, legacy alias compatibility, worker runtime, host HTTP SDK, operation registry, event behavior | plugin platform focused Jest passes; plugin scan has no `@/admin/` or `@/qqbot/` imports |
  • Step 7: Commit plugin migration

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/plugin-platform src/modules/qqbot/plugins test docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api add -u src/qqbot src/modules/qqbot/plugin-platform src/modules/qqbot/plugins test
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 收敛QQBot插件平台与现有插件"

Expected: commit succeeds.

Task 6: Admin Full-Domain Slimming And Caller Boundaries

Files:

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\system\**

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\blog\**

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\**

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\system\**

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\blog\**

  • Modify: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\**

  • Create: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\modules\status.ts

  • Create: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\modules\actions.tsx

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-inventory.md

  • Test: D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\napcat.spec.ts

  • Step 1: Scan Admin callers and pages

Run:

$admin = 'D:\MyFiles\KT\Vue\kt-template-admin'
rg -n 'deprecated|legacy|兼容|旧|废弃|console\.log' "$admin\apps\web-antdv-next\src\api\system" "$admin\apps\web-antdv-next\src\api\blog" "$admin\apps\web-antdv-next\src\api\qqbot" "$admin\apps\web-antdv-next\src\views\system" "$admin\apps\web-antdv-next\src\views\blog" "$admin\apps\web-antdv-next\src\views\qqbot"
rg -n '登录成功|登录失败|需要验证码|新设备|运行态清理失败|online|offline|enabled|disabled|pending' "$admin\apps\web-antdv-next\src\views" "$admin\apps\web-antdv-next\src\api"

Expected: scan output identifies duplicated state labels and legacy comments before cleanup.

  • Step 2: Create shared QQBot status module

Create apps/web-antdv-next/src/views/qqbot/modules/status.ts:

import type { TagProps } from 'antdv-next';

export const qqbotStatusLabels = {
  disabled: '已禁用',
  enabled: '已启用',
  failed: '失败',
  offline: '离线',
  online: '在线',
  pending: '处理中',
  unknown: '未知',
} as const;

export type QqbotStatusKey = keyof typeof qqbotStatusLabels;

export function getQqbotStatusLabel(status: string | undefined): string {
  if (!status) return qqbotStatusLabels.unknown;
  return qqbotStatusLabels[(status as QqbotStatusKey)] ?? status;
}

export function getQqbotStatusColor(status: string | undefined): TagProps['color'] {
  if (status === 'online' || status === 'enabled') return 'success';
  if (status === 'offline' || status === 'disabled') return 'default';
  if (status === 'failed') return 'error';
  if (status === 'pending') return 'processing';
  return 'default';
}
  • Step 3: Create shared QQBot actions module

Create apps/web-antdv-next/src/views/qqbot/modules/actions.tsx:

import { Button, Popconfirm, Space } from 'antdv-next';
import type { Component } from 'vue';

export interface QqbotActionItem {
  danger?: boolean;
  disabled?: boolean;
  icon?: Component;
  key: string;
  label: string;
  loading?: boolean;
  confirmText?: string;
  onClick: () => void | Promise<void>;
}

export function renderQqbotActions(actions: QqbotActionItem[]) {
  return (
    <Space size="small">
      {actions.map((action) => {
        const button = (
          <Button
            danger={action.danger}
            disabled={action.disabled}
            icon={action.icon ? <action.icon /> : undefined}
            loading={action.loading}
            size="small"
            type="link"
            onClick={action.confirmText ? undefined : action.onClick}
          >
            {action.label}
          </Button>
        );

        if (!action.confirmText) return <span key={action.key}>{button}</span>;

        return (
          <Popconfirm
            key={action.key}
            title={action.confirmText}
            onConfirm={action.onClick}
          >
            {button}
          </Popconfirm>
        );
      })}
    </Space>
  );
}
  • Step 4: Replace duplicate QQBot status/action logic

Update these pages to import getQqbotStatusLabel, getQqbotStatusColor, or renderQqbotActions where they duplicate status tags or action buttons:

apps/web-antdv-next/src/views/qqbot/account/list.tsx
apps/web-antdv-next/src/views/qqbot/command/list.tsx
apps/web-antdv-next/src/views/qqbot/rule/list.tsx
apps/web-antdv-next/src/views/qqbot/message/list.tsx
apps/web-antdv-next/src/views/qqbot/permission/list.tsx
apps/web-antdv-next/src/views/qqbot/plugin/list.tsx
apps/web-antdv-next/src/views/qqbot/sendLog/list.tsx

Run:

rg -n '登录成功|登录失败|需要验证码|新设备二维码|运行态清理失败' D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot

Expected: NapCat-specific progress labels remain in api/qqbot/napcat.ts and NapCat UI only; other QQBot pages do not copy these strings.

  • Step 5: Slim System and Blog/Admin pages

Run reference scans:

$admin = 'D:\MyFiles\KT\Vue\kt-template-admin'
rg -n 'ktTableDemo|clipboard|demo|legacy|deprecated|兼容旧|旧路由' "$admin\apps\web-antdv-next\src\views\system" "$admin\apps\web-antdv-next\src\views\blog" "$admin\apps\web-antdv-next\src\api\system" "$admin\apps\web-antdv-next\src\api\blog"
rg -n 'views/system/ktTableDemo|system/ktTableDemo|ktTableDemo' "$admin\apps\web-antdv-next\src\router" "$admin\apps\web-antdv-next\src\views" "$admin\apps\web-antdv-next\src\api"

Expected: if views/system/ktTableDemo has no menu/route/test entry, delete it. If a route or menu entry proves it is active, keep it and record the evidence.

Delete inactive demo files only after the scan proves no active entry:

git -C D:\MyFiles\KT\Vue\kt-template-admin rm -r apps/web-antdv-next/src/views/system/ktTableDemo
  • Step 6: Keep NapCat helper tests green

Extend apps/web-antdv-next/src/api/qqbot/napcat.spec.ts so it also asserts shared progress labels remain centralized:

it('keeps new-device labels centralized in the NapCat caller helpers', () => {
  expect(NAPCAT_LOGIN_PROGRESS_LABELS['new-device-required']).toBe(
    '需要新设备验证二维码',
  );
  expect(NAPCAT_LOGIN_PROGRESS_LABELS['new-device-scanned']).toBe(
    '新设备二维码已扫码',
  );
  expect(NAPCAT_LOGIN_PROGRESS_LABELS['new-device-confirming']).toBe(
    '新设备确认中',
  );
});
  • Step 7: Verify Admin

Run:

pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin exec vitest run apps/web-antdv-next/src/api/qqbot/napcat.spec.ts
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck

Expected: PASS.

  • Step 8: Update inventory

Append to the API inventory document:

| Admin UI | inactive demo pages and no-entry components proven by `rg`; duplicated status/action helpers | QQBot status/action rendering centralized under `views/qqbot/modules`; repeated NapCat progress labels kept in caller helper | System, Blog/WordPress/Asset, QQBot, Plugin, and NapCat visible behavior | Admin Vitest helper test and typecheck pass |
  • Step 9: Commit Admin changes and API inventory

Run:

git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api apps/web-antdv-next/src/views
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "refactor: 收敛Admin全域管理边界"
git -C D:\MyFiles\KT\Node\kt-template-online-api add docs/refactor-v3/architecture-convergence-inventory.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "docs: 记录Admin全域瘦身证据"

Expected: two commits succeed, one per repo.

Task 7: Final Legacy Root Deletion And Green Structure Gate

Files:

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\admin

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\blog

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\minio

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\wordpress

  • Delete: D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot

  • Modify: D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\architecture-convergence-verification.md

  • Modify: D:\MyFiles\KT\TASKS.md

  • Step 1: Prove no old imports remain

Run:

rg -n '@\/(admin|blog|minio|wordpress|qqbot)\/' D:\MyFiles\KT\Node\kt-template-online-api\src D:\MyFiles\KT\Node\kt-template-online-api\test

Expected: no hits.

  • Step 2: Delete remaining empty old roots

Run:

$api = 'D:\MyFiles\KT\Node\kt-template-online-api'
foreach ($root in @('src/admin','src/blog','src/minio','src/wordpress','src/qqbot')) {
  $path = Join-Path $api $root
  if (Test-Path $path) {
    git -C $api rm -r $root
  }
}

Expected: any remaining old root path is removed from Git.

  • Step 3: Run the structure gate green

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/architecture-convergence.spec.ts

Expected: PASS.

  • Step 4: Run final API verification

Run:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand

Expected: PASS.

  • Step 5: Run final Admin verification

Run:

pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin exec vitest run apps/web-antdv-next/src/api/qqbot/napcat.spec.ts
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck

Expected: PASS.

  • Step 6: Run local behavior smoke

Run API smoke using the existing bounded script:

pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck

Then start or reuse the local API only when a real interface smoke is needed. Required smoke evidence:

GET /health/runtime
Admin login and menu load
Blog public list/detail
Asset upload/download/remove through existing MinIO routes
QQBot command test
Plugin validate/install-local/enable/health
NapCat simulated login state machine

Expected: every smoke either passes or records a concrete blocker and stable next action. Do not call the work complete with a missing smoke.

  • Step 7: Write final verification document

Create docs/refactor-v3/architecture-convergence-verification.md:

# Architecture Convergence Verification

## Structure

- API old roots: removed.
- Forbidden imports from `src/modules/**` to old roots: zero.
- `src/app.module.ts`: imports target modules only.

## API Verification

- Structure gate: pass.
- Typecheck: pass.
- Jest: pass.
- Local smoke: pass with recorded command evidence.

## Admin Verification

- NapCat helper Vitest: pass.
- Typecheck: pass.
- Page smoke: pass with recorded routes.

## Review

- KT global review: pass.
- KT global review: pass.
  • Step 8: Update TASKS

Update D:\MyFiles\KT\TASKS.md with a short record:

### 2026-06-15API/Admin 第三期架构收敛完成

- 范围:`Node/kt-template-online-api`、`Vue/kt-template-admin`、`TASKS.md`。
- 关键词:旧根删除、`src/modules/**` 强门禁、全模块瘦身、Admin 全域边界、结构测试、API/Admin 本地验证。
- 验证:记录结构 gate、API typecheck/Jest、Admin Vitest/typecheck、local smoke、KT global review 的最终结果。
  • Step 9: Run review gates

Run:

pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run global-review -- --contentScanMode changed --includeContentScan true

Expected: findings=[].

Use KT workflow KT global review before declaring implementation complete.

  • Step 10: Commit final verification

Run:

git -C D:\MyFiles\KT\Node\kt-template-online-api add src test docs/refactor-v3/architecture-convergence-inventory.md docs/refactor-v3/architecture-convergence-verification.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "test: 完成架构收敛验证闭环"
git -C D:\MyFiles\KT add TASKS.md
git -C D:\MyFiles\KT commit -m "docs: 记录架构收敛闭环"

Expected: commits succeed and worktrees remain clean.

Final Completion Gate

Before reporting the goal complete, run:

git -C D:\MyFiles\KT\Node\kt-template-online-api status --short --branch
git -C D:\MyFiles\KT\Vue\kt-template-admin status --short --branch
git -C D:\MyFiles\KT status --short --branch
rg --files D:\MyFiles\KT\Node\kt-template-online-api\src\admin D:\MyFiles\KT\Node\kt-template-online-api\src\blog D:\MyFiles\KT\Node\kt-template-online-api\src\minio D:\MyFiles\KT\Node\kt-template-online-api\src\wordpress D:\MyFiles\KT\Node\kt-template-online-api\src\qqbot
rg -n '@\/(admin|blog|minio|wordpress|qqbot)\/' D:\MyFiles\KT\Node\kt-template-online-api\src\modules
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/architecture-convergence.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
pnpm --dir D:\MyFiles\KT\mcp\ktWorkflow run global-review -- --contentScanMode changed --includeContentScan true

Expected:

API/Admin/root status clean.
Old root scan returns no files.
Forbidden import scan returns no hits.
Structure gate passes.
API typecheck passes.
Admin typecheck passes.
global-review findings=[].

Plan Self-Review

Spec Coverage

Spec Requirement Plan Coverage
Clean worktree before work Task 0
API old roots deleted Tasks 1, 2, 3, 4, 5, 7
src/modules/** forbidden old imports Tasks 1 and 7
Admin/Auth/Platform Config migration and slimming Task 2
Blog/WordPress/Asset migration and slimming Task 3
QQBot Core and NapCat migration and slimming Task 4
Plugin Platform and existing plugin slimming Task 5
Admin full-domain slimming Task 6
Runtime/Common slimming rule Task 0 inventory and Task 7 final scan; module-private utilities discovered during Tasks 2-5 are moved back into domains before commit
Behavior preservation Focused Jest, typecheck, local smoke, Admin Vitest/typecheck
No meaningless backup artifacts Execution Rules and commit scopes
Documentation and TASKS update Tasks 0 and 7
KT global review Task 7

Placeholder Scan

No deferred placeholder work is allowed. Each task names the files to move or modify, the commands to run, and the expected result. Discovery commands have bounded decision rules: delete only with no-reference evidence, keep only with route/menu/test/manifest evidence.

Type And Path Consistency

  • API paths use D:\MyFiles\KT\Node\kt-template-online-api.
  • Admin paths use D:\MyFiles\KT\Vue\kt-template-admin.
  • Old API roots always mean src/admin, src/blog, src/minio, src/wordpress, and src/qqbot.
  • Target API root is always src/modules/**.
  • Admin route/page smoke remains under apps/web-antdv-next/src/**.