adspecs 0.1.32 → 0.1.34

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.
Files changed (25) hide show
  1. package/.adspecs/paths.json +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codebuddy-plugin/plugin.json +1 -1
  5. package/.qoder-plugin/plugin.json +1 -1
  6. package/.workbuddy-plugin/plugin.json +1 -1
  7. package/CLAUDE.md +2 -2
  8. package/README.md +137 -108
  9. package/package.json +1 -1
  10. package/references/ant6-front-standard/02-/347/273/204/344/273/266/350/247/204/350/214/203.md +7 -0
  11. package/references/ant6-front-standard/03-/345/210/227/350/241/250/350/247/204/350/214/203.md +222 -147
  12. package/references/ant6-front-standard/04-/350/241/250/345/215/225/350/247/204/350/214/203.md +8 -0
  13. package/references/ant6-front-standard/09-/345/270/270/350/247/201/351/227/256/351/242/230/350/247/204/350/214/203.md +1 -1
  14. package/references/ant6-front-standard/index.md +100 -99
  15. package/references/yudaocloud-end-standard/01-Java/345/220/216/347/253/257/347/274/226/347/240/201/350/247/204/350/214/203.md +1166 -0
  16. package/references/yudaocloud-end-standard/02-/346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/344/270/216/344/275/277/347/224/250/350/247/204/350/214/203.md +1023 -0
  17. package/references/yudaocloud-end-standard/03-/346/225/260/346/215/256/345/255/227/345/205/270/344/270/216/350/217/234/345/215/225/350/247/204/350/214/203.md +336 -0
  18. package/references/yudaocloud-end-standard/index.md +14 -3
  19. package/references/yudaocloud-end-standard/system_dict_type.sql +186 -0
  20. package/skills/adspecs-plan/SKILL.md +1 -1
  21. package/skills/adspecs-utest/SKILL.md +62 -40
  22. package/skills/project-init/SKILL.md +4 -4
  23. package/src/lib/paths-defaults.js +1 -1
  24. package/src/lib/readme-gen.js +1 -1
  25. package/references/ant6-front-standard/05-/345/211/215/347/253/257/347/274/226/347/240/201/350/247/204/350/214/203.md +0 -1443
