create-dwy 0.3.3 → 0.4.1
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/package.json +1 -1
- package/src/sync.js +8 -0
- package/templates/claude-global/CLAUDE.md +1 -0
- package/templates/claude-global/rules/backend-security.md +7 -0
- package/templates/claude-global/rules/docs-sync.md +23 -0
- package/templates/claude-global/rules/prefer-open-source.md +28 -0
- package/templates/claude-global/rules/python-code-style.md +3 -0
- package/templates/claude-global/rules/server-security.md +9 -0
- package/templates/claude-global/rules/vue-code-style.md +9 -0
- package/templates/claude-global/skills/dwy-auto-sync/SKILL.md +52 -0
- package/templates/claude-global/skills/dwy-frontend-eui/SKILL.md +29 -18
package/package.json
CHANGED
package/src/sync.js
CHANGED
|
@@ -28,6 +28,14 @@ export async function syncClaude() {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// Sync CLAUDE.md
|
|
32
|
+
const claudeMdSrc = path.join(sourceDir, 'CLAUDE.md')
|
|
33
|
+
if (await fs.pathExists(claudeMdSrc)) {
|
|
34
|
+
await fs.copy(claudeMdSrc, path.join(targetDir, 'CLAUDE.md'))
|
|
35
|
+
syncedCount++
|
|
36
|
+
console.log(chalk.green(' ✓ CLAUDE.md'))
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
const settingsSrc = path.join(sourceDir, 'settings.json')
|
|
32
40
|
if (await fs.pathExists(settingsSrc)) {
|
|
33
41
|
const settingsDest = path.join(targetDir, 'settings.json')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
所有回答必须使用中文。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 文档同步规则
|
|
2
|
+
|
|
3
|
+
代码变更时,必须同步更新所有关联文档。不允许只改代码不更新文档。
|
|
4
|
+
|
|
5
|
+
## 核心原则
|
|
6
|
+
|
|
7
|
+
**代码和文档是一个整体。** 如果一次变更修改了对外可见的 API(props、函数签名、导出类型、命令行参数等),那么描述该 API 的文档必须在同一个 commit 中更新。
|
|
8
|
+
|
|
9
|
+
## 检查清单
|
|
10
|
+
|
|
11
|
+
完成代码变更后,逐项确认:
|
|
12
|
+
|
|
13
|
+
1. **Skills / 速查文档** — 是否有 SKILL.md 或类似的 AI 速查文档描述了被修改的 API?如果有,更新对应条目。
|
|
14
|
+
2. **示例 / Demo 页面** — 新增的功能是否有对应的交互演示?如果没有,补充 demo。
|
|
15
|
+
3. **导航 / 搜索索引** — 新增的页面或组件是否已注册到路由、侧边栏、搜索索引?
|
|
16
|
+
4. **项目 CLAUDE.md** — 模块结构(新增/删除/重命名包或模块)、构建命令、测试命令是否变化?如果是,更新 CLAUDE.md。
|
|
17
|
+
5. **版本号** — 变更是否对外可见?如果是,更新 package.json / pyproject.toml 版本号。
|
|
18
|
+
|
|
19
|
+
## 提交规范
|
|
20
|
+
|
|
21
|
+
- 文档更新应与代码变更在**同一个 commit** 中
|
|
22
|
+
- 遗漏后发现,立即补一个 `docs: sync xxx` 的 commit
|
|
23
|
+
- 纯文档更新用 `docs:` 前缀,代码+文档混合用 `feat:` / `fix:`
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 优先使用成熟开源方案
|
|
2
|
+
|
|
3
|
+
开发新功能时,优先选用成熟的开源项目/库,而不是手写实现。只有在确认没有合适的开源方案时,才自行实现。
|
|
4
|
+
|
|
5
|
+
## 决策流程
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
需要某项功能
|
|
9
|
+
→ 1. 搜索是否有成熟的开源库(npm/PyPI/GitHub stars > 1k、近期有维护)
|
|
10
|
+
→ 有:评估是否适配当前技术栈(Vue 3 / FastAPI / Node.js)
|
|
11
|
+
→ 适配:直接使用,不重复造轮子
|
|
12
|
+
→ 不适配:寻找替代方案
|
|
13
|
+
→ 没有合适的:自行实现,但在代码注释中说明为什么没用现成方案
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 强制规则
|
|
17
|
+
|
|
18
|
+
- **禁止**手写已有成熟方案的功能:日期处理(dayjs/date-fns)、HTTP 请求(axios)、表单校验(zod/vee-validate)、状态管理(pinia)、图表(echarts/chart.js)、富文本(tiptap/quill)、拖拽(vuedraggable/dnd-kit)、虚拟滚动(@tanstack/virtual)、Markdown 渲染(markdown-it)、模糊搜索(fuse.js)
|
|
19
|
+
- **禁止**手写加密/哈希/JWT 算法,必须使用 bcrypt/jose/crypto 等标准库
|
|
20
|
+
- 选用开源库时,优先选择:项目已在用的依赖 > 社区主流方案 > 小众但适合的方案
|
|
21
|
+
|
|
22
|
+
## 例外情况
|
|
23
|
+
|
|
24
|
+
以下情况允许自行实现:
|
|
25
|
+
- 功能极其简单(< 20 行),引入一个库反而增加复杂度
|
|
26
|
+
- 开源库有严重的安全漏洞或已停止维护
|
|
27
|
+
- 开源库的依赖体积过大,与需求不成比例
|
|
28
|
+
- 项目有特殊定制需求,开源库无法满足且改造成本高于自建
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dwy-auto-sync
|
|
3
|
+
description: "create-dwy 发版后自动更新本地 CLI 并同步 Claude Code 配置。触发条件:执行了 npm publish create-dwy、pnpm publish:cli、或用户要求同步 dwy 配置时。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DWY 发版后自动同步
|
|
7
|
+
|
|
8
|
+
当 `create-dwy` 发布新版本后,必须执行以下步骤确保本地 Claude Code 配置与最新版本同步。
|
|
9
|
+
|
|
10
|
+
## 触发时机
|
|
11
|
+
|
|
12
|
+
以下任一情况发生时,执行同步流程:
|
|
13
|
+
|
|
14
|
+
1. 执行了 `npm publish`(在 claude-cli 目录下)
|
|
15
|
+
2. 执行了 `pnpm publish:cli`
|
|
16
|
+
3. 用户要求"同步 dwy"或"更新配置"
|
|
17
|
+
|
|
18
|
+
## 同步流程
|
|
19
|
+
|
|
20
|
+
发版成功后,按顺序执行:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 1. 更新全局 CLI 到最新版
|
|
24
|
+
npm i -g create-dwy@latest
|
|
25
|
+
|
|
26
|
+
# 2. 验证版本
|
|
27
|
+
dwy --version
|
|
28
|
+
|
|
29
|
+
# 3. 同步 Claude Code 配置(skills/rules/hooks/commands/settings)
|
|
30
|
+
dwy sync claude
|
|
31
|
+
|
|
32
|
+
# 4. 验证同步结果
|
|
33
|
+
ls ~/.claude/skills/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 同步了什么
|
|
37
|
+
|
|
38
|
+
`dwy sync claude` 会将以下内容从 CLI 模板同步到 `~/.claude/`:
|
|
39
|
+
|
|
40
|
+
| 目录 | 内容 | 同步方式 |
|
|
41
|
+
|------|------|---------|
|
|
42
|
+
| `~/.claude/skills/` | AI 速查文档 (dwy-frontend-eui, dwy-frontend-core, dwy-backend-base) | 覆盖同名,保留已有 |
|
|
43
|
+
| `~/.claude/rules/` | 编码规范 (python-code-style, vue-code-style, 安全规则等) | 覆盖同名,保留已有 |
|
|
44
|
+
| `~/.claude/hooks/` | 自动化脚本 (pre-git-commit 检查) | 覆盖同名,保留已有 |
|
|
45
|
+
| `~/.claude/commands/` | 自定义命令 | 覆盖同名,保留已有 |
|
|
46
|
+
| `~/.claude/settings.json` | Claude Code 设置 | 浅合并(新 key 加入,同名覆盖,已有独有 key 保留) |
|
|
47
|
+
|
|
48
|
+
## 注意事项
|
|
49
|
+
|
|
50
|
+
- npm 注册表有传播延迟(~1 分钟),如果 `npm i -g create-dwy@latest` 安装的不是刚发布的版本,等待后重试
|
|
51
|
+
- `dwy sync claude` 从 Gitee 仓库拉取模板,确保代码已 push 到 Gitee 后再执行
|
|
52
|
+
- 同步不会删除用户手动添加的 skills/rules,只覆盖同名文件
|
|
@@ -75,30 +75,30 @@ frontend/eui/src/components/{component-name}/types.ts
|
|
|
75
75
|
|
|
76
76
|
| 组件 | 用途 | 关键 Props |
|
|
77
77
|
|------|------|-----------|
|
|
78
|
-
| EInput | 输入框 | v-model, type, placeholder, size, clearable, showPassword, disabled, readonly, maxlength |
|
|
79
|
-
| ETextarea | 多行输入 | v-model, placeholder, rows, autoResize, maxlength, disabled |
|
|
80
|
-
| ENumberField | 数字输入 | v-model, min, max, step, size, disabled |
|
|
81
|
-
| ESelect | 下拉选择 | v-model, options(Option[]), placeholder, clearable, size, disabled |
|
|
78
|
+
| EInput | 输入框 | v-model, type, placeholder, size, clearable, showPassword, disabled, readonly, maxlength, showWordLimit |
|
|
79
|
+
| ETextarea | 多行输入 | v-model, placeholder, rows, autoResize, maxlength, disabled, showWordLimit, minRows, maxRows |
|
|
80
|
+
| ENumberField | 数字输入 | v-model, min, max, step, size, disabled, precision, controlsPosition, placeholder, readonly |
|
|
81
|
+
| ESelect | 下拉选择 | v-model, options(Option[]), placeholder, clearable, size, disabled, filterable, multiple, collapseTags, remote, remoteMethod, loading |
|
|
82
82
|
| ENativeSelect | 原生 select | v-model, options(SelectOption[]), placeholder, disabled |
|
|
83
83
|
| ECombobox | 组合框 | v-model, options(Option[]), placeholder, emptyText, disabled |
|
|
84
84
|
| EAutocomplete | 自动补全 | v-model, fetchSuggestions(async fn), debounce, placeholder |
|
|
85
|
-
| ECheckbox | 复选框 | v-model, label, disabled, indeterminate |
|
|
86
|
-
| ERadio | 单选组 | v-model, options(Option[]), direction(horizontal/vertical), disabled |
|
|
85
|
+
| ECheckbox | 复选框 | v-model, label, disabled, indeterminate, options(Option[]), direction(horizontal/vertical), border |
|
|
86
|
+
| ERadio | 单选组 | v-model, options(Option[]), direction(horizontal/vertical), disabled, optionType(default/button), border, size |
|
|
87
87
|
| ESwitch | 开关 | v-model, label, size, disabled |
|
|
88
88
|
| ETagsInput | 标签输入 | v-model(string[]), placeholder, max, size, disabled |
|
|
89
|
-
| EDatePicker | 日期选择 | v-model, placeholder, format, clearable, disabled |
|
|
89
|
+
| EDatePicker | 日期选择 | v-model, type(date/daterange/month/year), placeholder, startPlaceholder, endPlaceholder, rangeSeparator, format, clearable, disabled, disabledDate, shortcuts(DatePickerShortcut[]) |
|
|
90
90
|
| ETimePicker | 时间选择 | v-model, placeholder, format, hourStep, minuteStep, disabled |
|
|
91
91
|
| EColorPicker | 颜色选择 | v-model, presets(string[]), showAlpha, disabled |
|
|
92
92
|
| ERate | 评分 | v-model, max, allowHalf, showText, disabled |
|
|
93
93
|
| ESlider | 滑块 | v-model(number[]), min, max, step, orientation, disabled |
|
|
94
|
-
| ECascader | 级联选择 | v-model, options(CascaderOption[]), placeholder, filterable, clearable |
|
|
94
|
+
| ECascader | 级联选择 | v-model, options(CascaderOption[]), placeholder, filterable, clearable, lazy, loadFn, multiple, collapseTags |
|
|
95
95
|
| ETreeSelect | 树选择 | v-model, data(TreeNode[]), placeholder, multiple, checkable, disabled |
|
|
96
96
|
| EMention | @提及输入 | v-model, options(MentionOption[]), prefix, loading, placeholder |
|
|
97
97
|
| EInputOTP | OTP 验证码 | v-model, length, disabled, placeholder |
|
|
98
98
|
| EPinInput | PIN 输入 | v-model(string[]), length, mask, otp, type(text/number) |
|
|
99
|
-
| EUpload | 文件上传 | v-model(UploadFile[]), action, accept, multiple, limit, listType(text/picture/picture-card), drag |
|
|
99
|
+
| EUpload | 文件上传 | v-model(UploadFile[]), action, accept, multiple, limit, listType(text/picture/picture-card), drag, beforeUpload, autoUpload, headers, withCredentials |
|
|
100
100
|
| ETransfer | 穿梭框 | v-model, data(TransferItem[]), filterable, titles([string, string]) |
|
|
101
|
-
| EForm | 表单容器 | model, rules(Zod/FormRule[]), labelWidth, labelPosition(left/right/top), size, disabled |
|
|
101
|
+
| EForm | 表单容器 | model, rules(Zod/FormRule[]), labelWidth, labelPosition(left/right/top), size, disabled, inline |
|
|
102
102
|
| EFormItem | 表单项 | (配合 EForm 使用) |
|
|
103
103
|
| EField | 字段布局 | orientation(vertical/horizontal/responsive), invalid |
|
|
104
104
|
| EInputGroup | 输入组 | 子组件 EInputGroupAddon(align) |
|
|
@@ -107,22 +107,22 @@ frontend/eui/src/components/{component-name}/types.ts
|
|
|
107
107
|
|
|
108
108
|
| 组件 | 用途 | 关键 Props |
|
|
109
109
|
|------|------|-----------|
|
|
110
|
-
| ETable | 表格 | data, columns(TableColumn[]), loading, rowKey, striped, bordered, selectable, selectedKeys |
|
|
110
|
+
| ETable | 表格 | data, columns(TableColumn[]), loading, rowKey, striped, bordered, selectable, selectedKeys, expandable, expandedRowKeys, rowClassName, showSummary, summaryMethod, virtual, virtualRowHeight, resizable |
|
|
111
111
|
| EVirtualTable | 虚拟滚动表格 | columns(VirtualTableColumn[]), data, height, estimateRowHeight, rowKey, loading |
|
|
112
112
|
| EDescriptions | 描述列表 | items(DescriptionItem[]), columns, bordered, title |
|
|
113
113
|
| ETimeline | 时间线 | items(TimelineItem[]), reverse |
|
|
114
114
|
| EStatistic | 统计数值 | title, value, prefix, suffix, precision |
|
|
115
|
-
| ETree | 树形控件 | data(TreeNode[]), v-model, checkable, expandedKeys, defaultExpandAll |
|
|
115
|
+
| ETree | 树形控件 | data(TreeNode[]), v-model, checkable, expandedKeys, defaultExpandAll, lazy, loadFn, draggable, filterMethod, filterQuery, checkStrictly |
|
|
116
116
|
| ECalendar | 日历 | v-model, multiple, disabled, locale, minValue, maxValue |
|
|
117
117
|
| ERangeCalendar | 日期范围日历 | v-model({start, end}), disabled, locale, minValue, maxValue |
|
|
118
|
-
| EPagination | 分页 | v-model, total, pageSize, showSizeChanger, pageSizes, showTotal |
|
|
118
|
+
| EPagination | 分页 | v-model, total, pageSize, showSizeChanger, pageSizes, showTotal, jumper, layout, disabled |
|
|
119
119
|
| EBreadcrumb | 面包屑 | items(BreadcrumbItem[]), separator |
|
|
120
120
|
|
|
121
121
|
### 弹层与反馈
|
|
122
122
|
|
|
123
123
|
| 组件 | 用途 | 关键 Props |
|
|
124
124
|
|------|------|-----------|
|
|
125
|
-
| EDialog | 对话框 | v-model:open, title, description, showClose, maxWidth |
|
|
125
|
+
| EDialog | 对话框 | v-model:open, title, description, showClose, maxWidth, draggable, closeOnClickModal, closeOnPressEscape, fullscreen, destroyOnClose |
|
|
126
126
|
| EDrawer | 抽屉 | v-model:open, title, description, direction(top/right/bottom/left), showClose |
|
|
127
127
|
| ESheet | 侧边面板 | v-model:open, title, description, side(top/right/bottom/left), showClose |
|
|
128
128
|
| EAlertDialog | 确认对话框 | v-model:open, title, description, confirmText, cancelText |
|
|
@@ -136,9 +136,9 @@ frontend/eui/src/components/{component-name}/types.ts
|
|
|
136
136
|
|
|
137
137
|
| 组件 | 用途 | 关键 Props |
|
|
138
138
|
|------|------|-----------|
|
|
139
|
-
| ETabs | 标签页 | v-model, items(TabItem[]) |
|
|
140
|
-
| EMenu | 侧边菜单 | v-model, items(MenuItem[]), collapsed |
|
|
141
|
-
| EDropdown | 下拉菜单 | items(DropdownMenuItem[]), side, align, sideOffset |
|
|
139
|
+
| ETabs | 标签页 | v-model, items(TabItem[]), closable, addable, tabPosition(top/bottom/left/right) |
|
|
140
|
+
| EMenu | 侧边菜单 | v-model, items(MenuItem[]), collapsed, router, uniqueOpened, defaultOpeneds |
|
|
141
|
+
| EDropdown | 下拉菜单 | items(DropdownMenuItem[]), side, align, sideOffset, trigger(click/hover), splitButton, buttonText, buttonVariant |
|
|
142
142
|
| EAccordion | 手风琴 | v-model, items(AccordionItemOption[]), multiple, collapsible |
|
|
143
143
|
| ECollapsible | 折叠面板 | v-model(boolean), disabled |
|
|
144
144
|
| EStepper | 步骤条 | v-model, items(StepperItem[]), direction(horizontal/vertical) |
|
|
@@ -191,7 +191,7 @@ frontend/eui/src/components/{component-name}/types.ts
|
|
|
191
191
|
| Composable | 用途 | 返回值 |
|
|
192
192
|
|------------|------|--------|
|
|
193
193
|
| useMessage() | 全局消息提示 | { success, warning, error, info } — 每个接收 string 或 MessageOptions |
|
|
194
|
-
| useNotification() | 通知 | { success, warning, error, info } — 接收 NotificationOptions(title, message, position, duration) |
|
|
194
|
+
| useNotification() | 通知 | { success, warning, error, info } — 接收 NotificationOptions(title, message, position, duration, onClick, closable) |
|
|
195
195
|
| useMessageBox() | 对话确认 | { alert, confirm, prompt } — 返回 Promise<'confirm' \| 'cancel'> |
|
|
196
196
|
| useTheme() | 主题管理 | { isDark, theme, setTheme, toggleDark, colorTheme, setColorTheme } |
|
|
197
197
|
| useConfigProvider() | 读取全局配置 | { size, zIndex, locale } |
|
|
@@ -229,6 +229,8 @@ interface MenuItem {
|
|
|
229
229
|
key: string
|
|
230
230
|
label: string
|
|
231
231
|
icon?: string
|
|
232
|
+
/** Route path for router mode (falls back to key if not provided) */
|
|
233
|
+
path?: string
|
|
232
234
|
children?: MenuItem[]
|
|
233
235
|
disabled?: boolean
|
|
234
236
|
}
|
|
@@ -243,4 +245,13 @@ interface TableColumn<T = any> {
|
|
|
243
245
|
align?: 'left' | 'center' | 'right'
|
|
244
246
|
render?: (row: T, index: number) => any
|
|
245
247
|
}
|
|
248
|
+
|
|
249
|
+
type DatePickerType = 'date' | 'daterange' | 'month' | 'year'
|
|
250
|
+
|
|
251
|
+
interface DatePickerShortcut {
|
|
252
|
+
text: string
|
|
253
|
+
value: Date | Date[] | (() => Date | Date[])
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
type TabPosition = 'top' | 'bottom' | 'left' | 'right'
|
|
246
257
|
```
|