@robsun/create-keystone-app 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,6 +31,10 @@ pnpm dlx --package @robsun/create-keystone-app create-keystone-module <module-na
31
31
  - `--with-crud`:包含 CRUD 示例代码。
32
32
  - `--skip-register`:跳过自动注册步骤。
33
33
 
34
+ ## AI Skills
35
+ - Codex:`.codex/skills/keystone-dev`
36
+ - Claude:`.claude/skills/keystone-dev`
37
+
34
38
  ## 初始化后操作
35
39
  ```bash
36
40
  cd <dir>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robsun/create-keystone-app",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "scripts": {
5
5
  "build": "node scripts/build.js",
6
6
  "prepublishOnly": "node scripts/build.js && node scripts/prune-template-deps.js"
@@ -0,0 +1,127 @@
1
+ # Keystone 包完整能力清单
2
+
3
+ ## 一、前端组件 (@robsun/keystone-web-core)
4
+
5
+ ### 1. 应用与路由
6
+ ```typescript
7
+ import { KeystoneApp, createKeystoneRouter } from '@robsun/keystone-web-core'
8
+ import { registerModule, registerRoutes, registerMenus, registerPermissions } from '@robsun/keystone-web-core'
9
+ ```
10
+
11
+ ### 2. 高级 UI 组件
12
+ ```typescript
13
+ // 高级表格 - 过滤、分页、行选择、导出
14
+ import { ProTable } from '@robsun/keystone-web-core'
15
+
16
+ // 智能表单 - 自动验证、加载状态
17
+ import { ProForm } from '@robsun/keystone-web-core'
18
+
19
+ // 文件上传 - 拖拽、预览、多文件
20
+ import { FileUpload } from '@robsun/keystone-web-core'
21
+
22
+ // 数据导入向导
23
+ import { DataImporter, ImportWizard, ColumnMapper, ValidationResult } from '@robsun/keystone-web-core'
24
+
25
+ // 数据导出向导
26
+ import { DataExporter, ExportWizard } from '@robsun/keystone-web-core'
27
+
28
+ // 权限守卫
29
+ import { PermissionGuard } from '@robsun/keystone-web-core'
30
+ ```
31
+
32
+ ### 3. 审批流系统
33
+ ```typescript
34
+ import {
35
+ ApprovalFlowEditor, // 流程编辑器
36
+ ApprovalFlowCanvas, // 可视化画布
37
+ ApprovalNodeEditor, // 节点编辑
38
+ ConditionEditor, // 条件编辑
39
+ ApprovalStatus, // 状态展示
40
+ ApprovalAction, // 审批按钮
41
+ ApprovalHistory // 审批历史
42
+ } from '@robsun/keystone-web-core'
43
+ ```
44
+
45
+ ### 4. 帮助系统
46
+ ```typescript
47
+ import {
48
+ HelpButton, HelpDrawer, HelpSearch, HelpContent,
49
+ useCurrentHelpKey, useHelpSearch
50
+ } from '@robsun/keystone-web-core'
51
+ ```
52
+
53
+ ### 5. 布局与主题
54
+ ```typescript
55
+ import { MainLayout, antdTheme, useLayoutStore } from '@robsun/keystone-web-core'
56
+ ```
57
+
58
+ ### 6. 认证授权
59
+ ```typescript
60
+ import { useAuthStore, useAuth, matchesPermission } from '@robsun/keystone-web-core'
61
+ ```
62
+
63
+ ### 7. 运行时服务
64
+ ```typescript
65
+ import { api, setApiBaseUrl } from '@robsun/keystone-web-core'
66
+ import { createExportJob, createImportJob } from '@robsun/keystone-web-core'
67
+ import { listNotifications, markNotificationRead, fetchUnreadCount } from '@robsun/keystone-web-core'
68
+ import { getJob, listJobs } from '@robsun/keystone-web-core'
69
+ ```
70
+
71
+ ### 8. Hooks
72
+ ```typescript
73
+ import { useListState } from '@robsun/keystone-web-core'
74
+ ```
75
+
76
+ ### 9. 类型
77
+ ```typescript
78
+ import type { ApiResponse, PaginatedData, PaginatedResponse } from '@robsun/keystone-web-core'
79
+ import type { Permission, ModuleName, Action } from '@robsun/keystone-web-core'
80
+ ```
81
+
82
+ ## 二、后端能力 (Go)
83
+
84
+ ### 1. 模块系统
85
+ ```go
86
+ type Module interface {
87
+ Name() string
88
+ RegisterRoutes(r *gin.RouterGroup)
89
+ RegisterPermissions() []Permission
90
+ Migrate(db *gorm.DB) error
91
+ Seed(db *gorm.DB) error
92
+ }
93
+ ```
94
+
95
+ ### 2. 审批引擎
96
+ ```go
97
+ approvalService.CreateInstance(...)
98
+ approvalService.Approve(...)
99
+ approvalService.Reject(...)
100
+ approvalService.Cancel(...)
101
+ ```
102
+
103
+ ### 3. Job 队列
104
+ ```go
105
+ jobService.CreateJob(...)
106
+ jobService.GetJob(...)
107
+ jobService.ListJobs(...)
108
+ ```
109
+
110
+ ### 4. 通知服务
111
+ ```go
112
+ notificationService.SendNotification(...)
113
+ notificationService.ListNotifications(...)
114
+ notificationService.MarkRead(...)
115
+ ```
116
+
117
+ ### 5. 权限中间件
118
+ ```go
119
+ middleware.RequirePermission("module:resource:action")
120
+ ```
121
+
122
+ ### 6. 存储服务
123
+ ```go
124
+ storageService.Upload(...)
125
+ storageService.Download(...)
126
+ storageService.Delete(...)
127
+ ```
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: keystone-dev
3
+ description: 基于 Keystone 平台开发业务模块。当用户需要创建新模块、添加业务功能、实现 CRUD、审批流程、数据导入导出、文件上传时使用。Use when creating modules, adding features, implementing CRUD, approval workflows, import/export, or file upload for Keystone platform.
4
+ ---
5
+
6
+ # Keystone 业务模块开发
7
+
8
+ 使用 Keystone 平台快速开发业务模块。
9
+
10
+ ## 工作流程
11
+
12
+ 1. **解析需求** → 识别所需能力
13
+ 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts
14
+ 3. **生成后端模块** → handler/, service/, repository/, migrations/
15
+ 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
+ 5. **输出调整建议**
17
+
18
+ ## 能力选择矩阵
19
+
20
+ 根据需求关键词选用对应能力:
21
+
22
+ | 需求关键词 | 前端能力 | 后端能力 |
23
+ |-----------|---------|---------|
24
+ | 列表、查询 | ProTable + 过滤 + 分页 | ListHandler + Repository |
25
+ | 表单、编辑 | ProForm + 验证 | CreateHandler + UpdateHandler |
26
+ | 导入、批量 | DataImporter | ImportHandler + Job队列 |
27
+ | 导出、下载 | DataExporter | ExportHandler + Job队列 |
28
+ | 上传、附件 | FileUpload | UploadHandler + 存储服务 |
29
+ | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
30
+ | 权限 | PermissionGuard | 权限中间件 |
31
+
32
+ 详细能力清单见 [CAPABILITIES.md](CAPABILITIES.md)。
33
+ 代码模板见 [TEMPLATES.md](TEMPLATES.md)。
34
+
35
+ ## 模块结构约定
36
+
37
+ ### 前端模块
38
+ ```
39
+ apps/web/src/modules/{name}/
40
+ ├── index.ts # registerModule()
41
+ ├── routes.tsx # 路由 + 菜单 + 权限
42
+ ├── pages/
43
+ │ ├── List.tsx # ProTable
44
+ │ ├── Detail.tsx
45
+ │ └── Form.tsx # ProForm
46
+ ├── services/api.ts
47
+ ├── types.ts
48
+ └── help/index.md
49
+ ```
50
+
51
+ ### 后端模块
52
+ ```
53
+ apps/server/internal/modules/{name}/
54
+ ├── module.go
55
+ ├── api/handler/
56
+ ├── domain/models/
57
+ ├── domain/service/
58
+ ├── infra/repository/
59
+ └── bootstrap/migrations/
60
+ ```
61
+
62
+ ## 权限命名
63
+
64
+ 格式: `{module}:{resource}:{action}`
65
+
66
+ 动作: view | create | update | delete | manage | export | import | approve
67
+
68
+ ## 注册步骤
69
+
70
+ 生成代码后需手动注册:
71
+
72
+ 1. **前端** `main.tsx`: `import './modules/{name}'`
73
+ 2. **后端** `manifest.go`: `import _ "app/internal/modules/{name}"`
74
+ 3. **配置** `config.yaml`: 添加到 `modules.enabled`
@@ -0,0 +1,257 @@
1
+ # Keystone 代码模板
2
+
3
+ ## 前端模板
4
+
5
+ ### routes.tsx
6
+ ```tsx
7
+ import { RouteObject } from 'react-router-dom'
8
+ import { registerModule } from '@robsun/keystone-web-core'
9
+
10
+ const routes: RouteObject[] = [
11
+ {
12
+ path: '{name}',
13
+ handle: {
14
+ menu: { title: '{Title}', icon: 'icon-name' },
15
+ permission: '{name}:{resource}:view',
16
+ helpKey: '{name}/index',
17
+ },
18
+ children: [
19
+ { index: true, lazy: () => import('./pages/List') },
20
+ { path: 'create', lazy: () => import('./pages/Form') },
21
+ { path: ':id', lazy: () => import('./pages/Detail') },
22
+ { path: ':id/edit', lazy: () => import('./pages/Form') },
23
+ ],
24
+ },
25
+ ]
26
+
27
+ registerModule({ name: '{name}', routes })
28
+ ```
29
+
30
+ ### List.tsx (ProTable)
31
+ ```tsx
32
+ import { ProTable } from '@robsun/keystone-web-core'
33
+ import { api } from '@robsun/keystone-web-core'
34
+ import type { PaginatedResponse } from '@robsun/keystone-web-core'
35
+ import type { {Entity} } from '../types'
36
+
37
+ export function Component() {
38
+ const columns = [
39
+ { title: 'ID', dataIndex: 'id' },
40
+ { title: '名称', dataIndex: 'name' },
41
+ ]
42
+
43
+ const fetchData = async (params: any) => {
44
+ const res = await api.get<PaginatedResponse<{Entity}>>('/api/{name}', { params })
45
+ return res.data
46
+ }
47
+
48
+ return <ProTable columns={columns} request={fetchData} rowKey="id" />
49
+ }
50
+ ```
51
+
52
+ ### Form.tsx (ProForm)
53
+ ```tsx
54
+ import { ProForm } from '@robsun/keystone-web-core'
55
+ import { api } from '@robsun/keystone-web-core'
56
+ import { useParams, useNavigate } from 'react-router-dom'
57
+
58
+ export function Component() {
59
+ const { id } = useParams()
60
+ const navigate = useNavigate()
61
+ const isEdit = !!id
62
+
63
+ const onSubmit = async (values: any) => {
64
+ if (isEdit) {
65
+ await api.patch(`/api/{name}/${id}`, values)
66
+ } else {
67
+ await api.post('/api/{name}', values)
68
+ }
69
+ navigate('/{name}')
70
+ }
71
+
72
+ return (
73
+ <ProForm onFinish={onSubmit}>
74
+ {/* 表单字段 */}
75
+ </ProForm>
76
+ )
77
+ }
78
+ ```
79
+
80
+ ### services/api.ts
81
+ ```typescript
82
+ import { api } from '@robsun/keystone-web-core'
83
+ import type { ApiResponse, PaginatedResponse } from '@robsun/keystone-web-core'
84
+ import type { {Entity} } from '../types'
85
+
86
+ export const {name}Api = {
87
+ list: (params?: any) => api.get<PaginatedResponse<{Entity}>>('/api/{name}', { params }),
88
+ get: (id: string) => api.get<ApiResponse<{Entity}>>(`/api/{name}/${id}`),
89
+ create: (data: Partial<{Entity}>) => api.post<ApiResponse<{Entity}>>('/api/{name}', data),
90
+ update: (id: string, data: Partial<{Entity}>) => api.patch<ApiResponse<{Entity}>>(`/api/{name}/${id}`, data),
91
+ delete: (id: string) => api.delete<ApiResponse<void>>(`/api/{name}/${id}`),
92
+ }
93
+ ```
94
+
95
+ ### types.ts
96
+ ```typescript
97
+ export interface {Entity} {
98
+ id: string
99
+ name: string
100
+ createdAt: string
101
+ updatedAt: string
102
+ }
103
+ ```
104
+
105
+ ## 后端模板
106
+
107
+ ### module.go
108
+ ```go
109
+ package {name}
110
+
111
+ import (
112
+ "github.com/gin-gonic/gin"
113
+ "gorm.io/gorm"
114
+ )
115
+
116
+ type Module struct{}
117
+
118
+ func (m *Module) Name() string { return "{name}" }
119
+
120
+ func (m *Module) RegisterRoutes(r *gin.RouterGroup) {
121
+ g := r.Group("/{name}")
122
+ g.GET("", handler.List)
123
+ g.GET("/:id", handler.Detail)
124
+ g.POST("", handler.Create)
125
+ g.PATCH("/:id", handler.Update)
126
+ g.DELETE("/:id", handler.Delete)
127
+ }
128
+
129
+ func (m *Module) RegisterPermissions() []Permission {
130
+ return []Permission{
131
+ {Name: "{name}:{resource}:view", Title: "查看{Title}"},
132
+ {Name: "{name}:{resource}:create", Title: "创建{Title}"},
133
+ {Name: "{name}:{resource}:update", Title: "编辑{Title}"},
134
+ {Name: "{name}:{resource}:delete", Title: "删除{Title}"},
135
+ }
136
+ }
137
+
138
+ func (m *Module) Migrate(db *gorm.DB) error {
139
+ return db.AutoMigrate(&models.{Entity}{})
140
+ }
141
+
142
+ func (m *Module) Seed(db *gorm.DB) error { return nil }
143
+ ```
144
+
145
+ ### handler/list.go
146
+ ```go
147
+ package handler
148
+
149
+ import (
150
+ "github.com/gin-gonic/gin"
151
+ )
152
+
153
+ func (h *Handler) List(c *gin.Context) {
154
+ page, pageSize := parsePagination(c)
155
+ items, total, err := h.svc.List(c, page, pageSize)
156
+ if err != nil {
157
+ respondError(c, err)
158
+ return
159
+ }
160
+ respondPaginated(c, items, total, page, pageSize)
161
+ }
162
+ ```
163
+
164
+ ### domain/models/entity.go
165
+ ```go
166
+ package models
167
+
168
+ import "time"
169
+
170
+ type {Entity} struct {
171
+ ID string `json:"id" gorm:"primaryKey"`
172
+ Name string `json:"name"`
173
+ CreatedAt time.Time `json:"createdAt"`
174
+ UpdatedAt time.Time `json:"updatedAt"`
175
+ }
176
+ ```
177
+
178
+ ### domain/service/service.go
179
+ ```go
180
+ package service
181
+
182
+ type Service struct {
183
+ repo *repository.Repository
184
+ }
185
+
186
+ func NewService(repo *repository.Repository) *Service {
187
+ return &Service{repo: repo}
188
+ }
189
+
190
+ func (s *Service) List(ctx context.Context, page, pageSize int) ([]models.{Entity}, int64, error) {
191
+ return s.repo.List(ctx, page, pageSize)
192
+ }
193
+
194
+ func (s *Service) Get(ctx context.Context, id string) (*models.{Entity}, error) {
195
+ return s.repo.Get(ctx, id)
196
+ }
197
+
198
+ func (s *Service) Create(ctx context.Context, entity *models.{Entity}) error {
199
+ return s.repo.Create(ctx, entity)
200
+ }
201
+
202
+ func (s *Service) Update(ctx context.Context, id string, entity *models.{Entity}) error {
203
+ return s.repo.Update(ctx, id, entity)
204
+ }
205
+
206
+ func (s *Service) Delete(ctx context.Context, id string) error {
207
+ return s.repo.Delete(ctx, id)
208
+ }
209
+ ```
210
+
211
+ ### infra/repository/repo.go
212
+ ```go
213
+ package repository
214
+
215
+ import (
216
+ "context"
217
+ "gorm.io/gorm"
218
+ )
219
+
220
+ type Repository struct {
221
+ db *gorm.DB
222
+ }
223
+
224
+ func NewRepository(db *gorm.DB) *Repository {
225
+ return &Repository{db: db}
226
+ }
227
+
228
+ func (r *Repository) List(ctx context.Context, page, pageSize int) ([]models.{Entity}, int64, error) {
229
+ var items []models.{Entity}
230
+ var total int64
231
+
232
+ r.db.Model(&models.{Entity}{}).Count(&total)
233
+ r.db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
234
+
235
+ return items, total, nil
236
+ }
237
+
238
+ func (r *Repository) Get(ctx context.Context, id string) (*models.{Entity}, error) {
239
+ var item models.{Entity}
240
+ if err := r.db.First(&item, "id = ?", id).Error; err != nil {
241
+ return nil, err
242
+ }
243
+ return &item, nil
244
+ }
245
+
246
+ func (r *Repository) Create(ctx context.Context, entity *models.{Entity}) error {
247
+ return r.db.Create(entity).Error
248
+ }
249
+
250
+ func (r *Repository) Update(ctx context.Context, id string, entity *models.{Entity}) error {
251
+ return r.db.Model(&models.{Entity}{}).Where("id = ?", id).Updates(entity).Error
252
+ }
253
+
254
+ func (r *Repository) Delete(ctx context.Context, id string) error {
255
+ return r.db.Delete(&models.{Entity}{}, "id = ?", id).Error
256
+ }
257
+ ```
@@ -0,0 +1,127 @@
1
+ # Keystone 包完整能力清单
2
+
3
+ ## 一、前端组件 (@robsun/keystone-web-core)
4
+
5
+ ### 1. 应用与路由
6
+ ```typescript
7
+ import { KeystoneApp, createKeystoneRouter } from '@robsun/keystone-web-core'
8
+ import { registerModule, registerRoutes, registerMenus, registerPermissions } from '@robsun/keystone-web-core'
9
+ ```
10
+
11
+ ### 2. 高级 UI 组件
12
+ ```typescript
13
+ // 高级表格 - 过滤、分页、行选择、导出
14
+ import { ProTable } from '@robsun/keystone-web-core'
15
+
16
+ // 智能表单 - 自动验证、加载状态
17
+ import { ProForm } from '@robsun/keystone-web-core'
18
+
19
+ // 文件上传 - 拖拽、预览、多文件
20
+ import { FileUpload } from '@robsun/keystone-web-core'
21
+
22
+ // 数据导入向导
23
+ import { DataImporter, ImportWizard, ColumnMapper, ValidationResult } from '@robsun/keystone-web-core'
24
+
25
+ // 数据导出向导
26
+ import { DataExporter, ExportWizard } from '@robsun/keystone-web-core'
27
+
28
+ // 权限守卫
29
+ import { PermissionGuard } from '@robsun/keystone-web-core'
30
+ ```
31
+
32
+ ### 3. 审批流系统
33
+ ```typescript
34
+ import {
35
+ ApprovalFlowEditor, // 流程编辑器
36
+ ApprovalFlowCanvas, // 可视化画布
37
+ ApprovalNodeEditor, // 节点编辑
38
+ ConditionEditor, // 条件编辑
39
+ ApprovalStatus, // 状态展示
40
+ ApprovalAction, // 审批按钮
41
+ ApprovalHistory // 审批历史
42
+ } from '@robsun/keystone-web-core'
43
+ ```
44
+
45
+ ### 4. 帮助系统
46
+ ```typescript
47
+ import {
48
+ HelpButton, HelpDrawer, HelpSearch, HelpContent,
49
+ useCurrentHelpKey, useHelpSearch
50
+ } from '@robsun/keystone-web-core'
51
+ ```
52
+
53
+ ### 5. 布局与主题
54
+ ```typescript
55
+ import { MainLayout, antdTheme, useLayoutStore } from '@robsun/keystone-web-core'
56
+ ```
57
+
58
+ ### 6. 认证授权
59
+ ```typescript
60
+ import { useAuthStore, useAuth, matchesPermission } from '@robsun/keystone-web-core'
61
+ ```
62
+
63
+ ### 7. 运行时服务
64
+ ```typescript
65
+ import { api, setApiBaseUrl } from '@robsun/keystone-web-core'
66
+ import { createExportJob, createImportJob } from '@robsun/keystone-web-core'
67
+ import { listNotifications, markNotificationRead, fetchUnreadCount } from '@robsun/keystone-web-core'
68
+ import { getJob, listJobs } from '@robsun/keystone-web-core'
69
+ ```
70
+
71
+ ### 8. Hooks
72
+ ```typescript
73
+ import { useListState } from '@robsun/keystone-web-core'
74
+ ```
75
+
76
+ ### 9. 类型
77
+ ```typescript
78
+ import type { ApiResponse, PaginatedData, PaginatedResponse } from '@robsun/keystone-web-core'
79
+ import type { Permission, ModuleName, Action } from '@robsun/keystone-web-core'
80
+ ```
81
+
82
+ ## 二、后端能力 (Go)
83
+
84
+ ### 1. 模块系统
85
+ ```go
86
+ type Module interface {
87
+ Name() string
88
+ RegisterRoutes(r *gin.RouterGroup)
89
+ RegisterPermissions() []Permission
90
+ Migrate(db *gorm.DB) error
91
+ Seed(db *gorm.DB) error
92
+ }
93
+ ```
94
+
95
+ ### 2. 审批引擎
96
+ ```go
97
+ approvalService.CreateInstance(...)
98
+ approvalService.Approve(...)
99
+ approvalService.Reject(...)
100
+ approvalService.Cancel(...)
101
+ ```
102
+
103
+ ### 3. Job 队列
104
+ ```go
105
+ jobService.CreateJob(...)
106
+ jobService.GetJob(...)
107
+ jobService.ListJobs(...)
108
+ ```
109
+
110
+ ### 4. 通知服务
111
+ ```go
112
+ notificationService.SendNotification(...)
113
+ notificationService.ListNotifications(...)
114
+ notificationService.MarkRead(...)
115
+ ```
116
+
117
+ ### 5. 权限中间件
118
+ ```go
119
+ middleware.RequirePermission("module:resource:action")
120
+ ```
121
+
122
+ ### 6. 存储服务
123
+ ```go
124
+ storageService.Upload(...)
125
+ storageService.Download(...)
126
+ storageService.Delete(...)
127
+ ```
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: keystone-dev
3
+ description: 基于 Keystone 平台开发业务模块。当用户需要创建新模块、添加业务功能、实现 CRUD、审批流程、数据导入导出、文件上传时使用。Use when creating modules, adding features, implementing CRUD, approval workflows, import/export, or file upload for Keystone platform.
4
+ ---
5
+
6
+ # Keystone 业务模块开发
7
+
8
+ 使用 Keystone 平台快速开发业务模块。
9
+
10
+ ## 工作流程
11
+
12
+ 1. **解析需求** → 识别所需能力
13
+ 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts
14
+ 3. **生成后端模块** → handler/, service/, repository/, migrations/
15
+ 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
+ 5. **输出调整建议**
17
+
18
+ ## 能力选择矩阵
19
+
20
+ 根据需求关键词选用对应能力:
21
+
22
+ | 需求关键词 | 前端能力 | 后端能力 |
23
+ |-----------|---------|---------|
24
+ | 列表、查询 | ProTable + 过滤 + 分页 | ListHandler + Repository |
25
+ | 表单、编辑 | ProForm + 验证 | CreateHandler + UpdateHandler |
26
+ | 导入、批量 | DataImporter | ImportHandler + Job队列 |
27
+ | 导出、下载 | DataExporter | ExportHandler + Job队列 |
28
+ | 上传、附件 | FileUpload | UploadHandler + 存储服务 |
29
+ | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
30
+ | 权限 | PermissionGuard | 权限中间件 |
31
+
32
+ 详细能力清单见 [CAPABILITIES.md](CAPABILITIES.md)。
33
+ 代码模板见 [TEMPLATES.md](TEMPLATES.md)。
34
+
35
+ ## 模块结构约定
36
+
37
+ ### 前端模块
38
+ ```
39
+ apps/web/src/modules/{name}/
40
+ ├── index.ts # registerModule()
41
+ ├── routes.tsx # 路由 + 菜单 + 权限
42
+ ├── pages/
43
+ │ ├── List.tsx # ProTable
44
+ │ ├── Detail.tsx
45
+ │ └── Form.tsx # ProForm
46
+ ├── services/api.ts
47
+ ├── types.ts
48
+ └── help/index.md
49
+ ```
50
+
51
+ ### 后端模块
52
+ ```
53
+ apps/server/internal/modules/{name}/
54
+ ├── module.go
55
+ ├── api/handler/
56
+ ├── domain/models/
57
+ ├── domain/service/
58
+ ├── infra/repository/
59
+ └── bootstrap/migrations/
60
+ ```
61
+
62
+ ## 权限命名
63
+
64
+ 格式: `{module}:{resource}:{action}`
65
+
66
+ 动作: view | create | update | delete | manage | export | import | approve
67
+
68
+ ## 注册步骤
69
+
70
+ 生成代码后需手动注册:
71
+
72
+ 1. **前端** `main.tsx`: `import './modules/{name}'`
73
+ 2. **后端** `manifest.go`: `import _ "app/internal/modules/{name}"`
74
+ 3. **配置** `config.yaml`: 添加到 `modules.enabled`
@@ -0,0 +1,257 @@
1
+ # Keystone 代码模板
2
+
3
+ ## 前端模板
4
+
5
+ ### routes.tsx
6
+ ```tsx
7
+ import { RouteObject } from 'react-router-dom'
8
+ import { registerModule } from '@robsun/keystone-web-core'
9
+
10
+ const routes: RouteObject[] = [
11
+ {
12
+ path: '{name}',
13
+ handle: {
14
+ menu: { title: '{Title}', icon: 'icon-name' },
15
+ permission: '{name}:{resource}:view',
16
+ helpKey: '{name}/index',
17
+ },
18
+ children: [
19
+ { index: true, lazy: () => import('./pages/List') },
20
+ { path: 'create', lazy: () => import('./pages/Form') },
21
+ { path: ':id', lazy: () => import('./pages/Detail') },
22
+ { path: ':id/edit', lazy: () => import('./pages/Form') },
23
+ ],
24
+ },
25
+ ]
26
+
27
+ registerModule({ name: '{name}', routes })
28
+ ```
29
+
30
+ ### List.tsx (ProTable)
31
+ ```tsx
32
+ import { ProTable } from '@robsun/keystone-web-core'
33
+ import { api } from '@robsun/keystone-web-core'
34
+ import type { PaginatedResponse } from '@robsun/keystone-web-core'
35
+ import type { {Entity} } from '../types'
36
+
37
+ export function Component() {
38
+ const columns = [
39
+ { title: 'ID', dataIndex: 'id' },
40
+ { title: '名称', dataIndex: 'name' },
41
+ ]
42
+
43
+ const fetchData = async (params: any) => {
44
+ const res = await api.get<PaginatedResponse<{Entity}>>('/api/{name}', { params })
45
+ return res.data
46
+ }
47
+
48
+ return <ProTable columns={columns} request={fetchData} rowKey="id" />
49
+ }
50
+ ```
51
+
52
+ ### Form.tsx (ProForm)
53
+ ```tsx
54
+ import { ProForm } from '@robsun/keystone-web-core'
55
+ import { api } from '@robsun/keystone-web-core'
56
+ import { useParams, useNavigate } from 'react-router-dom'
57
+
58
+ export function Component() {
59
+ const { id } = useParams()
60
+ const navigate = useNavigate()
61
+ const isEdit = !!id
62
+
63
+ const onSubmit = async (values: any) => {
64
+ if (isEdit) {
65
+ await api.patch(`/api/{name}/${id}`, values)
66
+ } else {
67
+ await api.post('/api/{name}', values)
68
+ }
69
+ navigate('/{name}')
70
+ }
71
+
72
+ return (
73
+ <ProForm onFinish={onSubmit}>
74
+ {/* 表单字段 */}
75
+ </ProForm>
76
+ )
77
+ }
78
+ ```
79
+
80
+ ### services/api.ts
81
+ ```typescript
82
+ import { api } from '@robsun/keystone-web-core'
83
+ import type { ApiResponse, PaginatedResponse } from '@robsun/keystone-web-core'
84
+ import type { {Entity} } from '../types'
85
+
86
+ export const {name}Api = {
87
+ list: (params?: any) => api.get<PaginatedResponse<{Entity}>>('/api/{name}', { params }),
88
+ get: (id: string) => api.get<ApiResponse<{Entity}>>(`/api/{name}/${id}`),
89
+ create: (data: Partial<{Entity}>) => api.post<ApiResponse<{Entity}>>('/api/{name}', data),
90
+ update: (id: string, data: Partial<{Entity}>) => api.patch<ApiResponse<{Entity}>>(`/api/{name}/${id}`, data),
91
+ delete: (id: string) => api.delete<ApiResponse<void>>(`/api/{name}/${id}`),
92
+ }
93
+ ```
94
+
95
+ ### types.ts
96
+ ```typescript
97
+ export interface {Entity} {
98
+ id: string
99
+ name: string
100
+ createdAt: string
101
+ updatedAt: string
102
+ }
103
+ ```
104
+
105
+ ## 后端模板
106
+
107
+ ### module.go
108
+ ```go
109
+ package {name}
110
+
111
+ import (
112
+ "github.com/gin-gonic/gin"
113
+ "gorm.io/gorm"
114
+ )
115
+
116
+ type Module struct{}
117
+
118
+ func (m *Module) Name() string { return "{name}" }
119
+
120
+ func (m *Module) RegisterRoutes(r *gin.RouterGroup) {
121
+ g := r.Group("/{name}")
122
+ g.GET("", handler.List)
123
+ g.GET("/:id", handler.Detail)
124
+ g.POST("", handler.Create)
125
+ g.PATCH("/:id", handler.Update)
126
+ g.DELETE("/:id", handler.Delete)
127
+ }
128
+
129
+ func (m *Module) RegisterPermissions() []Permission {
130
+ return []Permission{
131
+ {Name: "{name}:{resource}:view", Title: "查看{Title}"},
132
+ {Name: "{name}:{resource}:create", Title: "创建{Title}"},
133
+ {Name: "{name}:{resource}:update", Title: "编辑{Title}"},
134
+ {Name: "{name}:{resource}:delete", Title: "删除{Title}"},
135
+ }
136
+ }
137
+
138
+ func (m *Module) Migrate(db *gorm.DB) error {
139
+ return db.AutoMigrate(&models.{Entity}{})
140
+ }
141
+
142
+ func (m *Module) Seed(db *gorm.DB) error { return nil }
143
+ ```
144
+
145
+ ### handler/list.go
146
+ ```go
147
+ package handler
148
+
149
+ import (
150
+ "github.com/gin-gonic/gin"
151
+ )
152
+
153
+ func (h *Handler) List(c *gin.Context) {
154
+ page, pageSize := parsePagination(c)
155
+ items, total, err := h.svc.List(c, page, pageSize)
156
+ if err != nil {
157
+ respondError(c, err)
158
+ return
159
+ }
160
+ respondPaginated(c, items, total, page, pageSize)
161
+ }
162
+ ```
163
+
164
+ ### domain/models/entity.go
165
+ ```go
166
+ package models
167
+
168
+ import "time"
169
+
170
+ type {Entity} struct {
171
+ ID string `json:"id" gorm:"primaryKey"`
172
+ Name string `json:"name"`
173
+ CreatedAt time.Time `json:"createdAt"`
174
+ UpdatedAt time.Time `json:"updatedAt"`
175
+ }
176
+ ```
177
+
178
+ ### domain/service/service.go
179
+ ```go
180
+ package service
181
+
182
+ type Service struct {
183
+ repo *repository.Repository
184
+ }
185
+
186
+ func NewService(repo *repository.Repository) *Service {
187
+ return &Service{repo: repo}
188
+ }
189
+
190
+ func (s *Service) List(ctx context.Context, page, pageSize int) ([]models.{Entity}, int64, error) {
191
+ return s.repo.List(ctx, page, pageSize)
192
+ }
193
+
194
+ func (s *Service) Get(ctx context.Context, id string) (*models.{Entity}, error) {
195
+ return s.repo.Get(ctx, id)
196
+ }
197
+
198
+ func (s *Service) Create(ctx context.Context, entity *models.{Entity}) error {
199
+ return s.repo.Create(ctx, entity)
200
+ }
201
+
202
+ func (s *Service) Update(ctx context.Context, id string, entity *models.{Entity}) error {
203
+ return s.repo.Update(ctx, id, entity)
204
+ }
205
+
206
+ func (s *Service) Delete(ctx context.Context, id string) error {
207
+ return s.repo.Delete(ctx, id)
208
+ }
209
+ ```
210
+
211
+ ### infra/repository/repo.go
212
+ ```go
213
+ package repository
214
+
215
+ import (
216
+ "context"
217
+ "gorm.io/gorm"
218
+ )
219
+
220
+ type Repository struct {
221
+ db *gorm.DB
222
+ }
223
+
224
+ func NewRepository(db *gorm.DB) *Repository {
225
+ return &Repository{db: db}
226
+ }
227
+
228
+ func (r *Repository) List(ctx context.Context, page, pageSize int) ([]models.{Entity}, int64, error) {
229
+ var items []models.{Entity}
230
+ var total int64
231
+
232
+ r.db.Model(&models.{Entity}{}).Count(&total)
233
+ r.db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&items)
234
+
235
+ return items, total, nil
236
+ }
237
+
238
+ func (r *Repository) Get(ctx context.Context, id string) (*models.{Entity}, error) {
239
+ var item models.{Entity}
240
+ if err := r.db.First(&item, "id = ?", id).Error; err != nil {
241
+ return nil, err
242
+ }
243
+ return &item, nil
244
+ }
245
+
246
+ func (r *Repository) Create(ctx context.Context, entity *models.{Entity}) error {
247
+ return r.db.Create(entity).Error
248
+ }
249
+
250
+ func (r *Repository) Update(ctx context.Context, id string, entity *models.{Entity}) error {
251
+ return r.db.Model(&models.{Entity}{}).Where("id = ?", id).Updates(entity).Error
252
+ }
253
+
254
+ func (r *Repository) Delete(ctx context.Context, id string) error {
255
+ return r.db.Delete(&models.{Entity}{}, "id = ?", id).Error
256
+ }
257
+ ```
@@ -43,6 +43,10 @@ pnpm create:module <module-name> [options]
43
43
  - `--with-crud`:包含 CRUD 示例代码。
44
44
  - `--skip-register`:跳过自动注册步骤。
45
45
 
46
+ ## AI Skills
47
+ - Codex:`.codex/skills/keystone-dev`
48
+ - Claude:`.claude/skills/keystone-dev`
49
+
46
50
  ## 目录结构
47
51
  - `apps/web/`:React + Vite 壳与业务模块(`src/modules/*`)。
48
52
  - `apps/server/`:Go API + 模块注册/迁移/种子数据(含 `config.yaml`)。