@@ -1,147 +1,222 @@
1
- # 列表规范
2
-
3
- > 适用范围: React 19 + TypeScript 6 + Ant Design 6 + ProComponents
4
- > 版本: v3.3
5
-
6
- ---
7
-
8
- ## 1、列表页标准模式(ProTable)
9
-
10
- > 所有「带筛选 + 分页」的列表都**必须**使用 `ProTable`,**不要再用** `Card + Form + Table`。
11
- > 树形列表(dept/menu)例外,用本地 `dataSource` + `pagination={false}` + `expandable`。
12
-
13
- ### 1.1 标准模板
14
-
15
- ```tsx
16
- import { useRef, useState } from 'react';
17
- import { App, Button, Space } from 'antd';
18
- import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
19
- import { ProTable, type ProColumns, type ActionType } from '@ant-design/pro-components';
20
- import { getXxxPage, deleteXxx, deleteXxxList, type XxxVO } from '@/api/xxx';
21
- import Access from '@/components/Access';
22
- import DictTag from '@/components/DictTag';
23
- import { dateFormatter } from '@/utils/formatTime';
24
- import { useDictStore } from '@/stores/useDictStore';
25
- import XxxModal from './components/XxxModal';
26
-
27
- const XxxPage: React.FC = () => {
28
- const { message, modal } = App.useApp();
29
- const actionRef = useRef<ActionType>(undefined);
30
- const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
31
- const [modalOpen, setModalOpen] = useState(false);
32
- const [editId, setEditId] = useState<number | null>(null);
33
- const getDictOptions = useDictStore((s) => s.getDictOptions);
34
-
35
- const reload = () => actionRef.current?.reload();
36
-
37
- const handleDelete = (record: XxxVO) => {
38
- modal.confirm({
39
- title: '确认删除?', okType: 'danger',
40
- content: `确认删除「${record.name}」吗?`,
41
- onOk: async () => {
42
- await deleteXxx(record.id!);
43
- message.success('删除成功'); reload();
44
- },
45
- });
46
- };
47
-
48
- const handleDeleteBatch = () => {
49
- modal.confirm({
50
- title: '确认批量删除?', okType: 'danger',
51
- content: `确认删除选中的 ${selectedRowKeys.length} 项?`,
52
- onOk: async () => {
53
- await deleteXxxList(selectedRowKeys.map(Number));
54
- message.success('删除成功');
55
- setSelectedRowKeys([]);
56
- reload();
57
- },
58
- });
59
- };
60
-
61
- const columns: ProColumns<XxxVO>[] = [
62
- { title: '名称', dataIndex: 'name', width: 200 },
63
- {
64
- title: '状态', dataIndex: 'status', width: 100,
65
- valueType: 'select',
66
- valueEnum: Object.fromEntries(
67
- getDictOptions('common_status').map((d) => [d.value, { text: d.label }]),
68
- ),
69
- render: (_, r) => <DictTag type="common_status" value={r.status} />,
70
- },
71
- {
72
- title: '创建时间', dataIndex: 'createTime', width: 180,
73
- valueType: 'dateRange',
74
- search: {
75
- transform: (value) => {
76
- if (!Array.isArray(value)) return {};
77
- return { createTimeStart: value[0], createTimeEnd: value[1] };
78
- },
79
- },
80
- render: (_, r) => dateFormatter(r.createTime) || '-',
81
- },
82
- {
83
- title: '操作', key: 'action', width: 140, fixed: 'right', search: false,
84
- render: (_, record) => (
85
- <Space>
86
- <Access code="xxx:update">
87
- <a onClick={() => { setEditId(record.id!); setModalOpen(true); }}>编辑</a>
88
- </Access>
89
- <Access code="xxx:delete">
90
- <a style={{ color: '#ff4d4f' }} onClick={() => handleDelete(record)}>删除</a>
91
- </Access>
92
- </Space>
93
- ),
94
- },
95
- ];
96
-
97
- return (
98
- <>
99
- <ProTable<XxxVO>
100
- columns={columns}
101
- actionRef={actionRef}
102
- rowKey="id"
103
- scroll={{ x: 1200 }}
104
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
- request={async (params: any) => {
106
- const { current, pageSize, ...rest } = params;
107
- const { data } = await getXxxPage({ pageNo: current ?? 1, pageSize: pageSize ?? 10, ...rest });
108
- return { data: data.list, total: data.total, success: true };
109
- }}
110
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
111
- rowSelection={{ selectedRowKeys, onChange: setSelectedRowKeys }}
112
- toolBarRender={() => [
113
- <Access code="xxx:create" key="add">
114
- <Button type="primary" icon={<PlusOutlined />}
115
- onClick={() => { setEditId(null); setModalOpen(true); }}>新增</Button>
116
- </Access>,
117
- <Access code="xxx:delete" key="batch">
118
- <Button danger icon={<DeleteOutlined />}
119
- disabled={selectedRowKeys.length === 0}
120
- onClick={handleDeleteBatch}>批量删除</Button>
121
- </Access>,
122
- ]}
123
- />
124
- <XxxModal open={modalOpen} id={editId}
125
- onSuccess={() => { setModalOpen(false); reload(); }}
126
- onCancel={() => setModalOpen(false)} />
127
- </>
128
- );
129
- };
130
-
131
- export default XxxPage;
132
- ```
133
-
134
- ### 1.2 ProTable 列定义关键规则
135
-
136
- | 场景 | 写法 |
137
- | ------------- | ------------------------------------------------------------------------------------------ |
138
- | 隐藏搜索 | `search: false`(**不是** `hideInSearch`) |
139
- | 下拉搜索 | `valueType: 'select'` + `valueEnum: Object.fromEntries(getDictOptions(...).map(...))` |
140
- | 日期区间 | `valueType: 'dateRange'` + `search.transform` 拆 `xxxStart/xxxEnd` |
141
- | 日期区间渲染 | **必须用 `render`,不要用 `renderText`** |
142
- | 长 label 搜索 | `search={{ labelWidth: 'auto' }}`(在 ProTable 上) |
143
- | request 参数 | 固定加 `// eslint-disable-next-line @typescript-eslint/no-explicit-any` 允许 `params: any` |
144
- | 树形表 | 去掉 `request`,改用 `dataSource={tree}` + `pagination={false}` + `expandable` |
145
-
146
- ---
147
-
1
+ # 列表规范
2
+
3
+ > 适用范围: React 19 + TypeScript 6 + Ant Design 6 + ProComponents
4
+ > 版本: v3.4
5
+
6
+ ---
7
+
8
+ ## 1、列表页标准模式(ProTable)
9
+
10
+ > 所有「带筛选 + 分页」的列表都**必须**使用 `ProTable`,**不要再用** `Card + Form + Table`。
11
+ > 树形列表(dept/menu)例外,用本地 `dataSource` + `pagination={false}` + `expandable`。
12
+
13
+ **三条硬性要求**:
14
+
15
+ 1. **高级筛选区**:`search={{ layout: 'vertical', span: <按筛选项数量分档> }}` —— 表单项 **vertical 布局**(label 在上),**span 按筛选项数量分档**(见 §1.1a)
16
+ 2. **操作栏**:若表格有操作列,宽度统一 `width: ACTION_COL_WIDTH`(= **150**,以 `TableActions` 组件导出为准,`fixed: 'right'`,`search: false`)
17
+ 3. **操作项展示规则**:操作项 **≤ 3 个平铺展示**;**> 3 个**时前 3 个平铺,其余收进 `...`,**鼠标悬停展开**。展示顺序按**后台菜单功能设置排序**(菜单树的按钮节点 `sort` 升序);具体显示的项**按用户权限与数据状态动态计算,不得写死**——统一使用通用组件 `<TableActions />`(见 §1.3)
18
+
19
+ ### 1.1a 高级筛选区 span 分档
20
+
21
+ > vertical 布局下,span 决定每行可容纳的筛选项数量(24 栅格制)。**筛选项数量 N** = 未设 `search: false` 且带 `dataIndex`/`valueType` 的列数(含 `hideInTable: true` 的隐藏搜索列,如日期区间拆分列)。
22
+
23
+ | 筛选项数量 N | span | 每行项数 | 示例 |
24
+ | ------------ | ---- | -------- | ---- |
25
+ | N 2 | 8 | 3 | `search={{ layout: 'vertical', span: 8 }}` |
26
+ | N = 3 | 6 | 4 | `search={{ layout: 'vertical', span: 6 }}` |
27
+ | N = 4-6 | 4 | 6 | `search={{ layout: 'vertical', span: 4 }}` |
28
+
29
+ - **日期区间(dateRange)**:组件约占两栏宽度。当 N = 4-6 且含日期区间时,日期列通过 `order`(Form 排序,数值大者靠后)排到搜索表单**最后**,自然换行到第二行;N ≤ 3(span 8/6)时日期项宽度充足,无需处理
30
+ - **上限**:单页筛选项建议 6 项;超过时靠高级筛选区默认「展开/收起」自折叠,不刻意堆满
31
+
32
+ ### 1.1 标准模板
33
+
34
+ ```tsx
35
+ import { useRef, useState } from 'react';
36
+ import { App, Button, Space } from 'antd';
37
+ import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
38
+ import { ProTable, type ProColumns, type ActionType } from '@ant-design/pro-components';
39
+ import { getXxxPage, deleteXxx, deleteXxxList, type XxxVO } from '@/api/xxx';
40
+ import Access from '@/components/Access';
41
+ import TableActions, { ACTION_COL_WIDTH, type TableActionItem } from '@/components/TableActions';
42
+ import DictTag from '@/components/DictTag';
43
+ import { dateFormatter } from '@/utils/formatTime';
44
+ import { useDictStore } from '@/stores/useDictStore';
45
+ import XxxModal from './components/XxxModal';
46
+
47
+ const XxxPage: React.FC = () => {
48
+ const { message, modal } = App.useApp();
49
+ const actionRef = useRef<ActionType>(undefined);
50
+ const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
51
+ const [modalOpen, setModalOpen] = useState(false);
52
+ const [editId, setEditId] = useState<number | null>(null);
53
+ const getDictOptions = useDictStore((s) => s.getDictOptions);
54
+
55
+ const reload = () => actionRef.current?.reload();
56
+
57
+ const handleDelete = (record: XxxVO) => {
58
+ modal.confirm({
59
+ title: '确认删除?', okType: 'danger',
60
+ content: `确认删除「${record.name}」吗?`,
61
+ onOk: async () => {
62
+ await deleteXxx(record.id!);
63
+ message.success('删除成功'); reload();
64
+ },
65
+ });
66
+ };
67
+
68
+ const handleDeleteBatch = () => {
69
+ modal.confirm({
70
+ title: '确认批量删除?', okType: 'danger',
71
+ content: `确认删除选中的 ${selectedRowKeys.length} 项?`,
72
+ onOk: async () => {
73
+ await deleteXxxList(selectedRowKeys.map(Number));
74
+ message.success('删除成功');
75
+ setSelectedRowKeys([]);
76
+ reload();
77
+ },
78
+ });
79
+ };
80
+
81
+ /**
82
+ * 操作项定义(顺序即默认展示顺序;权限与数据状态驱动显隐,不写死):
83
+ * - permission:按钮权限码(菜单树 type=3 按钮),未授权自动隐藏
84
+ * - show:数据状态判定(布尔或 (record) => boolean),如「草稿才显示编辑」
85
+ * - 最终展示顺序由 TableActions 按当前菜单按钮 sort 重排
86
+ */
87
+ const buildActionItems = (record: XxxVO): TableActionItem<XxxVO>[] => {
88
+ const items: TableActionItem<XxxVO>[] = [];
89
+ const push = (key: string, show: boolean, permission: string, label: string, danger?: boolean) => {
90
+ if (show) items.push({ key, permission, label, danger, onClick: () => setEditId(record.id!) && setModalOpen(true) });
91
+ };
92
+ push('edit', true, 'xxx:update', '编辑');
93
+ push('delete', record.status !== 'PUBLISHED', 'xxx:delete', '删除', true);
94
+ return items;
95
+ };
96
+
97
+ const columns: ProColumns<XxxVO>[] = [
98
+ { title: '名称', dataIndex: 'name', width: 200 },
99
+ {
100
+ title: '状态', dataIndex: 'status', width: 100,
101
+ valueType: 'select',
102
+ valueEnum: Object.fromEntries(
103
+ getDictOptions('common_status').map((d) => [d.value, { text: d.label }]),
104
+ ),
105
+ render: (_, r) => <DictTag type="common_status" value={r.status} />,
106
+ },
107
+ {
108
+ title: '创建时间', dataIndex: 'createTime', width: 180,
109
+ valueType: 'dateRange',
110
+ search: {
111
+ transform: (value) => {
112
+ if (!Array.isArray(value)) return {};
113
+ return { createTimeStart: value[0], createTimeEnd: value[1] };
114
+ },
115
+ },
116
+ render: (_, r) => dateFormatter(r.createTime) || '-',
117
+ },
118
+ {
119
+ title: '操作', key: 'action', width: ACTION_COL_WIDTH, fixed: 'right', search: false,
120
+ render: (_, record) => <TableActions record={record} items={buildActionItems(record)} />,
121
+ },
122
+ ];
123
+
124
+ return (
125
+ <>
126
+ <ProTable<XxxVO>
127
+ columns={columns}
128
+ actionRef={actionRef}
129
+ rowKey="id"
130
+ scroll={{ x: 1200 }}
131
+ // 高级筛选区:表单项 vertical 布局,span 按筛选项数量分档(本示例 3 项 → span 6,见 §1.1a)
132
+ search={{ layout: 'vertical', span: 6 }}
133
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
+ request={async (params: any) => {
135
+ const { current, pageSize, ...rest } = params;
136
+ const { data } = await getXxxPage({ pageNo: current ?? 1, pageSize: pageSize ?? 10, ...rest });
137
+ return { data: data.list, total: data.total, success: true };
138
+ }}
139
+ pagination={{ defaultPageSize: 10, showSizeChanger: true }}
140
+ rowSelection={{ selectedRowKeys, onChange: setSelectedRowKeys }}
141
+ toolBarRender={() => [
142
+ <Access code="xxx:create" key="add">
143
+ <Button type="primary" icon={<PlusOutlined />}
144
+ onClick={() => { setEditId(null); setModalOpen(true); }}>新增</Button>
145
+ </Access>,
146
+ <Access code="xxx:delete" key="batch">
147
+ <Button danger icon={<DeleteOutlined />}
148
+ disabled={selectedRowKeys.length === 0}
149
+ onClick={handleDeleteBatch}>批量删除</Button>
150
+ </Access>,
151
+ ]}
152
+ />
153
+ <XxxModal open={modalOpen} id={editId}
154
+ onSuccess={() => { setModalOpen(false); reload(); }}
155
+ onCancel={() => setModalOpen(false)} />
156
+ </>
157
+ );
158
+ };
159
+
160
+ export default XxxPage;
161
+ ```
162
+
163
+ ### 1.2 ProTable 列定义关键规则
164
+
165
+ | 场景 | 写法 |
166
+ | ------------- | ------------------------------------------------------------------------------------------ |
167
+ | 隐藏搜索 | `search: false`(**不是** `hideInSearch`) |
168
+ | 下拉搜索 | `valueType: 'select'` + `valueEnum: Object.fromEntries(getDictOptions(...).map(...))` |
169
+ | 日期区间 | `valueType: 'dateRange'` + `search.transform` 拆 `xxxStart/xxxEnd` |
170
+ | 日期区间渲染 | **必须用 `render`,不要用 `renderText`** |
171
+ | 长 label 搜索 | `search={{ labelWidth: 'auto' }}`(在 ProTable 上) |
172
+ | 高级筛选区 | `search={{ layout: 'vertical', span: <分档> }}`(表单项垂直,span 按筛选项数量分档,见 §1.1a) |
173
+ | 操作列 | `width: ACTION_COL_WIDTH`(150)+ `fixed: 'right'` + `search: false` + `<TableActions />`;操作项文字较多时可自定义加宽(如 180) |
174
+ | request 参数 | 固定加 `// eslint-disable-next-line @typescript-eslint/no-explicit-any` 允许 `params: any` |
175
+ | 树形表 | 去掉 `request`,改用 `dataSource={tree}` + `pagination={false}` + `expandable` |
176
+
177
+ ### 1.3 通用操作组件 TableActions
178
+
179
+ > 路径:`web-ui/src/components/TableActions/index.tsx`
180
+
181
+ **为什么做成通用组件**:操作项显隐 = 权限 × 数据状态、展示顺序 = 后台菜单 sort、折叠规则 = ≤3 平铺 />3 `...` 悬停展开——这些是所有列表页共通的展示逻辑,若每页手写(如早期 agent-factory 的 renderActions)必然重复且易写死。抽成组件后,页面只需声明「有哪些操作项」及其权限码/状态判定/回调,**展示规则由组件统一保证**。
182
+
183
+ **Props**:
184
+
185
+ ```ts
186
+ export interface TableActionItem<T = unknown> {
187
+ key: string;
188
+ label?: React.ReactNode; // 按钮文案(显式传优先;否则取菜单按钮 name)
189
+ permission?: string; // 权限码(菜单树 type=3 按钮 permission;不传=常显)
190
+ show?: boolean | ((record: T) => boolean); // 数据状态显隐
191
+ danger?: boolean; // 危险操作(红色)
192
+ color?: string; // 自定义文字颜色(如橙色警告操作;danger 优先)
193
+ icon?: React.ReactNode;
194
+ onClick?: (record: T) => void;
195
+ }
196
+ export interface TableActionsProps<T = unknown> {
197
+ record: T;
198
+ items: TableActionItem<T>[];
199
+ max?: number; // 平铺上限,默认 3
200
+ sortByMenu?: boolean; // 是否按当前菜单按钮 sort 排序,默认 true
201
+ }
202
+ export const ACTION_COL_WIDTH = 150; // 操作栏列宽
203
+ ```
204
+
205
+ **机制**:
206
+
207
+ 1. **过滤**:`permission` 非空且未授权 → 隐藏;`show` 为函数时以 `record` 计算,为 `false` 隐藏
208
+ 2. **排序**:`sortByMenu`(默认开)从 `useAuthStore.menus` 取当前路由(`useLocation().pathname` 最长前缀匹配)对应菜单节点的 `type===3` 按钮子节点,按 `sort` 升序得到权限顺序,`items` 按 `permission ?? key` 对齐重排;**菜单树未匹配或无按钮节点时退化为 items 传入顺序**(不报错)
209
+ 3. **折叠**:过滤排序后 ≤ `max`(默认 3)平铺;> `max` 前 `max` 个平铺,其余进 `Dropdown trigger={['hover']}`(`...` 悬停展开)
210
+ 4. **样式**:`<a>` 链接形式,`danger` 红色(`#ff4d4f`)、`color` 自定义色(danger 优先)
211
+
212
+ **接入示例**(见 §1.1 模板 `buildActionItems`):页面定义操作项数组(permission + show + onClick),操作列渲染 `<TableActions record={record} items={buildActionItems(record)} />` 即可。
213
+
214
+ **注意事项**:
215
+
216
+ - 排序依赖**后台菜单管理已配置按钮节点及 sort**(系统管理 → 菜单管理,type=按钮);未配置时按 items 传入顺序展示,不影响功能
217
+ - 操作列宽度默认 `ACTION_COL_WIDTH`(150);操作项文字较多导致换行时,页面可自定义加宽(如 180),不必拘泥默认值
218
+ - 操作项的「数据状态判定」在页面内实现(如 `getAgentRowActions(record)`),组件不感知业务
219
+ - 危险操作(删除/驳回/废弃等)传 `danger: true`,无需再手动加色
220
+ - 批量操作(toolBarRender 的新增/批量删除)不属于行操作项,不走 TableActions
221
+
222
+ ---
@@ -13,6 +13,13 @@
13
13
 
