Add conventions, ADR, CI workflows, and prompts
New directories: - .claude/rules/: Coding conventions (Flyway, Java, Vue, memory) - .claude/skills/fix-gate/, gen-migration/: Specialized skills - .github/workflows/: CI/CD pipelines - docs/: Architecture documentation and ADRs - prompts/: System prompts and evaluation templates - scripts/ci/: CI linting scripts - spec/phase/TEMPLATE.md: Phase Brief template Files added: - Flyway, Java, Vue conventions for code generation - Memory management decisions and session tracking - CI workflow with shell/yaml linting - Architecture decision records (ADR-001: tech stack) - Backend/Frontend builder system prompts - Phase execution templates and evaluations Total: 19 files, 1118 insertions Co-authored-by: Qwen-Coder <[email protected]>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
---
|
||||
paths:
|
||||
- "ljwx-platform-app/src/main/resources/db/migration/**/*.sql"
|
||||
---
|
||||
|
||||
# Flyway 迁移规范 — LJWX Platform
|
||||
|
||||
## 文件命名
|
||||
|
||||
格式:`V{phase}_{seq}__{description}.sql`
|
||||
|
||||
示例:
|
||||
- `V1_1__create_sys_user.sql`
|
||||
- `V6_1__seed_admin_user.sql`
|
||||
- `V15_2__add_notification_index.sql`
|
||||
|
||||
迁移文件路径:`ljwx-platform-app/src/main/resources/db/migration/`
|
||||
|
||||
## DDL 硬规则
|
||||
|
||||
1. **禁止** `IF NOT EXISTS`(Flyway 负责版本管理,不需要幂等 DDL)
|
||||
2. 业务表(非 Quartz)**必须**含 7 列审计字段,均 NOT NULL + 有 DEFAULT:
|
||||
|
||||
```sql
|
||||
CREATE TABLE sys_example (
|
||||
id BIGINT NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
-- 7 个审计字段,业务表必须全部包含
|
||||
tenant_id BIGINT NOT NULL DEFAULT 0,
|
||||
created_by BIGINT NOT NULL DEFAULT 0,
|
||||
created_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_by BIGINT NOT NULL DEFAULT 0,
|
||||
updated_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted TINYINT NOT NULL DEFAULT 0,
|
||||
version INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
```
|
||||
|
||||
3. Quartz 系统表(`QRTZ_*`)**不得**含审计字段
|
||||
4. **禁止** `DROP TABLE`(除非 ADR 明确批准)
|
||||
5. **禁止** `TRUNCATE`
|
||||
|
||||
## 已应用迁移不可修改
|
||||
|
||||
一旦 Flyway 迁移文件被 apply,**永远不能修改**。
|
||||
追加变更需创建新的迁移文件(更高版本号)。
|
||||
|
||||
## 种子数据
|
||||
|
||||
- 管理员初始密码 `Admin@12345`,使用 BCrypt cost=10 哈希
|
||||
- 写在 V006 种子 SQL 中
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
paths:
|
||||
- "ljwx-platform-*/src/**/*.java"
|
||||
- "ljwx-platform-*/src/**/*.xml"
|
||||
---
|
||||
|
||||
# Java 编码规范 — LJWX Platform
|
||||
|
||||
## 模块 DAG 依赖(硬规则)
|
||||
|
||||
```
|
||||
core ← {security, data} ← web ← app
|
||||
```
|
||||
|
||||
- `ljwx-platform-data/` **禁止** import `com.ljwx.platform.security.*`
|
||||
- `ljwx-platform-security/` **禁止** import `com.ljwx.platform.data.*`
|
||||
- `ljwx-platform-core/` **禁止** import 任何其他 `com.ljwx.platform.*` 模块
|
||||
- `ljwx-platform-web/` 通过 security 间接依赖,**禁止**直接 import data
|
||||
|
||||
## 实体 / Mapper
|
||||
|
||||
- 所有业务实体必须继承 `BaseEntity`(含 7 列审计字段)
|
||||
- 审计字段:`tenant_id`, `created_by`, `created_time`, `updated_by`, `updated_time`, `deleted`, `version`
|
||||
- 使用 MyBatis-Plus `@TableName` 注解
|
||||
|
||||
## Service
|
||||
|
||||
- `tenant_id` 由 `TenantLineInterceptor` 自动注入,**禁止** `setTenantId()`
|
||||
- 写操作加 `@Transactional`
|
||||
|
||||
## Controller
|
||||
|
||||
正确写法:
|
||||
```java
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAuthority('resource:action')")
|
||||
public Result<PageResult<UserVO>> list(UserQueryDTO query) { ... }
|
||||
```
|
||||
|
||||
- 每个 `@(Get|Post|Put|Delete|Patch)Mapping` 方法上方 **必须** 有 `@PreAuthorize`
|
||||
- 格式:`hasAuthority('resource:action')`,**禁止** `hasRole(...)` 或 `ROLE_` 前缀
|
||||
- 例外:路径含 `/auth/login` 或 `/auth/refresh` 的端点
|
||||
|
||||
## DTO / Request / Response
|
||||
|
||||
- **禁止** 出现 `tenantId` 或 `tenant_id` 字段
|
||||
- 字段用 `@NotNull`、`@NotBlank`、`@Size` 等 Bean Validation 注解
|
||||
- 命名:`XxxCreateDTO`、`XxxUpdateDTO`、`XxxQueryDTO`、`XxxVO`
|
||||
|
||||
## POM
|
||||
|
||||
- **禁止** `${latest.version}` 占位符
|
||||
- 所有版本号必须硬编码数字
|
||||
- 版本以 CLAUDE.md "版本锁定" 表为唯一来源
|
||||
|
||||
## 安全规范
|
||||
|
||||
- 密码字段日志输出 → `***`
|
||||
- 手机号中间四位 → `*`
|
||||
- 身份证中间段 → `*`
|
||||
- BCrypt cost=10:`new BCryptPasswordEncoder(10)`
|
||||
@@ -0,0 +1,45 @@
|
||||
# LJWX Platform — 关键决策记录
|
||||
|
||||
本文件记录已做出的架构决策,避免重复讨论。
|
||||
|
||||
## 2026-02-23: macOS 兼容性 — 使用 ERE 而非 PCRE
|
||||
|
||||
所有 shell 脚本使用 POSIX ERE(`grep -E`),禁止 `grep -P`(GNU/PCRE-only)。
|
||||
理由:macOS 自带 BSD grep 不支持 `-P`。
|
||||
|
||||
具体替换规则:
|
||||
- `\s` → `[[:space:]]`
|
||||
- `\S` → `[^[:space:]]`
|
||||
- `\|`(PCRE 交替) → `|`(ERE 交替)
|
||||
- `\K`(lookbehind)→ `sed -n 's/.../\1/p'`
|
||||
- `(?!...)`(负向前瞻)→ 两步 grep:先匹配,再排除
|
||||
|
||||
## 2026-02-23: Flyway 规范 — 禁止 IF NOT EXISTS
|
||||
|
||||
Flyway 通过版本号管理迁移,不需要幂等 DDL。
|
||||
`CREATE TABLE IF NOT EXISTS` 是反模式,已通过 post-edit-check.sh hook 拦截。
|
||||
|
||||
## 2026-02-23: Vue Router v5 API
|
||||
|
||||
项目使用 vue-router `~5.0.2`。v5 将 unplugin-vue-router 功能内置。
|
||||
所有代码必须用 Composition API(`useRoute()`/`useRouter()`),禁止 Options API 路由守卫。
|
||||
`onBeforeRouteLeave` 和 `onBeforeRouteUpdate` 在 v5 中合法。
|
||||
|
||||
## 2026-02-23: Hook 机制
|
||||
|
||||
Claude Code hooks 仅支持三种事件:`PreToolUse`、`PostToolUse`、`Stop`。
|
||||
`SessionStart` 不是有效事件类型。
|
||||
PreToolUse → pre-edit-guard.sh(路径级阻断)
|
||||
PostToolUse → post-edit-check.sh(内容级检查)
|
||||
Stop → stop-gate.sh(Phase 完成校验)
|
||||
|
||||
## 2026-02-23: .env.example 处理
|
||||
|
||||
Claude Code 系统沙箱阻止写入所有 `.env.*` 文件(含 `.env.example`)。
|
||||
解决方案:`stop-gate.sh` 跳过 `.env*` 文件的 scope 检查;用户手动创建该文件。
|
||||
|
||||
## 2026-02-23: settings.json 权限策略
|
||||
|
||||
使用 `"defaultMode": "dontAsk"` 配合精细化 allow/deny 列表。
|
||||
`sandbox.enabled: true` 提供额外的系统级保护。
|
||||
代理类型权限用 `Task(backend-builder)` 格式。
|
||||
@@ -0,0 +1,54 @@
|
||||
# LJWX Platform — 项目档案
|
||||
|
||||
本文件由 Claude Code 自动维护,记录不变的项目事实。
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 层 | 技术 | 版本 |
|
||||
|---|------|------|
|
||||
| 后端语言 | Java | 21 |
|
||||
| 框架 | Spring Boot | 3.5.11 |
|
||||
| ORM | MyBatis-Plus | 3.0.5 |
|
||||
| 数据库 | PostgreSQL | 16.12 |
|
||||
| 迁移 | Flyway | 由 Spring Boot BOM 管理 |
|
||||
| 前端框架 | Vue | ~3.5.28 |
|
||||
| 路由 | Vue Router | ~5.0.2 |
|
||||
| 状态管理 | Pinia | ~3.0.4 |
|
||||
| UI 组件 | Element Plus | ~2.13.2 |
|
||||
| 包管理 | pnpm | 10.30.1 |
|
||||
| 构建 | Vite | ~7.3.1 |
|
||||
| 类型 | TypeScript | ~5.9.3 |
|
||||
|
||||
## 模块结构
|
||||
|
||||
```
|
||||
ljwx-platform/
|
||||
├── ljwx-platform-core/ # 基础类,无外部依赖
|
||||
├── ljwx-platform-security/ # 认证授权,依赖 core
|
||||
├── ljwx-platform-data/ # 数据访问,依赖 core(不依赖 security)
|
||||
├── ljwx-platform-web/ # Web 层,依赖 security + data
|
||||
├── ljwx-platform-app/ # 启动模块,依赖 web
|
||||
├── ljwx-platform-admin/ # Vue 3 管理后台
|
||||
├── ljwx-platform-mobile/ # uni-app 移动端
|
||||
└── ljwx-platform-screen/ # 数据大屏
|
||||
```
|
||||
|
||||
## 多租户策略
|
||||
|
||||
- 应用层隔离:每张业务表含 `tenant_id` 列
|
||||
- TenantLineInterceptor 自动注入 tenant_id(从 JWT claim 提取)
|
||||
- DTO / 请求参数**禁止**传 tenantId
|
||||
- SecurityContext 是 tenantId 的唯一来源
|
||||
|
||||
## 关键配置
|
||||
|
||||
- 后端编译:`mvn clean compile -f pom.xml -q`
|
||||
- 前端类型检查:`pnpm run type-check`(在 ljwx-platform-admin/)
|
||||
- Gate 检查:`bash scripts/gates/gate-all.sh <phase-number>`
|
||||
- 预检:`bash scripts/preflight/preflight-check.sh`
|
||||
|
||||
## Phase 系统
|
||||
|
||||
- Phase 0–19(当前规划)
|
||||
- 每个 Phase 的说明在 `spec/phase/phase-NN.md`
|
||||
- 完成记录写入 `PHASE_MANIFEST.txt`
|
||||
@@ -0,0 +1,44 @@
|
||||
# LJWX Platform — 会话日志
|
||||
|
||||
本文件由 Claude Code 在每次会话结束时更新,记录已完成的工作。
|
||||
|
||||
## 2026-02-23: 基础设施建设(Session 1-2)
|
||||
|
||||
### 完成内容
|
||||
- 修复所有 gate 脚本(gate-nfr.sh、gate-contract.sh)的 PCRE 兼容性问题
|
||||
- 创建 Phase 0 骨架文件:pom.xml、pnpm-workspace.yaml、package.json、.npmrc、
|
||||
.nvmrc、docker-compose.yml、.gitignore、.editorconfig、.mvn/wrapper/、
|
||||
scripts/tools/export-openapi.sh、scripts/acceptance/smoke-test.sh
|
||||
- 修复 pre-edit-guard.sh(shebang、.env.example 白名单)
|
||||
- 修复 stop-gate.sh(.env* 跳过逻辑)
|
||||
- 修复 preflight-check.sh(8 处 PCRE → ERE 转换、J3/K9 逻辑修正)
|
||||
- 为三个 agent 文件添加 permissionMode 字段
|
||||
- 在 CLAUDE.md 第 3 条添加 "(audit fields)" 英文关键词
|
||||
|
||||
### 当前 Phase 状态
|
||||
Phase 0 骨架文件已创建,PHASE_MANIFEST.txt 已写入 PASSED。
|
||||
下一步:运行 `/preflight` 确认全部通过,然后执行 `/phase-exec 1`。
|
||||
|
||||
### 挂起事项
|
||||
- `.env.example` 需用户手动创建(沙箱限制)
|
||||
- preflight Section I 的版本号警告(WARN,非 FAIL):spec/01-constraints.md 中
|
||||
版本号格式与提取 pattern 不匹配,需酌情更新 spec 文件
|
||||
|
||||
## 2026-02-23: AI-Native GitOps 体系建设(Session 3)
|
||||
|
||||
### 完成内容
|
||||
- 创建 .claude/rules/ 条件上下文规则文件:
|
||||
- java-conventions.md(paths: *.java)
|
||||
- vue-conventions.md(paths: *.vue, *.ts)
|
||||
- flyway-rules.md(paths: */migration/*.sql)
|
||||
- memory-profile.md(全局)
|
||||
- memory-decisions.md(全局)
|
||||
- memory-sessions.md(全局,即本文件)
|
||||
- 更新 .claude/agents/ 文件(清理无效字段)
|
||||
- 添加新技能:fix-gate、gen-migration
|
||||
- 创建 docs/ 文档结构
|
||||
- 创建 spec/phase/TEMPLATE.md
|
||||
- 创建 scripts/ci/ 和 .github/workflows/
|
||||
|
||||
### 下一步
|
||||
确认 preflight 全绿,执行 Phase 1。
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
paths:
|
||||
- "ljwx-platform-admin/**/*.vue"
|
||||
- "ljwx-platform-admin/**/*.ts"
|
||||
- "ljwx-platform-admin/**/*.tsx"
|
||||
- "ljwx-platform-screen/**/*.vue"
|
||||
- "ljwx-platform-mobile/**/*.vue"
|
||||
---
|
||||
|
||||
# Vue 3 / TypeScript 规范 — LJWX Platform
|
||||
|
||||
## TypeScript 硬规则
|
||||
|
||||
- **禁止** `: any`、`as any`、`<any>`
|
||||
- `tsconfig.json` 必须 `"strict": true`
|
||||
- 所有 props、emits、ref 必须有明确类型
|
||||
|
||||
## 组件写法
|
||||
|
||||
正确:
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import type { UserVO } from '@ljwx/shared'
|
||||
const users = ref<UserVO[]>([])
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
// scoped styles
|
||||
</style>
|
||||
```
|
||||
|
||||
- 只用 `<script setup lang="ts">` 语法糖
|
||||
- **禁止** Options API、`defineComponent()`
|
||||
- 样式必须 `<style scoped lang="scss">`
|
||||
|
||||
## Vue Router v5 API(重要)
|
||||
|
||||
```typescript
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
// Composition API:
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
// 路由守卫(v5 合法写法):
|
||||
onBeforeRouteLeave((to, from) => { ... })
|
||||
onBeforeRouteUpdate((to, from) => { ... })
|
||||
```
|
||||
|
||||
- **禁止** Options API 路由守卫(`beforeRouteLeave` / `beforeRouteUpdate` 写在组件选项里)
|
||||
- **禁止** v4 专属的 `useLink`(v5 已内置)
|
||||
- 所有路由视图必须懒加载:`component: () => import('...')`
|
||||
- 路由文件:手动定义,不使用文件系统路由
|
||||
|
||||
## API 调用
|
||||
|
||||
```typescript
|
||||
import request from '@/api/request'
|
||||
// 返回类型从 @ljwx/shared 引入
|
||||
```
|
||||
|
||||
- API 调用只通过 `src/api/*.ts` 模块,**禁止**在组件内直接 fetch / axios
|
||||
- **禁止** `VITE_API_BASE_URL`、`VITE_BASE_API` 等变量,只用 `VITE_APP_BASE_API`
|
||||
|
||||
## Pinia Store
|
||||
|
||||
```typescript
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const token = ref<string>('')
|
||||
return { token }
|
||||
})
|
||||
```
|
||||
|
||||
- 使用 setup function 语法,禁止 options 语法
|
||||
- Store 文件放 `src/stores/`
|
||||
|
||||
## package.json 依赖版本
|
||||
|
||||
- 所有 `dependencies` / `devDependencies` 只用 `~`(tilde patch)
|
||||
- **禁止** `^`(caret)
|
||||
- 版本号以 CLAUDE.md "版本锁定" 表为唯一来源
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: fix-gate
|
||||
description: Fix all gate failures for a phase. Reads gate output, fixes each violation, re-runs gate until all checks pass. Use when gate-all.sh reports FAILs.
|
||||
argument-hint: "[phase-number]"
|
||||
---
|
||||
|
||||
# 修复 Gate 失败
|
||||
|
||||
修复 Phase $ARGUMENTS 的所有 gate 失败项。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. 运行 gate 获取失败列表:
|
||||
```bash
|
||||
bash scripts/gates/gate-all.sh $ARGUMENTS
|
||||
```
|
||||
|
||||
2. 对每条 `FAIL` 输出,按以下流程处理:
|
||||
|
||||
**[no-preauthorize]** — Controller 缺少 @PreAuthorize:
|
||||
- 读取对应的 Controller 文件
|
||||
- 在每个 @*Mapping 上方添加 `@PreAuthorize("hasAuthority('resource:action')")`
|
||||
- login/refresh 端点除外
|
||||
|
||||
**[no-caret]** — package.json 使用了 `^`:
|
||||
- 将所有 `"^x.y.z"` 改为 `"~x.y.z"`
|
||||
|
||||
**[dto-no-tenant-id]** — DTO 含 tenantId 字段:
|
||||
- 删除该字段;在 Service 层从 SecurityContext 提取
|
||||
|
||||
**[no-any]** — TypeScript 使用了 `any`:
|
||||
- 替换为正确的类型定义;从 @ljwx/shared 导入共享类型
|
||||
|
||||
**[no-if-not-exists]** — Flyway SQL 含 IF NOT EXISTS:
|
||||
- 删除 `IF NOT EXISTS` 关键词(Flyway 通过版本号保证幂等性)
|
||||
|
||||
**[wrong-env-var]** — 错误的环境变量名:
|
||||
- 替换为 `VITE_APP_BASE_API`
|
||||
|
||||
**[dag-violation]** — 模块 DAG 违规:
|
||||
- 检查 import 语句,移除跨层引用
|
||||
- 如需共享,将类移至 core 模块
|
||||
|
||||
**[audit-columns]** — SQL 缺少审计字段:
|
||||
- 添加 7 列:tenant_id, created_by, created_time, updated_by, updated_time, deleted, version
|
||||
|
||||
3. 每修复一类问题后,重新运行对应的编译/类型检查:
|
||||
- Java 文件修改后:`mvn clean compile -f pom.xml -q`
|
||||
- TS/Vue 文件修改后:`pnpm run type-check`(在 ljwx-platform-admin/)
|
||||
|
||||
4. 所有问题修复后,重新运行完整 gate:
|
||||
```bash
|
||||
bash scripts/gates/gate-all.sh $ARGUMENTS
|
||||
```
|
||||
|
||||
5. 重复步骤 2-4,直到 gate 输出全部 `PASS`。
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: gen-migration
|
||||
description: Generate a Flyway SQL migration file following LJWX project conventions. Use when adding new database tables or schema changes.
|
||||
argument-hint: "[phase-number] [description]"
|
||||
---
|
||||
|
||||
# 生成 Flyway 迁移文件
|
||||
|
||||
为 Phase $ARGUMENTS 生成符合项目规范的 Flyway 迁移 SQL 文件。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. 查看现有迁移文件,确定版本号:
|
||||
```bash
|
||||
ls ljwx-platform-app/src/main/resources/db/migration/
|
||||
```
|
||||
|
||||
2. 确定新文件名:
|
||||
- 格式:`V{phase}_{seq}__{description}.sql`
|
||||
- 示例:`V15_1__create_notification_table.sql`
|
||||
- seq 从当前 phase 最大序号 +1 开始
|
||||
|
||||
3. 生成 SQL 文件,遵循以下规则:
|
||||
|
||||
**业务表模板(必须含 7 列审计字段)**:
|
||||
```sql
|
||||
CREATE TABLE t_example (
|
||||
id BIGINT NOT NULL COMMENT '主键',
|
||||
name VARCHAR(100) NOT NULL COMMENT '名称',
|
||||
-- 7 个审计字段 — 业务表必须全部包含
|
||||
tenant_id BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID',
|
||||
created_by BIGINT NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
created_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
updated_by BIGINT NOT NULL DEFAULT 0 COMMENT '更新人',
|
||||
updated_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0:正常,1:删除)',
|
||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||
PRIMARY KEY (id),
|
||||
INDEX idx_tenant_id (tenant_id)
|
||||
) COMMENT = '示例表';
|
||||
```
|
||||
|
||||
**硬规则**:
|
||||
- 禁止 `IF NOT EXISTS`
|
||||
- 禁止 `DROP TABLE`(除非有 ADR 批准)
|
||||
- 禁止修改已应用的迁移文件
|
||||
- Quartz 系统表(`QRTZ_*`)不含审计字段
|
||||
|
||||
4. 验证迁移文件创建后后端仍可编译:
|
||||
```bash
|
||||
mvn clean compile -f pom.xml -q
|
||||
```
|
||||
|
||||
5. 如果是 Quartz 相关表,参考 Spring Boot Quartz 官方 SQL schema,不添加审计字段。
|
||||
@@ -0,0 +1,65 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Shell script syntax check
|
||||
run: bash scripts/ci/lint-shell.sh
|
||||
|
||||
- name: YAML validation
|
||||
run: |
|
||||
pip install pyyaml --quiet
|
||||
bash scripts/ci/lint-yaml.sh
|
||||
|
||||
backend:
|
||||
name: Backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
cache: 'maven'
|
||||
|
||||
- name: Backend compile
|
||||
run: mvn clean compile -f pom.xml -q
|
||||
|
||||
- name: Backend test
|
||||
run: mvn test -f pom.xml -q
|
||||
|
||||
frontend:
|
||||
name: Frontend
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: '10.30.1'
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd ljwx-platform-admin && pnpm install --frozen-lockfile
|
||||
|
||||
- name: Type check
|
||||
run: cd ljwx-platform-admin && pnpm run type-check
|
||||
|
||||
- name: Lint
|
||||
run: cd ljwx-platform-admin && pnpm run lint
|
||||
@@ -0,0 +1,80 @@
|
||||
name: Prompt Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'CLAUDE.md'
|
||||
- '.claude/rules/**'
|
||||
- '.claude/skills/**'
|
||||
- '.claude/agents/**'
|
||||
- 'prompts/**'
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate AI Assets
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Shell script syntax check
|
||||
run: bash scripts/ci/lint-shell.sh
|
||||
|
||||
- name: YAML validation
|
||||
run: |
|
||||
pip install pyyaml --quiet
|
||||
bash scripts/ci/lint-yaml.sh
|
||||
|
||||
- name: CLAUDE.md line count check
|
||||
run: |
|
||||
LINES=$(wc -l < CLAUDE.md)
|
||||
echo "CLAUDE.md: $LINES lines"
|
||||
if [ "$LINES" -gt 200 ]; then
|
||||
echo "::warning file=CLAUDE.md::CLAUDE.md exceeds 200 lines ($LINES). Consider moving detail to spec/ files."
|
||||
fi
|
||||
|
||||
- name: Rules files frontmatter check
|
||||
run: |
|
||||
ERRORS=0
|
||||
while IFS= read -r -d '' RULE_FILE; do
|
||||
REL="${RULE_FILE#"$PWD"/}"
|
||||
FIRST=$(head -1 "$RULE_FILE")
|
||||
if [ "$FIRST" = "---" ]; then
|
||||
echo " [OK] $REL has frontmatter"
|
||||
else
|
||||
echo " [INFO] $REL has no frontmatter (loads globally)"
|
||||
fi
|
||||
done < <(find .claude/rules -type f -name "*.md" -print0 2>/dev/null)
|
||||
|
||||
- name: Agent files required fields check
|
||||
run: |
|
||||
ERRORS=0
|
||||
for AGENT_FILE in .claude/agents/*.md; do
|
||||
[ -f "$AGENT_FILE" ] || continue
|
||||
REL="$AGENT_FILE"
|
||||
if ! grep -q '^permissionMode:' "$AGENT_FILE"; then
|
||||
echo " [FAIL] $REL missing permissionMode field"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
else
|
||||
echo " [OK] $REL"
|
||||
fi
|
||||
done
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
echo "Agent validation failed: $ERRORS file(s) missing required fields"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Prompt version bump check
|
||||
run: |
|
||||
CHANGED=$(git diff --name-only origin/${{ github.base_ref }} -- prompts/system/ prompts/templates/ 2>/dev/null || true)
|
||||
for F in $CHANGED; do
|
||||
[ -f "$F" ] || continue
|
||||
OLD_VER=$(git show "origin/${{ github.base_ref }}:$F" 2>/dev/null | grep -m1 '^version:' | sed 's/version:[[:space:]]*//' || echo "none")
|
||||
NEW_VER=$(grep -m1 '^version:' "$F" | sed 's/version:[[:space:]]*//' || echo "none")
|
||||
if [ "$OLD_VER" = "$NEW_VER" ] && [ "$OLD_VER" != "none" ]; then
|
||||
echo "::warning file=$F::Version not bumped (still $OLD_VER). Update 'version:' and add a changelog entry."
|
||||
else
|
||||
echo " Version bump: $OLD_VER -> $NEW_VER in $F"
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,38 @@
|
||||
# ADR-001: 技术栈选型
|
||||
|
||||
## 状态
|
||||
|
||||
已采纳(2026-02-23)
|
||||
|
||||
## 背景
|
||||
|
||||
构建企业级多租户 SaaS 平台,需要:
|
||||
- 强类型安全
|
||||
- 成熟的安全框架
|
||||
- 良好的前端工程化
|
||||
- 简单的数据库迁移管理
|
||||
|
||||
## 决策
|
||||
|
||||
| 层 | 技术选型 | 理由 |
|
||||
|---|---------|------|
|
||||
| 后端 | Spring Boot 3.5 + Java 21 | 成熟生态、强安全框架、LTS |
|
||||
| ORM | MyBatis-Plus | 多租户拦截器支持好 |
|
||||
| 前端 | Vue 3 + Vue Router 5 + Pinia | Composition API、TS 支持完善 |
|
||||
| 数据库 | PostgreSQL 16 | 生产稳定、JSONB 支持 |
|
||||
| 迁移 | Flyway | 显式版本管理,与 Phase 开发模式匹配 |
|
||||
| 前端构建 | Vite 7 + pnpm | 快速 HMR、确定性依赖 |
|
||||
| API 文档 | springdoc-openapi | Spring Boot 3 原生支持 |
|
||||
|
||||
## 后果
|
||||
|
||||
- Java 21 需要对应 JDK(`JAVA_HOME` 指向 21)
|
||||
- pnpm 10 作为包管理器,版本由 `packageManager` 字段锁定
|
||||
- Flyway 迁移文件不可修改(已 apply 的),需新建版本文件追加变更
|
||||
- Vue Router 5 与 v4 API 不完全兼容,需按 v5 文档编写
|
||||
|
||||
## 参考
|
||||
|
||||
- [Spring Boot 3.x 文档](https://docs.spring.io/spring-boot/docs/3.5.x/)
|
||||
- [Vue Router 5 迁移指南](https://router.vuejs.org/guide/migration/v4-to-v5)
|
||||
- [MyBatis-Plus 多租户插件](https://baomidou.com/plugins/tenant/)
|
||||
@@ -0,0 +1,92 @@
|
||||
# LJWX Platform — 架构概览
|
||||
|
||||
## 系统定位
|
||||
|
||||
企业级多租户 SaaS 平台脚手架。支持管理后台(Admin)、移动端(uni-app Mobile)、数据大屏(Screen)三端接入。
|
||||
|
||||
## 后端架构
|
||||
|
||||
### 模块 DAG
|
||||
|
||||
```
|
||||
ljwx-platform-core
|
||||
↑ ↑
|
||||
ljwx-platform-security ljwx-platform-data
|
||||
↑ ↑
|
||||
ljwx-platform-web
|
||||
↑
|
||||
ljwx-platform-app ← Spring Boot 启动入口
|
||||
```
|
||||
|
||||
约束:
|
||||
- `core` 不依赖任何其他模块
|
||||
- `security` 和 `data` 仅依赖 `core`,互不依赖
|
||||
- `web` 依赖 `security` 和 `data`
|
||||
- `app` 是唯一的可运行模块
|
||||
|
||||
### 关键组件
|
||||
|
||||
| 组件 | 职责 |
|
||||
|------|------|
|
||||
| TenantLineInterceptor | MyBatis-Plus 拦截器,自动在所有 SQL 注入 `tenant_id` WHERE 条件 |
|
||||
| SecurityConfig | Spring Security 配置,JWT 过滤链 |
|
||||
| JwtTokenFilter | 解析 JWT,填充 SecurityContext(含 tenantId) |
|
||||
| BaseEntity | 含 7 列审计字段的 MyBatis-Plus 基类 |
|
||||
| Result<T> | 统一 REST 响应包装器 |
|
||||
|
||||
### 多租户策略
|
||||
|
||||
- **方式**:应用层过滤(每张业务表含 `tenant_id` 列)
|
||||
- **注入点**:TenantLineInterceptor 自动读取 SecurityContext 中的 tenantId
|
||||
- **禁止**:Service 层手动 `setTenantId()`;DTO/请求参数携带 tenantId
|
||||
|
||||
## 前端架构
|
||||
|
||||
```
|
||||
src/
|
||||
├── api/ # Axios 封装 + 各模块 API 函数
|
||||
├── components/ # 全局公共组件
|
||||
├── layouts/ # 布局(BasicLayout、BlankLayout)
|
||||
├── router/ # Vue Router 5,手动路由定义
|
||||
│ └── modules/ # 按模块拆分的路由文件
|
||||
├── stores/ # Pinia 状态管理
|
||||
├── views/ # 页面组件(按模块组织)
|
||||
└── types/ # TypeScript 类型定义
|
||||
```
|
||||
|
||||
### 关键约束
|
||||
|
||||
- 只用 `<script setup lang="ts">`,禁止 Options API
|
||||
- Vue Router 5 Composition API(`useRoute()`、`useRouter()`)
|
||||
- 所有 API 调用通过 `src/api/*.ts`,禁止组件内直接 fetch
|
||||
- 环境变量只用 `VITE_APP_BASE_API`
|
||||
|
||||
## 数据库
|
||||
|
||||
- PostgreSQL 16
|
||||
- Flyway 版本化迁移(文件命名:`V{phase}_{seq}__{description}.sql`)
|
||||
- 每张业务表包含 7 列审计字段
|
||||
|
||||
## API 设计
|
||||
|
||||
- REST 风格,统一前缀 `/api/v1/`
|
||||
- 响应体统一用 `Result<T>` 包装
|
||||
- 认证:JWT Bearer Token
|
||||
- 授权:Spring Security `@PreAuthorize("hasAuthority('resource:action')")`
|
||||
- 分页:Spring `Pageable` 参数 + `PageResult<T>` 响应
|
||||
|
||||
## 开发环境
|
||||
|
||||
```bash
|
||||
# 启动数据库
|
||||
docker compose -f docker-compose.yml up -d
|
||||
|
||||
# 后端编译
|
||||
mvn clean compile -f pom.xml -q
|
||||
|
||||
# 前端依赖安装
|
||||
cd ljwx-platform-admin && pnpm install
|
||||
|
||||
# 前端类型检查
|
||||
cd ljwx-platform-admin && pnpm run type-check
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
name: backend-builder-evaluation
|
||||
version: "1.0.0"
|
||||
target_prompt: backend-builder-system-prompt
|
||||
target_prompt_version: "1.0.0"
|
||||
description: "Assertions on the backend builder system prompt completeness"
|
||||
|
||||
assertions:
|
||||
- id: E-BE-01
|
||||
description: "Prompt mentions tenantId isolation"
|
||||
type: contains
|
||||
value: "tenantId"
|
||||
|
||||
- id: E-BE-02
|
||||
description: "Prompt requires @PreAuthorize"
|
||||
type: contains
|
||||
value: "@PreAuthorize"
|
||||
|
||||
- id: E-BE-03
|
||||
description: "Prompt forbids IF NOT EXISTS in Flyway"
|
||||
type: contains
|
||||
value: "IF NOT EXISTS"
|
||||
|
||||
- id: E-BE-04
|
||||
description: "Prompt specifies compile command"
|
||||
type: contains
|
||||
value: "mvn clean compile"
|
||||
|
||||
- id: E-BE-05
|
||||
description: "Prompt specifies entity generation order"
|
||||
type: contains
|
||||
value: "Entity"
|
||||
|
||||
- id: E-BE-06
|
||||
description: "Prompt references TenantLineInterceptor"
|
||||
type: contains
|
||||
value: "TenantLineInterceptor"
|
||||
|
||||
- id: E-BE-07
|
||||
description: "Prompt specifies BCrypt requirement"
|
||||
type: contains
|
||||
value: "BaseEntity"
|
||||
|
||||
- id: E-BE-08
|
||||
description: "Prompt enforces complete output"
|
||||
type: contains
|
||||
value: "完整"
|
||||
|
||||
- id: E-BE-09
|
||||
description: "Prompt covers DAG dependency"
|
||||
type: contains
|
||||
value: "DAG"
|
||||
|
||||
- id: E-BE-10
|
||||
description: "Prompt covers DTO tenantId prohibition"
|
||||
type: contains
|
||||
value: "DTO"
|
||||
@@ -0,0 +1,39 @@
|
||||
name: backend-builder-system-prompt
|
||||
version: "1.0.0"
|
||||
model: claude-sonnet-4-6
|
||||
author: ljwx-team
|
||||
changelog:
|
||||
- version: "1.0.0"
|
||||
date: "2026-02-23"
|
||||
description: "Initial backend builder system prompt"
|
||||
|
||||
system_prompt: |
|
||||
你是 LJWX Platform 的高级 Java 后端工程师,负责生成高质量、符合所有硬规则的代码。
|
||||
技术栈:Spring Boot 3.5 / Java 21 / MyBatis-Plus / PostgreSQL / Flyway。
|
||||
|
||||
## 模块 DAG(严格执行)
|
||||
core ← {security, data} ← web ← app
|
||||
- data 禁止 import security 的任何类
|
||||
- security 禁止 import data 的任何类
|
||||
- core 禁止 import 其他 ljwx 模块
|
||||
|
||||
## 硬规则
|
||||
1. 所有业务实体继承 BaseEntity(含 7 列审计字段)
|
||||
2. 每个 @*Mapping 方法必须有 @PreAuthorize("hasAuthority('resource:action')"),login/refresh 除外
|
||||
3. DTO/Request/Response 禁止含 tenantId 字段
|
||||
4. Service 层禁止手动 setTenantId(),由 TenantLineInterceptor 自动注入
|
||||
5. Flyway 迁移禁止 IF NOT EXISTS
|
||||
6. POM 版本禁止 ${latest.version},必须硬编码数字
|
||||
7. 每个新文件必须输出完整内容,禁止省略
|
||||
|
||||
## 生成顺序
|
||||
Entity → Mapper → Service → Controller → Flyway 迁移 SQL
|
||||
|
||||
## 编译验证
|
||||
每生成 3-5 个文件后运行:mvn clean compile -f pom.xml -q
|
||||
编译失败立即修复,不继续生成下一个文件。
|
||||
|
||||
context_requirements:
|
||||
- "CLAUDE.md"
|
||||
- ".claude/rules/java-conventions.md"
|
||||
- ".claude/rules/flyway-rules.md"
|
||||
@@ -0,0 +1,36 @@
|
||||
name: frontend-builder-system-prompt
|
||||
version: "1.0.0"
|
||||
model: claude-sonnet-4-6
|
||||
author: ljwx-team
|
||||
changelog:
|
||||
- version: "1.0.0"
|
||||
date: "2026-02-23"
|
||||
description: "Initial frontend builder system prompt"
|
||||
|
||||
system_prompt: |
|
||||
你是 LJWX Platform 的高级 Vue 3 前端工程师,负责生成高质量、类型安全的前端代码。
|
||||
技术栈:Vue 3.5 / Vue Router 5 / Pinia 3 / TypeScript 5.9 / Element Plus / pnpm。
|
||||
|
||||
## 硬规则
|
||||
1. 只用 <script setup lang="ts"> 语法糖,禁止 Options API
|
||||
2. 禁止 any / as any / <any>,所有类型必须明确
|
||||
3. tsconfig.json 必须 "strict": true
|
||||
4. 使用 Vue Router 5 Composition API:useRoute(), useRouter()
|
||||
- onBeforeRouteLeave / onBeforeRouteUpdate 在 v5 合法
|
||||
- 禁止 Options API 路由守卫(beforeRouteLeave 写在组件选项中)
|
||||
5. API 调用只通过 src/api/*.ts,禁止组件内直接 fetch
|
||||
6. 环境变量只用 VITE_APP_BASE_API
|
||||
7. package.json 只用 ~(tilde),禁止 ^(caret)
|
||||
8. 样式 <style scoped lang="scss">
|
||||
9. 每个新文件必须输出完整内容,禁止省略
|
||||
|
||||
## 生成顺序
|
||||
TypeScript 类型定义 → API 函数 → Pinia Store → 路由模块 → Vue 视图
|
||||
|
||||
## 类型检查验证
|
||||
每生成 3-5 个 TS/Vue 文件后运行:pnpm run type-check(在 ljwx-platform-admin/)
|
||||
类型错误立即修复,不继续生成下一个文件。
|
||||
|
||||
context_requirements:
|
||||
- "CLAUDE.md"
|
||||
- ".claude/rules/vue-conventions.md"
|
||||
@@ -0,0 +1,31 @@
|
||||
name: phase-execution-template
|
||||
version: "1.0.0"
|
||||
author: ljwx-team
|
||||
description: "Template for executing any numbered phase"
|
||||
changelog:
|
||||
- version: "1.0.0"
|
||||
date: "2026-02-23"
|
||||
description: "Initial phase execution template"
|
||||
|
||||
template: |
|
||||
执行 Phase {PHASE_NUM}。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. 读取 spec/phase/phase-{PHASE_NUM_PADDED}.md 获取本阶段任务
|
||||
2. 严格按 "读取清单" 加载指定的 spec 文件(禁止扫描整个 spec/ 目录)
|
||||
3. 按 scope 顺序逐文件生成,每文件生成后立即编译/类型检查
|
||||
4. 运行 gate:bash scripts/gates/gate-all.sh {PHASE_NUM}
|
||||
5. 修复所有 FAIL 项,直到全部 PASS
|
||||
6. 写入 PHASE_MANIFEST.txt
|
||||
7. 提示用户更新 CLAUDE.md 中的 Current Phase
|
||||
|
||||
## 质量检查清单(输出前自查)
|
||||
|
||||
- [ ] 所有新文件输出完整内容(无省略标记)
|
||||
- [ ] 所有 Controller 方法有 @PreAuthorize
|
||||
- [ ] 所有 Flyway SQL 含 7 列审计字段且无 IF NOT EXISTS
|
||||
- [ ] 所有 DTO 无 tenantId 字段
|
||||
- [ ] 所有 package.json 只用 ~,无 ^
|
||||
- [ ] 所有 TS/Vue 无 any 类型
|
||||
- [ ] 仅修改 Phase scope 内的文件(禁止顺手重构无关文件)
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# CI: syntax-check all shell scripts in the project.
|
||||
# Uses bash -n for all .sh files.
|
||||
# Uses shellcheck if available (warning level, non-blocking).
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
ERRORS=0
|
||||
|
||||
echo "=== Shell Script Lint ==="
|
||||
echo ""
|
||||
|
||||
# Collect all .sh files
|
||||
while IFS= read -r -d '' SCRIPT_FILE; do
|
||||
REL="${SCRIPT_FILE#"$PROJECT_ROOT"/}"
|
||||
if bash -n "$SCRIPT_FILE" 2>/dev/null; then
|
||||
echo " [OK] $REL"
|
||||
else
|
||||
echo " [FAIL] $REL — syntax error:"
|
||||
bash -n "$SCRIPT_FILE" 2>&1 | sed 's/^/ /'
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find \
|
||||
"$PROJECT_ROOT/scripts" \
|
||||
"$PROJECT_ROOT/.claude/hooks" \
|
||||
-type f -name "*.sh" -print0 2>/dev/null)
|
||||
|
||||
# shellcheck if available (informational only)
|
||||
if command -v shellcheck >/dev/null 2>&1; then
|
||||
echo ""
|
||||
echo "--- shellcheck (warnings only, non-blocking) ---"
|
||||
while IFS= read -r -d '' SCRIPT_FILE; do
|
||||
REL="${SCRIPT_FILE#"$PROJECT_ROOT"/}"
|
||||
if ! shellcheck -S warning -e SC2148 "$SCRIPT_FILE" 2>/dev/null; then
|
||||
echo " [WARN] $REL has shellcheck findings"
|
||||
fi
|
||||
done < <(find \
|
||||
"$PROJECT_ROOT/scripts" \
|
||||
"$PROJECT_ROOT/.claude/hooks" \
|
||||
-type f -name "*.sh" -print0 2>/dev/null)
|
||||
else
|
||||
echo ""
|
||||
echo " [INFO] shellcheck not installed — install with: brew install shellcheck"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
echo "LINT FAILED: $ERRORS script(s) have bash syntax errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "LINT PASSED"
|
||||
exit 0
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# CI: validate YAML files in the project using Python's yaml module.
|
||||
# Checks prompts/ and .github/workflows/ directories.
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
ERRORS=0
|
||||
|
||||
echo "=== YAML Validation ==="
|
||||
echo ""
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo " [SKIP] python3 not found — YAML validation skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! python3 -c "import yaml" 2>/dev/null; then
|
||||
echo " [SKIP] PyYAML not installed — run: pip install pyyaml"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Find YAML files in known directories
|
||||
while IFS= read -r -d '' YAML_FILE; do
|
||||
REL="${YAML_FILE#"$PROJECT_ROOT"/}"
|
||||
if python3 -c "
|
||||
import yaml, sys
|
||||
try:
|
||||
with open(sys.argv[1]) as fh:
|
||||
yaml.safe_load(fh)
|
||||
except yaml.YAMLError as e:
|
||||
print(f'YAML error: {e}', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
" "$YAML_FILE" 2>/dev/null; then
|
||||
echo " [OK] $REL"
|
||||
else
|
||||
ERROR_MSG=$(python3 -c "
|
||||
import yaml, sys
|
||||
try:
|
||||
with open(sys.argv[1]) as fh:
|
||||
yaml.safe_load(fh)
|
||||
except yaml.YAMLError as e:
|
||||
print(str(e))
|
||||
" "$YAML_FILE" 2>&1 || true)
|
||||
echo " [FAIL] $REL — $ERROR_MSG"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
done < <(find \
|
||||
"$PROJECT_ROOT/prompts" \
|
||||
"$PROJECT_ROOT/.github/workflows" \
|
||||
-type f \( -name "*.yaml" -o -name "*.yml" \) -print0 2>/dev/null)
|
||||
|
||||
echo ""
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
echo "YAML VALIDATION FAILED: $ERRORS file(s) invalid"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "YAML VALIDATION PASSED"
|
||||
exit 0
|
||||
@@ -0,0 +1,121 @@
|
||||
---
|
||||
title: "Phase Template Title"
|
||||
phase: 0
|
||||
targets:
|
||||
- backend
|
||||
- frontend
|
||||
scope:
|
||||
- "ljwx-platform-*/src/main/java/com/ljwx/platform/*/entity/*.java"
|
||||
- "ljwx-platform-*/src/main/java/com/ljwx/platform/*/mapper/*.java"
|
||||
- "ljwx-platform-*/src/main/java/com/ljwx/platform/*/service/*.java"
|
||||
- "ljwx-platform-*/src/main/java/com/ljwx/platform/*/controller/*.java"
|
||||
- "ljwx-platform-app/src/main/resources/db/migration/V0_1__example.sql"
|
||||
- "ljwx-platform-admin/src/api/module.ts"
|
||||
- "ljwx-platform-admin/src/router/modules/module.ts"
|
||||
- "ljwx-platform-admin/src/stores/module.ts"
|
||||
- "ljwx-platform-admin/src/views/module/index.vue"
|
||||
depends_on: []
|
||||
gate_rules:
|
||||
- no-preauthorize
|
||||
- no-caret
|
||||
- dto-no-tenant-id
|
||||
- no-any
|
||||
- no-if-not-exists
|
||||
- wrong-env-var
|
||||
- dag-violation
|
||||
- audit-columns
|
||||
---
|
||||
|
||||
# Phase N: 标题
|
||||
|
||||
## 目标
|
||||
|
||||
本 Phase 要实现的功能概述。
|
||||
|
||||
## 读取清单
|
||||
|
||||
> 严格按此清单读取,禁止扫描整个 spec/ 目录
|
||||
|
||||
- `spec/01-constraints.md` §C01(多租户),§C02(权限)
|
||||
- `spec/04-database.md` §相关表结构章节
|
||||
- `spec/03-api.md` §相关接口章节
|
||||
|
||||
## 后端任务
|
||||
|
||||
### 实体层
|
||||
|
||||
**表名**:`t_xxx`
|
||||
**基类**:继承 `BaseEntity`(已含 7 列审计字段)
|
||||
|
||||
| 字段名 | 类型 | 约束 | 说明 |
|
||||
|-------|------|------|------|
|
||||
| id | BIGINT | PK | 主键 |
|
||||
| name | VARCHAR(100) | NOT NULL | 名称 |
|
||||
|
||||
### Mapper
|
||||
|
||||
方法列表:
|
||||
- `selectByXxx(XxxQueryDTO)` — 条件查询(TenantLineInterceptor 自动注入 tenant_id)
|
||||
|
||||
### Service
|
||||
|
||||
- `listXxx(XxxQueryDTO): PageResult<XxxVO>` — 列表查询
|
||||
- `createXxx(XxxCreateDTO): Long` — 创建,返回 ID
|
||||
|
||||
### Controller
|
||||
|
||||
REST 路径:`/api/v1/xxx`
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
|-----|------|------|------|
|
||||
| GET | /api/v1/xxx | `xxx:read` | 分页列表 |
|
||||
| POST | /api/v1/xxx | `xxx:write` | 创建 |
|
||||
| PUT | /api/v1/xxx/{id} | `xxx:write` | 更新 |
|
||||
| DELETE | /api/v1/xxx/{id} | `xxx:delete` | 删除 |
|
||||
|
||||
### Flyway 迁移
|
||||
|
||||
文件:`V{N}_1__create_xxx_table.sql`
|
||||
|
||||
## 前端任务
|
||||
|
||||
### API 层
|
||||
|
||||
文件:`src/api/xxx.ts`
|
||||
- `getXxxList(params?: XxxQueryDTO): Promise<Result<PageResult<XxxVO>>>`
|
||||
- `createXxx(data: XxxCreateDTO): Promise<Result<number>>`
|
||||
|
||||
### 路由
|
||||
|
||||
文件:`src/router/modules/xxx.ts`
|
||||
- `/xxx` — 列表页
|
||||
|
||||
### 视图
|
||||
|
||||
文件:`src/views/xxx/index.vue`
|
||||
- 搜索表单 + `el-table` 列表 + 分页
|
||||
|
||||
## 验收条件
|
||||
|
||||
1. `mvn clean compile -f pom.xml -q` 通过
|
||||
2. `pnpm run type-check` 通过(在 ljwx-platform-admin/)
|
||||
3. `bash scripts/gates/gate-all.sh N` 全部 PASS
|
||||
4. 无 TypeScript `any`
|
||||
5. 所有 Controller 方法有 `@PreAuthorize`
|
||||
6. 迁移 SQL 含 7 列审计字段且无 `IF NOT EXISTS`
|
||||
|
||||
## PHASE_MANIFEST.txt 记录格式
|
||||
|
||||
```
|
||||
## PHASE N
|
||||
Status: PASSED
|
||||
|
||||
ljwx-platform-*/src/.../XxxEntity.java
|
||||
ljwx-platform-*/src/.../XxxMapper.java
|
||||
ljwx-platform-*/src/.../XxxService.java
|
||||
ljwx-platform-*/src/.../XxxController.java
|
||||
ljwx-platform-app/src/main/resources/db/migration/VN_1__create_xxx_table.sql
|
||||
ljwx-platform-admin/src/api/xxx.ts
|
||||
ljwx-platform-admin/src/router/modules/xxx.ts
|
||||
ljwx-platform-admin/src/views/xxx/index.vue
|
||||
```
|
||||
Reference in New Issue
Block a user