Files
geg-gas-web/.claude/CLAUDE.md

486 lines
14 KiB
Markdown
Raw Normal View History

# 交互规范
1、使用中文交互
---
# 项目架构概览
## 技术栈
| 层级 | 技术 |
| --------- | ---------------------------- |
| 框架 | Vue 3 + TypeScript 5 |
| 构建 | Vite 4 |
| UI 组件库 | Ant Design Vue 3 |
| 状态管理 | Pinia 2 |
| 路由 | Vue Router 4 |
| HTTP | Axios自定义封装`defHttp` |
| 样式 | Less + Windi CSS |
| 国际化 | Vue I18n 9 |
| 基础框架 | Vben Admin深度定制 |
| 包管理 | pnpm |
> 注意:本项目与 Vue 3.4.x 不兼容,请保持 Vue ~3.3.4。
---
## 目录结构
```
src/
├── api/ # HTTP 请求模块,按业务域分组
│ └── <domain>/
│ └── <module>/
│ ├── index.ts # 请求函数
│ └── model/ # 请求/响应 TS 类型
├── assets/ # 静态资源、全局样式
├── components/ # 可复用组件BasicTable、BasicForm、Modal 等)
├── design/ # 全局 Less 主题入口
├── hooks/ # 组合式函数composables
├── layouts/ # 布局组件header、sider、tabs
├── locales/ # i18n 配置
├── router/ # 路由配置、守卫
├── store/ # Pinia 状态模块
│ └── modules/ # app / user / permission / locale / lock / multipleTab
├── utils/ # 工具函数
│ └── http/axios/ # HTTP 封装核心
└── views/ # 业务页面,按业务域分组
└── <domain>/ # erp / system / workflow / contract / sales ...
```
---
## 路径别名
| 别名 | 指向 |
| --------- | --------------------------------- |
| `/@/` | `src/` |
| `/#/` | `types/` |
| `/@bpmn/` | `src/views/workflow/design/bpmn/` |
**始终使用别名,禁止使用相对路径 `../../`。**
---
# 代码规范
## 1. Vue 组件
### 新文件优先使用 `<script setup>`
```vue
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
const visible = ref(false);
</script>
```
存量代码中存在 `defineComponent` 写法,维护时保持原有风格,新增代码统一用 `<script setup>`
### 文件命名
| 场景 | 规范 | 示例 |
| ----------- | ----------- | ----------------------------------- |
| 页面入口 | `index.vue` | `src/views/system/user/index.vue` |
| 弹窗/子组件 | PascalCase | `UserModal.vue``DetailDrawer.vue` |
| 组合式函数 | camelCase | `useUserList.ts` |
### 事件处理函数命名
统一以 `handle` 开头:`handleEdit``handleDelete``handleSubmit`
---
## 2. API 模块
每个业务模块的 API 结构:
```
src/api/<domain>/<module>/
├── index.ts # 导出请求函数
└── model/
└── index.ts # 请求/响应类型定义
```
**示例:**
```ts
// src/api/erp/purchase/apply/index.ts
import { defHttp } from '/@/utils/http/axios';
import type { ApplyListParams, ApplyListResult } from './model';
enum Api {
List = '/erp/purchase/apply/list',
Save = '/erp/purchase/apply/save',
}
export const getApplyList = (params: ApplyListParams) =>
defHttp.get<ApplyListResult>({ url: Api.List, params });
export const saveApply = (data: ApplyListParams) =>
defHttp.post({ url: Api.Save, data });
```
- 所有 HTTP 请求必须通过 `defHttp`,禁止直接使用 axios。
- 接口路径统一用 `enum Api` 管理。
- 错误提示通过 `errorMessageMode` 控制(`'modal'` | `'message'` | `'none'`)。
---
## 3. 状态管理Pinia
```ts
// src/store/modules/xxx.ts
import { defineStore } from 'pinia';
import { store } from '/@/store';
export const useXxxStore = defineStore({
id: 'app-xxx',
state: () => ({ ... }),
getters: { ... },
actions: { ... },
});
// 在 setup 外使用
export function useXxxStoreWithOut() {
return useXxxStore(store);
}
```
- Store 命名:`useXxxStore`
- 需要在 setup 外调用时,导出 `useXxxStoreWithOut`
---
## 4. 表格页面CRUD 标准模式)
```vue
<template>
<PageWrapper>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button type="primary" @click="handleAdd">新增</a-button>
</template>
<template #action="{ record }">
<TableAction :actions="getActions(record)" />
</template>
</BasicTable>
<XxxModal @register="registerModal" @success="reload" />
</PageWrapper>
</template>
<script setup lang="ts">
import { useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { PageWrapper } from '/@/components/Page';
import { TableAction } from '/@/components/Table';
const [registerTable, { reload }] = useTable({
api: getXxxList,
columns,
useSearchForm: true,
formConfig: { schemas },
showTableSetting: true,
bordered: true,
});
const [registerModal, { openModal }] = useModal();
function handleAdd() {
openModal(true, { isUpdate: false });
}
function getActions(record) {
return [
{ label: '编辑', onClick: () => openModal(true, { record, isUpdate: true }) },
{ label: '删除', color: 'error', popConfirm: { title: '确认删除?', confirm: () => handleDelete(record) } },
];
}
</script>
```
---
## 5. 样式规范
- 组件内样式:`<style lang="less" scoped>`
- 全局主题变量在 `src/design/``src/assets/style/theme/` 中定义
- 工具类优先使用 Windi CSS`flex``items-center``mt-4`
- 项目自定义主题类前缀:`lng-`
- 禁止在 scoped 样式中直接穿透 AntD 组件,改用 `:deep()`
```less
// 正确
:deep(.ant-table-cell) {
padding: 8px;
}
```
---
## 6. TypeScript 规范
- 严格模式已开启(`strict: true`),但项目对 `any` 较宽松
- API 请求/响应类型放在对应 `model/` 目录
- 通用类型放在 `types/` 目录,通过 `/#/` 别名引用
- 变量命名:
- `ref` 变量加 `Ref` 后缀:`visibleRef``loadingRef`
- computed 可加 `ComputedRef` 后缀
---
## 7. 国际化
所有用户可见文本必须通过 i18n
```ts
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();
// 使用
t('common.okText')
```
---
## 8. 权限控制
按钮级权限通过 `v-auth` 指令或 `usePermission` 控制:
```vue
<a-button v-auth="'system:user:add'">新增</a-button>
```
```ts
import { usePermission } from '/@/hooks/web/usePermission';
const { hasPermission } = usePermission();
if (hasPermission('system:user:edit')) { ... }
```
---
## 9. 工作流路由约定
特殊路由格式(在 `src/router/routes/basic.ts` 中定义):
| 路由 | 用途 |
| ----------------------------------- | ------------ |
| `/flow/:arg1/:arg2/createFlow` | 发起流程 |
| `/flow/:arg1/:arg2/approveFlowPage` | 审批流程 |
| `/form/:module/:id/createForm` | 通用表单新建 |
| `/form/:module/:id/updateForm` | 通用表单编辑 |
| `/flowList/todo` | 待办列表 |
---
## 10. 提交规范
遵循 Conventional Commits
```
feat: 新增功能
fix: 修复 bug
refactor: 重构
style: 样式调整
docs: 文档更新
chore: 构建/工具变更
```
---
## 新增页面检查清单
- [ ]`src/views/<domain>/` 下创建目录
- [ ] 页面入口为 `index.vue`,弹窗为 `XxxModal.vue`
- [ ] API 模块放在 `src/api/<domain>/<module>/index.ts`
- [ ] 类型定义放在 `model/index.ts`
- [ ] 使用 `PageWrapper` + `BasicTable` + `useTable` + `useModal` 标准结构
- [ ] 文本通过 `useI18n` 国际化
- [ ] 按钮权限通过 `v-auth` 控制
- [ ] 样式使用 `<style lang="less" scoped>`
- [ ] 路径使用 `/@/` 别名
---
# 代码生成器generator规范
## 目录结构
```
src/views/generator/
├── codeTemplate/ # 模板管理列表(草稿增删改查)
├── designer/ # 表单设计器演示/测试页
├── dev/ # 代码生成器核心入口
│ ├── choose.vue # 模式选择入口页
│ └── components/
│ ├── DataFirstModal.vue # 数据优先向导
│ ├── CodeFirstModal.vue # 界面优先向导
│ ├── SimpleTemplateModal.vue # 简易模板向导
│ ├── PreviewCodeStep.vue # 代码预览步骤(三种模式共用)
│ └── SelectDatabase.vue # 选择数据库表弹窗
├── desktop/ # 桌面/首页可视化设计器
├── order/ # 示例产物(订单模块演示)
└── print/ # 打印模板设计器
```
步骤子组件统一放在 `/@/components/CreateCodeStep/src/` 下。
---
## 三种生成模式
| 维度 | 数据优先 | 界面优先 | 简易模板 |
|------|---------|---------|---------|
| `designType` | `'data'` | `'code'` | `'template'` |
| `outputConfig.type` | `0` | `1` | `2` |
| 起点 | 选数据库表 | 设计表单 | 设计表单(固定 master 库) |
| 表配置字段 | `tableConfigs` | `tableStructureConfigs` | `tableStructureConfigs` |
| 生成接口 | `dataFirstGeneratorCode` | `codeFirstGeneratorCode` | `codeFirstGeneratorCode` |
| 预览接口 | `dataFirstPreviewCode` | `codeFirstPreviewCode` | `codeFirstPreviewCode` |
| 特殊逻辑 | 无 | 自动推导主表名 | 额外判断字段大小写Oracle/DM 等) |
简易模板本质是界面优先的变体,复用同一套后端生成接口,仅 `type` 不同。
---
## 核心设计模式
### 1. provide/inject 共享生成状态
父 Modal 通过 `provide` 下发,子步骤通过 `inject` 直接读写,禁止 props 层层传递:
```ts
provide('generatorConfig', generatorConfig) // 核心配置reactive
provide('tableInfo', tableInfo) // 表结构信息
provide('current', current) // 当前步骤索引
provide('designType', 'data') // 生成模式标识
provide('widgetForm', widgetForm) // 表单设计器状态
provide('mainTableName', mainTableName) // 主表名(界面优先/简易模板)
provide('isFieldUpper', isFieldUpper) // 字段大小写(简易模板)
```
### 2. ref + defineExpose 控制步骤流转
每个步骤子组件必须暴露 `validateStep()`,父组件通过 ref 统一调用:
```ts
// 子组件
defineExpose({ validateStep, initStep?, getFormData?, editFieldsValue? })
// 父组件
const stepValidate = {
0: () => tableConfigStepRef.value.validateStep(),
1: () => formDesignStepRef.value.validateStep(),
// ...
}
```
### 3. 前端本地生成 + 后端补全的混合模式
```
前端本地 buildCode() 后端接口 previewCode()
───────────────────── ──────────────────────
listCode列表页 controllerCode控制器
formCode表单页 entityCode实体类
apiCodeAPI 模块)
modelCodeTS 类型)
configJsonCode路由配置
```
### 4. hiddenComponent 生命周期
```ts
// 编辑模板时:从列表剔除,不在设计器中展示
formJson.list = formJson.list.filter(x => x.type !== 'hiddenComponent')
// 正式生成时:重新塞回,参与代码生成
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent)
```
### 5. 两段式下载
```
生成接口 → 返回 uuid → downloadCodes(uuid) → 下载 zip
```
---
## 核心数据结构
```ts
GeneratorConfig {
databaseId: string | null
listConfig: {
isLeftMenu, queryConfigs, leftMenuConfig,
columnConfigs, buttonConfigs, defaultOrder, isPage
}
tableConfigs: TableConfig[] // 仅数据优先
tableStructureConfigs: [] // 界面优先/简易模板
formJson: FormJson // 表单设计结果
menuConfig: MenuConfig
outputConfig: {
creator, isMenu,
type: 0 | 1 | 2 // 生成模式
}
formEventConfig: FormEventColumnConfig
isDataAuth: boolean
dataAuthList: []
}
```
类型定义文件:`src/api/system/generator/model/index.ts`
---
## API 接口
所有接口在 `src/api/system/generator/index.ts`
| 函数 | 方法 | 路径 |
|------|------|------|
| `dataFirstGeneratorCode` | POST | `/system/generator/generator-code/data-first` |
| `codeFirstGeneratorCode` | POST | `/system/generator/generator-code/code-first` |
| `dataFirstPreviewCode` | POST | `/system/generator/preview-code/data-first` |
| `codeFirstPreviewCode` | POST | `/system/generator/preview-code/code-first` |
| `saveDraftGeneratorCode` | POST | `/system/code-schema` |
| `updateDraftGeneratorCode` | PUT | `/system/code-schema` |
| `getCodeTemplateInfo` | GET | `/system/code-schema/info` |
| `getCodeTemplateList` | GET | `/system/code-schema/page` |
| `deleteCodeTemplate` | DELETE | `/system/code-schema` |
| `getMasterInfo` | GET | `/system/databaselink/master-info` |
| `batchGeneratorCode` | POST | `/system/generator/generator-code/batch` |
| `downloadCodes` | GET | `/system/generator/downloadCodes/{uuid}` |
---
## 功能扩展指南
### 新增生成模式
1. 复制 `CodeFirstModal.vue`,修改 `designType``outputConfig.type`
2.`choose.vue` 加入入口卡片
3.`codeTemplate/index.vue` 的路由名判断中加入新类型
4. 后端新增对应生成/预览接口
### 新增向导步骤
1.`/@/components/CreateCodeStep/src/` 下新建步骤组件,暴露 `validateStep()`
2. 在主 Modal 的 `<a-steps>` 中加入新步骤
3.`stepValidate` 对象中加入对应索引的校验函数
4.`generatorConfig` 中加入新步骤的配置字段,并通过 `provide` 下发
### 扩展代码预览输出类型
1.`FrontCode` 类型中加入新字段
2.`PreviewCodeStep.vue``<a-tabs>` 中加入新 tab
3.`validateStep()` 中加入非空校验
4.`buildCode()``previewCode()` 中补充生成逻辑