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

14 KiB
Raw Blame 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>

<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.vueDetailDrawer.vue
组合式函数 camelCase useUserList.ts

事件处理函数命名

统一以 handle 开头:handleEdithandleDeletehandleSubmit


2. API 模块

每个业务模块的 API 结构:

src/api/<domain>/<module>/
├── index.ts      # 导出请求函数
└── model/
    └── index.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

// 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 标准模式)

<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 CSSflexitems-centermt-4
  • 项目自定义主题类前缀:lng-
  • 禁止在 scoped 样式中直接穿透 AntD 组件,改用 :deep()
// 正确
:deep(.ant-table-cell) {
  padding: 8px;
}

6. TypeScript 规范

  • 严格模式已开启(strict: true),但项目对 any 较宽松
  • API 请求/响应类型放在对应 model/ 目录
  • 通用类型放在 types/ 目录,通过 /#/ 别名引用
  • 变量命名:
    • ref 变量加 Ref 后缀:visibleRefloadingRef
    • computed 可加 ComputedRef 后缀

7. 国际化

所有用户可见文本必须通过 i18n

import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n();

// 使用
t('common.okText')

8. 权限控制

按钮级权限通过 v-auth 指令或 usePermission 控制:

<a-button v-auth="'system:user:add'">新增</a-button>
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 层层传递:

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 统一调用:

// 子组件
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 生命周期

// 编辑模板时:从列表剔除,不在设计器中展示
formJson.list = formJson.list.filter(x => x.type !== 'hiddenComponent')

// 正式生成时:重新塞回,参与代码生成
generatorConfig.formJson.list.push(...generatorConfig.formJson.hiddenComponent)

5. 两段式下载

生成接口 → 返回 uuid → downloadCodes(uuid) → 下载 zip

核心数据结构

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,修改 designTypeoutputConfig.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() 中补充生成逻辑