14
14
  2、表单较复杂(字段 ≥ 4 个)或业务流程需要连续操作时,推荐使用右侧 Drawer 替代 Modal。
15
15
 
16
+ 3、在使用drawer抽屉后的表单有需要弹窗选择的弹窗,推荐使用 Modal
17
+
18
+ 4、使用抽屉drawer组件时,必须使用 `closable={{ placement: 'end' }}`和`mask={{ closable: false }}`,其宽度必须使用`size`不能使用`width`
19
+
20
+ 5、使用抽屉drawer组件时,内容区块必须使用<Card></Card>组建包裹
21
+
22
+
16
23
  > 根据表单字段数量分级选择布局和 Drawer 宽度。
17
24
 
18
25
  | 字段数量 | 布局 | Drawer 宽度 | Form layout | 说明 |
@@ -307,6 +314,7 @@ const XxxDrawer: React.FC<Props> = ({ open, id, onSuccess, onClose }) => {
307
314
  - `originData = useRef()` 保留服务端字段,提交时合并:`{ ...originData.current, ...values, id }`
308
315
  - 编辑模式下隐藏字段用 `hidden={!!id}` 而非条件渲染(条件渲染会让 `validateFields` 跳过该字段)
309
316
  - 用 `destroyOnHidden` 自动清理状态,**不要**手动 reset
317
+ - Drawer 宽度必须使用`size`不能使用`width`
310
318
 
311
319
  ---
312
320
 
@@ -1,7 +1,7 @@
1
1
  # 常见问题规范(必读陷阱)
2
2
 
3
3
  > 适用范围: React 19 + TypeScript 6 + Ant Design 6 + ProComponents
4
- > 版本: v3.3
4
+ > 版本: v3.4
5
5
 
6
6
  ---
7
7
 
@@ -1,100 +1,101 @@
1
- # 前端编码规范索引
2
-
3
- > **适用范围**: React 19 + TypeScript 6 + Ant Design 6 + ProComponents
4
- > **版本**: v3.3
5
-
6
- ---
7
-
8
- 本目录包含 `front-demo`和`web-ui` 两个前端项目的前端开发规则。生成或修改代码前,先按任务类型读取对应规则。
9
-
10
- ## 文件清单
11
-
12
- | 序号 | 文件名 | 主要内容 |
13
- | ---- | -------------------------------------------------- | ---------------------------------------------------------------------------------------- |
14
- | 01 | [01-基础规范.md](./01-基础规范.md) | 一 ~ 技术栈基线、目录结构、命名、编码风格、TypeScript、样式、Vue→React 迁移映射表、总结 |
15
- | 02 | [02-组件规范.md](./02-组件规范.md) | React 组件规范(函数组件 / Props / Hook)、上传组件、时间格式化 |
16
- | 03 | [03-列表规范.md](./03-列表规范.md) | ProTable 列表页标准模式(标准模板、列定义规则) |
17
- | 04 | [04-表单规范.md](./04-表单规范.md) | Modal / Drawer 使用标准规范(布局分级、标准模板、一栏~四栏布局) |
18
- | 05 | [05-路由状态接口规范.md](./05-路由状态接口规范.md) | 路由(动态路由 / 守卫)、Zustand 状态管理、API 接口规范 |
19
- | 06 | [06-国际化规范.md](./06-国际化规范.md) | react-i18next 多语言支持(命名空间、语言包结构、切换) |
20
- | 07 | [07-字典权限规范.md](./07-字典权限规范.md) | 字典系统(DictTag / getDictOptions)、权限系统(Access / useAccess) |
21
- | 08 | [08-性能质量规范.md](./08-性能质量规范.md) | 性能优化(lazy / memo / useMemo)、代码质量标准(复杂度 / ESLint / 构建) |
22
- | 09 | [09-常见问题规范.md](./09-常见问题规范.md) | 项目实际踩坑与解决方案(16 条必读陷阱) |
23
-
24
- ---
25
-
26
- ## 按场景推荐阅读
27
-
28
- ### 新增普通业务页面
29
-
30
- 1. `01-基础规范.md` — 熟悉技术栈与目录约定
31
- 2. `05-路由状态接口规范.md` — 路由、状态、接口规范
32
- 3. `03-列表规范.md` — ProTable 列表页模板
33
- 4. `04-表单规范.md` — Modal / Drawer 表单模板
34
- 5. `07-字典权限规范.md` — 字典渲染与按钮权限
35
-
36
- ### 新增列表页
37
-
38
- 1. `03-列表规范.md` — ProTable 标准模板与列规则
39
- 2. `07-字典权限规范.md` — 字典下拉 + 权限按钮
40
- 3. `02-组件规范.md` — 时间格式化与上传组件
41
-
42
- ### 新增表单 / 流程页面
43
-
44
- 1. `04-表单规范.md` — Modal / Drawer 布局分级与标准模板
45
- 2. `05-路由状态接口规范.md` — API 接口规范
46
- 3. `09-常见问题规范.md` — 必读陷阱(validateFields、Upload、Tree 等)
47
-
48
- ### 国际化 / 字典 / 权限模块
49
-
50
- 1. `06-国际化规范.md` — i18n 命名空间、语言包结构
51
- 2. `07-字典权限规范.md` — 字典与权限系统
52
-
53
- ### 代码评审 / 质量检查
54
-
55
- 1. `08-性能质量规范.md` — 性能与质量标准
56
- 2. `09-常见问题规范.md` — 16 条踩坑清单
57
- 3. `01-基础规范.md` — 命名 / 编码风格 / TypeScript 规范
58
-
59
- ### 从 Vue 迁移到 React
60
-
61
- 1. `01-基础规范.md` — 熟悉技术栈与目录约定
62
- 2. `vue迁移到react规范.md` — Vue → React 迁移映射表
63
- 3. `09-常见问题规范.md` — 常见差异点
64
-
65
- ---
66
-
67
-
68
- ## 维护说明
69
-
70
- - 拆分后的各文件章节号已独立重编号,每份均从「一」开始,便于独立阅读。
71
- - 更新规范时,请同步修改对应拆分文件及本索引。
72
-
73
- ## 总结
74
-
75
- 本规范文档涵盖了 React 19 + TypeScript 6 + Ant Design 6 项目的完整开发规范。团队成员必须严格遵守,以确保代码质量和协作效率。
76
-
77
- **重要提醒**:
78
- 1. 所有新代码必须符合本规范
79
- 2. 代码评审时重点检查规范遵守情况
80
- 3. 定期更新规范以适应项目发展
81
- 4. 遇到规范未覆盖的情况,及时讨论并补充
82
-
83
- **新模块自检清单**:
84
-
85
- - [ ] 文件路径与后端菜单 path 对齐
86
- - [ ] API、Mock handler、Mock data、菜单、权限码 五处全部更新
87
- - [ ] 所有时间字段用 `dateFormatter` 渲染
88
- - [ ] 所有字典字段用 `<DictTag>` + `valueEnum`
89
- - [ ] 所有按钮用 `<Access code="...">` 包裹
90
- - [ ] Modal 用 `open/id/onSuccess/onCancel` 四件套 + `originData` 合并
91
- - [ ] ProTable 而非手撸 Card+Form+Table
92
- - [ ] `npm run build` 通过
93
- - [ ] `npx eslint <new-files>` 零错误
94
- - [ ] 关键逻辑加中文注释,复杂分支说明「为什么这么写」
95
-
96
- ---
97
-
98
- **文档结束**
99
-
1
+ # 前端编码规范索引
2
+
3
+ > **适用范围**: React 19 + TypeScript 6 + Ant Design 6 + ProComponents
4
+ > **版本**: v3.3
5
+
6
+ ---
7
+
8
+ 本目录包含 `front-demo`和`web-ui` 两个前端项目的前端开发规则。生成或修改代码前,先按任务类型读取对应规则。
9
+
10
+ ## 文件清单
11
+
12
+ | 序号 | 文件名 | 主要内容 |
13
+ | ---- | -------------------------------------------------- | ---------------------------------------------------------------------------------------- |
14
+ | 01 | [01-基础规范.md](./01-基础规范.md) | 一 ~ 技术栈基线、目录结构、命名、编码风格、TypeScript、样式、Vue→React 迁移映射表、总结 |
15
+ | 02 | [02-组件规范.md](./02-组件规范.md) | React 组件规范(函数组件 / Props / Hook)、上传组件、时间格式化 |
16
+ | 03 | [03-列表规范.md](./03-列表规范.md) | ProTable 列表页标准模式(标准模板、列定义规则) |
17
+ | 04 | [04-表单规范.md](./04-表单规范.md) | Modal / Drawer 使用标准规范(布局分级、标准模板、一栏~四栏布局) |
18
+ | 05 | [05-路由状态接口规范.md](./05-路由状态接口规范.md) | 路由(动态路由 / 守卫)、Zustand 状态管理、API 接口规范 |
19
+ | 06 | [06-国际化规范.md](./06-国际化规范.md) | react-i18next 多语言支持(命名空间、语言包结构、切换) |
20
+ | 07 | [07-字典权限规范.md](./07-字典权限规范.md) | 字典系统(DictTag / getDictOptions)、权限系统(Access / useAccess) |
21
+ | 08 | [08-性能质量规范.md](./08-性能质量规范.md) | 性能优化(lazy / memo / useMemo)、代码质量标准(复杂度 / ESLint / 构建) |
22
+ | 09 | [09-常见问题规范.md](./09-常见问题规范.md) | 项目实际踩坑与解决方案(16 条必读陷阱) |
23
+
24
+ ---
25
+
26
+ ## 按场景推荐阅读
27
+
28
+ ### 新增普通业务页面
29
+
30
+ 1. `01-基础规范.md` — 熟悉技术栈与目录约定
31
+ 2. `05-路由状态接口规范.md` — 路由、状态、接口规范
32
+ 3. `03-列表规范.md` — ProTable 列表页模板
33
+ 4. `04-表单规范.md` — Modal / Drawer 表单模板
34
+ 5. `07-字典权限规范.md` — 字典渲染与按钮权限
35
+
36
+ ### 新增列表页
37
+
38
+ 1. `03-列表规范.md` — ProTable 标准模板与列规则
39
+ 2. `07-字典权限规范.md` — 字典下拉 + 权限按钮
40
+ 3. `02-组件规范.md` — 时间格式化与上传组件
41
+
42
+ ### 新增表单 / 流程页面
43
+
44
+ 1. `04-表单规范.md` — Modal / Drawer 布局分级与标准模板
45
+ 2. `05-路由状态接口规范.md` — API 接口规范
46
+ 3. `09-常见问题规范.md` — 必读陷阱(validateFields、Upload、Tree 等)
47
+
48
+ ### 国际化 / 字典 / 权限模块
49
+
50
+ 1. `06-国际化规范.md` — i18n 命名空间、语言包结构
51
+ 2. `07-字典权限规范.md` — 字典与权限系统
52
+
53
+ ### 代码评审 / 质量检查
54
+
55
+ 1. `08-性能质量规范.md` — 性能与质量标准
56
+ 2. `09-常见问题规范.md` — 16 条踩坑清单
57
+ 3. `01-基础规范.md` — 命名 / 编码风格 / TypeScript 规范
58
+
59
+ ### 从 Vue 迁移到 React
60
+
61
+ 1. `01-基础规范.md` — 熟悉技术栈与目录约定
62
+ 2. `vue迁移到react规范.md` — Vue → React 迁移映射表
63
+ 3. `09-常见问题规范.md` — 常见差异点
64
+
65
+ ---
66
+
67
+
68
+ ## 维护说明
69
+
70
+ - 拆分后的各文件章节号已独立重编号,每份均从「一」开始,便于独立阅读。
71
+ - 更新规范时,请同步修改对应拆分文件及本索引。
72
+
73
+ ## 总结
74
+
75
+ 本规范文档涵盖了 React 19 + TypeScript 6 + Ant Design 6 项目的完整开发规范。团队成员必须严格遵守,以确保代码质量和协作效率。
76
+
77
+ **重要提醒**:
78
+ 1. 所有新代码必须符合本规范
79
+ 2. 代码评审时重点检查规范遵守情况
80
+ 3. 定期更新规范以适应项目发展
81
+ 4. 遇到规范未覆盖的情况,及时讨论并补充
82
+
83
+ **新模块自检清单**:
84
+
85
+ - [ ] 文件路径与后端菜单 path 对齐
86
+ - [ ] API、Mock handler、Mock data、菜单、权限码 五处全部更新
87
+ - [ ] 所有时间字段用 `dateFormatter` 渲染
88
+ - [ ] 所有字典字段用 `<DictTag>` + `valueEnum`
89
+ - [ ] 所有按钮用 `<Access code="...">` 包裹
90
+ - [ ] Modal 用 `open/id/onSuccess/onCancel` 四件套 + `originData` 合并
91
+ - [ ] ProTable 而非手撸 Card+Form+Table
92
+ - [ ] `npm run build` 通过
93
+ - [ ] `npx eslint <new-files>` 零错误
94
+ - [ ] 关键逻辑加中文注释,复杂分支说明「为什么这么写」
95
+ - [ ] 是否符合09-常见问题规范.md
96
+
97
+ ---
98
+
99
+ **文档结束**
100
+
100
101
  *本文档作为前端开发的标准规范,所有开发人员必须严格遵守。*