docs(claude): 清理和优化CLAUDE.md项目文档规范

优化CLAUDE.md文档结构,移除重复和过时的示例代码,提高文档的可读性和实用性。

主要变更:
- 删除重复的按钮示例代码片段
- 精简弹框组件使用示例
- 优化图标使用规范的代码示例
- 统一代码样式和格式
- 保持核心规范要求不变

文档优化后更加简洁明了,便于开发团队参考和遵循。
This commit is contained in:
Leo 2025-07-09 18:32:38 +08:00
parent 4264ef36b7
commit 0f98692b25

331
CLAUDE.md
View File

@ -368,54 +368,6 @@ coiMsgBox('确定要删除吗?', '删除确认').then(() => {
- ❌ 图标与功能语义不匹配 - ❌ 图标与功能语义不匹配
- ❌ 在表格列表页面使用圆角按钮(`round` 属性) - ❌ 在表格列表页面使用圆角按钮(`round` 属性)
### 示例:完整的页面按钮实现
```vue
<template>
<div class="page-actions">
<!-- 主要操作按钮 -->
<NButton v-permission="PERMISSIONS.USER.ADD" type="primary" @click="handleAdd">
<template #icon>
<NIcon><icon-park-outline:plus /></NIcon>
</template>
新增
</NButton>
<!-- 批量操作按钮 -->
<NButton type="error" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
<template #icon>
<NIcon><icon-park-outline:delete /></NIcon>
</template>
删除
</NButton>
<!-- 功能按钮 -->
<NButton @click="handleExport">
<template #icon>
<NIcon><icon-park-outline:download /></NIcon>
</template>
导出
</NButton>
<!-- 搜索重置按钮 -->
<NButton type="primary" @click="handleSearch">
<template #icon>
<NIcon><icon-park-outline:search /></NIcon>
</template>
搜索
</NButton>
<NButton @click="handleReset">
<template #icon>
<NIcon><icon-park-outline:refresh /></NIcon>
</template>
重置
</NButton>
</div>
</template>
```
**遵循此规范可确保项目界面的一致性和专业性!**
### 🚀 render函数中图标渲染规范强制要求 ### 🚀 render函数中图标渲染规范强制要求
**在DataTable等组件的render函数中使用图标时必须遵循以下规范** **在DataTable等组件的render函数中使用图标时必须遵循以下规范**
@ -528,41 +480,6 @@ const columns: DataTableColumns<DataType> = [
default: () => '编辑', default: () => '编辑',
})) }))
} }
// 删除按钮(带确认)
if (hasPermission('delete')) {
buttons.push(h(NPopconfirm, {
onPositiveClick: () => handleDelete(row.id),
negativeText: '取消',
positiveText: '确定',
}, {
default: () => '确定删除此项吗?',
trigger: () => h(NButton, {
type: 'error',
size: 'small',
}, {
icon: () => h(NIcon, { size: 14, style: 'transform: translateY(-1px)' }, {
default: () => h(IconParkOutlineDelete)
}),
default: () => '删除',
}),
}))
}
// 设置按钮
if (hasPermission('setting')) {
buttons.push(h(NButton, {
type: 'warning',
size: 'small',
onClick: () => handleSetting(row),
}, {
icon: () => h(NIcon, { size: 14, style: 'transform: translateY(-1px)' }, {
default: () => h(IconParkOutlineSetting)
}),
default: () => '设置',
}))
}
return h('div', { class: 'flex items-center justify-center gap-2' }, buttons) return h('div', { class: 'flex items-center justify-center gap-2' }, buttons)
}, },
}, },
@ -780,40 +697,6 @@ const deleteDialogRef = ref()
</div> </div>
</template> </template>
</CoiDialog> </CoiDialog>
<!-- 仅查看类弹框示例(无确认按钮) -->
<CoiDialog
ref="viewDialogRef"
title="查看详情"
:width="600"
height="auto"
cancel-text="关闭"
:show-confirm="false"
@coi-cancel="handleClose"
>
<template #content>
<div class="p-3">
<!-- 查看内容 -->
</div>
</template>
</CoiDialog>
<!-- 禁用ESC键关闭的弹框示例 -->
<CoiDialog
ref="criticalDialogRef"
title="重要操作确认"
:width="600"
:close-on-esc="false"
:mask-closable="false"
@coi-confirm="handleCriticalConfirm"
@coi-cancel="handleCriticalCancel"
>
<template #content>
<div class="p-3">
<p class="text-red-600">此操作不可逆,请谨慎操作!</p>
</div>
</template>
</CoiDialog>
</template> </template>
``` ```
@ -1069,20 +952,6 @@ var(--info-color) /* 信息色 */
</template> </template>
新增 新增
</NButton> </NButton>
<NButton type="error" @click="handleDelete">
<template #icon>
<NIcon><icon-park-outline:delete /></NIcon>
</template>
删除
</NButton>
<NButton @click="handleExport">
<template #icon>
<NIcon><icon-park-outline:download /></NIcon>
</template>
导出
</NButton>
</div> </div>
<!-- 数据表格 - 表头不加粗,使用默认样式 --> <!-- 数据表格 - 表头不加粗,使用默认样式 -->
@ -1349,62 +1218,6 @@ import { coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
</template> </template>
新增 新增
</NButton> </NButton>
<NButton type="error" @click="handleDelete">
<template #icon>
<NIcon><icon-park-outline:delete /></NIcon>
</template>
删除
</NButton>
<NButton @click="handleExport">
<template #icon>
<NIcon><icon-park-outline:download /></NIcon>
</template>
导出
</NButton>
<NButton type="primary" @click="handleSearch">
<template #icon>
<NIcon><icon-park-outline:search /></NIcon>
</template>
搜索
</NButton>
<NButton @click="handleReset">
<template #icon>
<NIcon><icon-park-outline:refresh /></NIcon>
</template>
重置
</NButton>
</div>
</template>
```
### 错误示例(严格禁止)
```vue
<template>
<div class="page-actions">
<!-- ❌ 错误:使用圆角按钮 -->
<NButton type="primary" round @click="handleAdd">
<template #icon>
<NIcon><icon-park-outline:plus /></NIcon>
</template>
新增
</NButton>
<!-- ❌ 错误:只有文字没有图标 -->
<NButton type="primary" @click="handleAdd">
新增
</NButton>
<!-- ❌ 错误:只有图标没有文字 -->
<NButton type="primary" @click="handleAdd">
<template #icon>
<NIcon><icon-park-outline:plus /></NIcon>
</template>
</NButton>
</div> </div>
</template> </template>
``` ```
@ -1750,3 +1563,147 @@ import { coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
- Node.js 21.x - Node.js 21.x
- pnpm 10.x - pnpm 10.x
- 现代浏览器支持ES6+ - 现代浏览器支持ES6+
## 🔢 雪花ID和大数字处理规范强制要求
**项目使用雪花ID算法生成唯一标识必须严格按照以下规范处理大数字精度问题**
### 问题背景
**JavaScript数字精度限制**
- 雪花ID长度19位数字`194285920715864064`
- JavaScript安全整数范围`Number.MAX_SAFE_INTEGER = 9007199254740991`16位数字
- **超过安全整数范围的数字会发生精度丢失**
**典型问题示例**
```text
// 精度丢失示例
194285920715864064 变成 194285920715864060 // 末尾数字被修改
```
### 核心原则
1. **全链路字符串保持**从数据库到前端再到API调用都保持字符串格式
2. **后端安全转换**只在后端业务逻辑中进行字符串到Long的转换
3. **前端零转换**前端严禁将大数字ID转换为Number类型
4. **向后兼容**同时支持短ID和长ID的处理
### 强制实施规范
#### 1. **前端API接口设计**
**✅ 正确的API设计**
```typescript
// 接收和发送都使用字符串格式
export function saveRoleMenuPermission(roleId: string, menuIds: string[]) {
const menuIdsStr = menuIds.length > 0 ? menuIds : ['-1']
return request.Post<Service.ResponseResult<string>>('/coder/sysMenu/saveRoleMenu', {
roleId, // 字符串格式
menuIds: menuIdsStr // 字符串数组格式
})
}
```
**❌ 错误的API设计**
```typescript
// 不要在前端进行数字转换
export function saveRoleMenuPermission(roleId: string, menuIds: string[]) {
const menuIdsLong = menuIds.map(id => Number(id)) // ❌ 会造成精度丢失
return request.Post('/api/save', {
roleId: Number(roleId), // ❌ 会造成精度丢失
menuIds: menuIdsLong // ❌ 会造成精度丢失
})
}
```
#### 2. **前端类型定义规范**
**✅ 正确的类型定义**
```typescript
// 所有ID相关字段使用字符串类型
export interface RoleMenuPermissionBo {
roleId: string // 字符串格式避免精度丢失
menuIds: string[] // 字符串数组格式避免精度丢失
}
export interface UserVo {
userId: string // 字符串格式
roleId: string // 字符串格式
menuIds: string[] // 字符串数组格式
}
```
**❌ 错误的类型定义**
```typescript
// 不要使用number类型处理大数字ID
export interface RoleMenuPermissionBo {
roleId: number // ❌ 会造成精度丢失
menuIds: number[] // ❌ 会造成精度丢失
}
```
#### 3. **前端数据处理规范**
**✅ 正确的数据处理**
```typescript
// 保持字符串格式进行比较和处理
function handleRowSelectionChange(rowKeys: (string | number)[]) {
const stringKeys = rowKeys.map(key => String(key))
selectedRows.value = tableData.value.filter(row =>
stringKeys.includes(String(row.roleId))
)
}
// 发送API请求时保持字符串格式
const response = await saveRoleMenuPermission(
String(currentRole.roleId),
selectedMenuIds // 已经是字符串数组
)
```
**❌ 错误的数据处理**
```typescript
// 不要将字符串ID转换为数字
function handleRowSelectionChange(rowKeys: (string | number)[]) {
const numericKeys = rowKeys.map(key => Number(key)) // ❌ 精度丢失
selectedRows.value = tableData.value.filter(row =>
numericKeys.includes(Number(row.roleId)) // ❌ 精度丢失
)
}
// 不要在发送前进行数字转换
const menuIds = selectedMenuIds.map(id => Number(id)) // ❌ 精度丢失
const response = await saveRoleMenuPermission(
Number(currentRole.roleId), // ❌ 精度丢失
menuIds
)
```
### 检查清单
**开发新功能时,必须确保**
- [ ] 前端类型定义中所有ID字段使用string类型
- [ ] 前端API调用保持字符串格式不进行Number转换
- [ ] 前端数据处理中避免parseInt()、Number()等数字转换
- [ ] 后端BO类提供字符串接收和Long转换的安全方法
- [ ] 后端控制器使用安全转换方法
- [ ] 后端服务层对无效ID进行过滤处理
### 常见问题排查
**当遇到大数字ID相关问题时按以下步骤排查**
1. **检查前端是否进行了数字转换**:搜索`Number(`、`parseInt(`、`parseFloat(`
2. **检查API调用参数格式**:确认发送的是字符串而非数字
3. **检查后端BO类设计**:确认使用字符串接收和安全转换
4. **检查数据库表字段类型**:确认使用`bigint`类型存储
5. **检查序列化配置**确认JSON序列化时大数字转为字符串
### 历史修复案例
**案例:菜单权限分配失败**
- **问题**雪花ID在前端Number转换时精度丢失
- **症状**:部门管理等新菜单权限无法保存
- **解决**:全链路改为字符串格式,后端安全转换
- **文件**`SysRoleMenuBo.java`、`saveRoleMenuPermission API`、角色管理页面
**遵循此规范可彻底避免大数字精度丢失问题,确保系统稳定运行!**