代码风格与规范.md 24 KB

代码风格与规范

本文引用的文件

  • ai-electron/frontend/.prettierrc.mjs
  • ai-electron/frontend/eslint.config.mjs
  • ai-electron/frontend/stylelint.config.mjs
  • ai-electron/frontend/.prettierignore
  • ai-electron/frontend/.stylelintignore
  • ai-electron/frontend/package.json
  • ai-electron/electron/main.ts
  • ai-electron/electron/preload/index.ts
  • ai-electron/electron/preload/bridge.ts
  • ai-electron/electron/config/windowOptions.ts
  • ai-electron/frontend/src/App.vue
  • ai-electron/frontend/src/main.ts
  • ai-server/pom.xml
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanSynonym.java
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/mapper/AiCleanSynonymMapper.java
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanSynonymService.java
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/api/AiCleanSynonymController.java
  • sql/user.sql

目录

  1. 引言
  2. 项目结构总览
  3. 前端代码规范:Prettier、ESLint、Stylelint
  4. Electron 主进程、preload、渲染进程边界
  5. 后端 Spring Boot 模块划分与分层
  6. MyBatis-Plus 实体与 SQL 脚本约定
  7. 具体示例:新增后端模块、Vue 组件、建表 SQL
  8. 常见违规问题与自动修复命令
  9. 结论

引言

本规范面向清鉴 AI 调查工具的多语言代码库,覆盖 Java、TypeScript/Vue、SQL、Shell/Batch 的命名约定、目录组织、注释和格式化规则。重点说明前端 Prettier、ESLint、Stylelint 配置及忽略策略,明确 Electron 主进程、preload、渲染进程的隔离边界;同时给出后端 Spring Boot 模块划分、controller/service/mapper/entity 的组织方式,以及 MyBatis-Plus 实体与 SQL 脚本编写约定。文末提供新增模块示例、常见违规问题和可执行修复命令。

项目结构总览

仓库采用多模块、前后端分离、桌面应用加 Web 前端的组合结构:

graph TB
    A["仓库根目录"] --> B["ai-electron<br/>Electron 桌面应用"]
    A --> C["ai-server<br/>Spring Boot 后端"]
    A --> D["ai-gateway<br/>网关或辅助服务"]
    A --> E["sql<br/>数据库脚本"]
    A --> F["deploy、cmd、docs 等工程化资源"]

    B --> B1["electron/<br/>主进程与 preload"]
    B --> B2["frontend/<br/>Vue + TypeScript 前端"]

    C --> C1["src/main/java/com/zsjz/ai/module/*<br/>业务模块"]
    C --> C2["src/main/java/com/zsjz/ai/common/*<br/>通用能力"]
    C --> C3["src/main/resources/*<br/>配置与映射"]

    E --> E1["平台库脚本<br/>如 user.sql"]
    E --> E2["案件库/测试脚本<br/>如 case_table.sql、testSql/*"]
  • ai-electron:Electron 桌面应用,包含主进程入口、preload 预加载模块、窗口配置,以及基于 Vue 的前端工程。
  • ai-server:Spring Boot 后端,使用 MyBatis-Plus、Sa-Token、Redis、PostgreSQL 等。
  • sql:集中存放 PostgreSQL 相关脚本,包括平台库、案件库、索引、初始数据等。

图表来源

  • ai-electron/electron/main.ts:1-19
  • ai-electron/frontend/package.json:1-40
  • ai-server/pom.xml:1-60
  • sql/user.sql:1-12

章节来源

  • ai-electron/electron/main.ts:1-19
  • ai-electron/frontend/package.json:1-40
  • ai-server/pom.xml:1-60
  • sql/user.sql:1-12

前端代码规范:Prettier、ESLint、Stylelint

统一格式:Prettier

Prettier 是前端样式与代码格式的单一事实来源,所有 JavaScript、TypeScript、Vue、Less、SCSS、HTML、JSON 等由它决定换行、缩进、引号、分号、尾逗号等细节。

核心规则要点:

  • 打印宽度为 120。
  • 使用 2 空格缩进,不使用 Tab。
  • 语句末尾加分号。
  • 字符串优先使用单引号。
  • JSX/TSX 中不强制单引号。
  • 对象属性间保留空格。
  • 尾逗号启用到所有可能位置。
  • 箭头函数参数始终带括号。
  • HTML 空白敏感度为 strict。
  • 对 .rc 类配置文件使用 JSON 解析器。
  • 引入 prettier-plugin-packagejson 以格式化 package.json。

章节来源

  • ai-electron/frontend/.prettierrc.mjs:1-32

代码质量:ESLint

ESLint 负责语法错误、类型提示、Vue 模板规则、Prettier 集成等。当前配置按文件类型分块:

  • 公共基础配置:
    • ECMAScript 版本为 latest。
    • 模块语法。
    • 允许浏览器与 Node.js 全局变量。
    • 关闭部分过于严格的默认规则,例如 no-undef、no-var-requires、no-unused-vars 等。
  • Vue 文件:
    • 使用 vue-eslint-parser。
    • 模板解析器使用 espree。
    • 关闭组件名多词、每文件一组件、属性排序、属性数量限制等严格规则。
    • 自定义自闭合规则:HTML void 元素自闭合、普通 HTML 元素不自闭合、组件 SVG/Math 自闭合。
    • 关闭 vue/no-v-html。
  • TypeScript:
    • 使用 @typescript-eslint/parser。
    • 启用 recommended 规则集。
    • 关闭 ban-ts-comment、ban-types、explicit-module-boundary-types、no-explicit-any、no-non-null-assertion、no-unused-vars 等规则。
  • JavaScript:
    • 使用 Babel 解析器。
    • 启用 decorators legacy 模式。
  • Prettier 集成:
    • ESLint 内再声明一次 printWidth、semi、singleQuote、trailingComma,确保 ESLint 报告时与 Prettier 行为一致。

章节来源

  • ai-electron/frontend/eslint.config.mjs:1-177

样式质量:Stylelint

Stylelint 主要检查 Less、SCSS、Vue 模板中的样式,并与 Prettier 协作。

关键约定:

  • 继承 stylelint-config-standard、stylelint-config-standard-less。
  • Vue 与 HTML 使用 postcss-html 解析。
  • Less 使用 postcss-less。
  • SCSS 使用 postcss-scss。
  • 允许 Vue 特有的伪类和伪元素:global、deep、v-deep、v-global、v-slotted。
  • 允许传统定位属性 top/right/bottom/left,但禁止 inset 值。
  • 允许 UnoCSS、Less mixin、at-rule 等现代样式语法。
  • 允许单位 rpx。
  • 关闭重复选择器、特定性、网格区域无效等部分规则,避免与 UI 框架冲突。

章节来源

  • ai-electron/frontend/stylelint.config.mjs:1-121

忽略规则

Prettier 忽略以下路径与文件:

  • 构建产物:dist。
  • 静态资源目录:public。
  • 包管理器依赖:node_modules。
  • 本地缓存:.local。
  • npm 配置、输出临时文件:.npmrc、.output.js。
  • Shell 脚本:*.sh。
  • Markdown:*.md。
  • SVG、HTML、JSON、lock 文件:*.svg、*.html、*.json、*-lock.yaml。

Stylelint 忽略:

  • dist、public、node_modules。
  • *.sh、*.md。

ESLint 在配置内部也忽略了 node_modules、dist、public、build、git、编辑器目录、shell 脚本、Markdown、字体、类型声明、快照等。

章节来源

  • ai-electron/frontend/.prettierignore:1-14
  • ai-electron/frontend/.stylelintignore:1-6
  • ai-electron/frontend/eslint.config.mjs:11-35

前端脚本命令

package.json 定义了常用命令:

  • pnpm lint:eslint:检查并尝试修复 TS、TSX、MJS、Vue。
  • pnpm lint:prettier:检查并写入 Vue、TSX、Less、SCSS。
  • pnpm lint:stylelint:检查并修复 Vue、Less、SCSS、CSS。
  • pnpm lint:all:安装依赖、类型检查、运行 ESLint、Prettier、Stylelint。

章节来源

  • ai-electron/frontend/package.json:8-20

Electron 主进程、preload、渲染进程边界

本项目当前 Electron 渲染进程未启用上下文隔离,而是通过主进程直接暴露 IPC 给渲染进程。

主进程入口

主进程使用 ElectronEgg 启动应用,注册生命周期钩子,并注册 preload。

sequenceDiagram
    participant Main as "main.ts"
    participant Lifecycle as "preload/lifecycle.ts"
    participant Preload as "preload/index.ts"
    participant App as "ElectronEgg"

    Main->>App: new ElectronEgg()
    Main->>Lifecycle: new Lifecycle()
    Main->>App: register("ready", ready)
    Main->>App: register("window-ready", windowReady)
    Main->>App: register("before-close", beforeClose)
    Main->>App: register("preload", preload)
    Main->>App: run()

图表来源

  • ai-electron/electron/main.ts:1-19

preload 职责

preload 初始化托盘服务和安全服务,并通过日志记录加载阶段。当前 preload 本身没有向渲染进程暴露 API。

flowchart TD
    Start(["preload 入口"]) --> Tray["创建托盘服务"]
    Tray --> Security["创建安全服务"]
    Security --> End(["完成初始化"])

图表来源

  • ai-electron/electron/preload/index.ts:1-16

渲染进程访问 Electron API 的方式

由于当前窗口配置关闭了 contextIsolation 并开启 nodeIntegration,渲染进程可直接使用 require('electron')。仓库中存在一个 bridge 示例,使用 contextBridge.exposeInMainWorld 暴露 ipcRenderer,但在当前共享 webPreferences 下,该桥接并非唯一路径。

graph LR
    Renderer["渲染进程"] -->|直接 require electron| NodeAPI["Node/Electron API"]
    Renderer -->|contextBridge 示例| Bridge["bridge.ts 暴露 ipcRenderer"]
    Bridge --> Renderer

图表来源

  • ai-electron/electron/preload/bridge.ts:1-10
  • ai-electron/electron/config/windowOptions.ts:1-41

安全边界建议

当前实现为了兼容现有渲染进程代码,显式设置:

  • contextIsolation: false
  • nodeIntegration: true

这意味着渲染进程可以调用 Node.js 和 Electron 原生 API。若未来改为上下文隔离,必须:

  1. 将敏感系统能力集中到主进程。
  2. 通过 preload 的 contextBridge 暴露最小接口。
  3. 让渲染进程只调用桥接方法,不再直接操作文件系统、网络或操作系统。

章节来源

  • ai-electron/electron/main.ts:1-19
  • ai-electron/electron/preload/index.ts:1-16
  • ai-electron/electron/preload/bridge.ts:1-10
  • ai-electron/electron/config/windowOptions.ts:1-41

后端 Spring Boot 模块划分与分层

模块组织

后端包路径以 com.zsjz.ai 为基础,业务功能按模块拆分到 module 下。已有模块包括:

  • plat:平台基础能力,如用户、系统信息、健康检查、会话、SSE 等。
  • aiclean:AI 清洗、模板、同义词、规则、字段、批处理、作业等。
  • agent:Agent 聊天、工具、模型、附件、Python 执行、RAG、意图等。
  • knowledge:知识库文档、基座、下载日志等。
  • dm:数据管理、文件识别等。
  • external、otg、person、trans、search、govern 等扩展领域模块。

每个模块通常包含:

  • api:对外 REST 控制器。
  • controller:其他控制器(部分模块直接使用 controller)。
  • service:业务逻辑。
  • mapper:MyBatis Mapper。
  • entity:数据库实体。
  • 其他领域子包,如 tree、rag、followup、artifact 等。

分层职责

  • Controller:接收 HTTP 请求,封装/解包参数,返回统一结果对象。
  • Service:实现业务校验、事务控制、缓存重建、跨层调用。
  • Mapper:继承 MyBatis-Plus 的 BaseMapper,定义数据访问接口。
  • Entity:使用 Lombok 与 MyBatis-Plus 注解映射数据库表。

    classDiagram
    class AiCleanSynonymController {
        +list()
        +create(row)
        +update(row)
        +delete(row)
        +toggle(row)
    }
    
    class AiCleanSynonymService {
        +list()
        +create(row)
        +update(row)
        +delete(id)
        +toggle(id, status)
        -assertWordsFree(stdWord, aliasWord, excludeId)
        -refreshAfterCommit()
    }
    
    class AiCleanSynonymMapper {
        +selectList(wrapper)
        +insert(entity)
        +updateById(entity)
        +deleteById(id)
    }
    
    class AiCleanSynonym {
        +id
        +stdWord
        +aliasWord
        +remark
        +status
        +createBy
        +createTime
        +updateTime
    }
    
    AiCleanSynonymController --> AiCleanSynonymService : "调用"
    AiCleanSynonymService --> AiCleanSynonymMapper : "调用"
    AiCleanSynonymService --> AiCleanSynonym : "操作实体"
    

图表来源

  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/api/AiCleanSynonymController.java:1-70
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanSynonymService.java:1-178
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/mapper/AiCleanSynonymMapper.java:1-12
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanSynonym.java:1-63

章节来源

  • ai-server/pom.xml:1-200
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/api/AiCleanSynonymController.java:1-70
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanSynonymService.java:1-178
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/mapper/AiCleanSynonymMapper.java:1-12
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanSynonym.java:1-63

MyBatis-Plus 实体与 SQL 脚本约定

Java 命名约定

  • 包名小写,按公司域名倒序,再按模块划分。
  • 类名使用大驼峰,例如 AiCleanSynonym、AiCleanSynonymController。
  • 方法名使用小驼峰,例如 create、update、assertWordsFree。
  • 常量使用全大写加下划线,例如 STARTUP_PROBE_RETRIES(前端也有类似模式)。
  • 私有字段、局部变量使用小驼峰。
  • 包名、类名、方法名均避免拼音缩写,除非项目既有历史惯例。

Entity 约定

  • 使用 Lombok @Data 简化 getter/setter。
  • 使用 MyBatis-Plus @TableName 指定表名。
  • 主键使用 @TableId(type = IdType.ASSIGN_ID)。
  • 非默认列名使用 @TableField。
  • 时间字段使用 LocalDateTime。
  • 字段注释使用 Javadoc,说明业务含义、约束、状态码。
  • 实现 Serializable,保留 serialVersionUID。

Mapper 约定

  • 接口位于 module.<domain>.mapper。
  • 继承 BaseMapper<Entity>。
  • 使用 @Mapper 注解。
  • 简单 CRUD 直接复用 BaseMapper,复杂查询放在 XML 或 Service 层构造条件。

Service 约定

  • 使用 @Service。
  • 使用 @RequiredArgsConstructor 注入依赖。
  • 写操作使用 @Transactional。
  • 对外抛出业务异常,而不是吞掉异常。
  • 对缓存、索引等副作用放在事务提交后重建,失败时降级为日志。

SQL 约定

  • 使用 PostgreSQL 风格脚本。
  • 使用 CREATE TABLE IF NOT EXISTS 保证幂等。
  • 使用 COMMENT ON TABLE 和 COMMENT ON COLUMN 描述表和列。
  • 使用 CREATE INDEX 和 CREATE UNIQUE INDEX 建立必要索引。
  • 使用 ALTER TABLE ... ADD COLUMN IF NOT EXISTS 做增量迁移。
  • 使用 INSERT INTO ... SELECT ... WHERE NOT EXISTS 做幂等初始化数据。
  • 脚本顶部用注释说明目标库、执行方式、幂等性、影响范围。

章节来源

  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanSynonym.java:1-63
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/mapper/AiCleanSynonymMapper.java:1-12
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanSynonymService.java:1-178
  • sql/user.sql:1-75

具体示例:新增后端模块、Vue 组件、建表 SQL

新增后端模块示例

假设新增“线索追踪”模块,包结构应遵循现有 module 模式:

com.zsjz.ai.module.tracking
├── api
│   └── TrackingController.java
├── service
│   └── TrackingService.java
├── mapper
│   └── TrackingMapper.java
├── entity
│   └── TrackingRecord.java

对应约定:

  • Controller 放在 api,使用 @RestController 和 @RequestMapping。
  • Service 使用 @Service,写操作加 @Transactional。
  • Mapper 继承 BaseMapper,加 @Mapper。
  • Entity 使用 @TableName、@TableId、@TableField、Javadoc 注释。

章节来源

  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/api/AiCleanSynonymController.java:1-70
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/service/AiCleanSynonymService.java:1-178
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/mapper/AiCleanSynonymMapper.java:1-12
  • ai-server/src/main/java/com/zsjz/ai/module/aiclean/entity/AiCleanSynonym.java:1-63

Vue 组件写法示例

现有前端大量使用 Vue 3 <script setup lang="ts"> 组合式 API,并在 <template> 中使用 Ant Design Vue、UnoCSS、国际化等能力。参考根组件和组织方式:

flowchart TD
    Entry["main.ts 创建 Vue 应用"] --> Router["路由初始化"]
    Entry --> Store["Pinia 状态初始化"]
    Entry --> I18n["国际化初始化"]
    Entry --> ErrorHandle["全局错误处理"]
    Entry --> Directives["全局指令"]
    Entry --> Components["全局组件注册"]
    Entry --> Root["App.vue 根组件"]

图表来源

  • ai-electron/frontend/src/main.ts:1-40
  • ai-electron/frontend/src/App.vue:1-85

组件编写建议:

  • 使用 <script setup lang="ts">。
  • 使用 Composition API 的 computed、watch、onMounted。
  • 使用 Ant Design Vue 组件和主题配置。
  • 使用 UnoCSS 或 Less 编写样式。
  • 使用 ESLint、Prettier、Stylelint 保持格式一致。
  • 组件文件名使用 kebab-case 或 PascalCase,视现有组件习惯而定。

章节来源

  • ai-electron/frontend/src/main.ts:1-40
  • ai-electron/frontend/src/App.vue:1-85
  • ai-electron/frontend/eslint.config.mjs:60-110
  • ai-electron/frontend/stylelint.config.mjs:10-40

建表 SQL 格式示例

参考平台用户表脚本,新建一张“线索追踪记录表”时应遵循:

  • 脚本头部说明目标库、用途、是否幂等。
  • 使用 CREATE TABLE IF NOT EXISTS。
  • 字段命名清晰,避免无意义缩写。
  • 主键使用自增或序列,必要时添加唯一索引。
  • 使用 COMMENT ON TABLE 和 COMMENT ON COLUMN。
  • 如果需要初始数据,使用 INSERT INTO ... SELECT ... WHERE NOT EXISTS。
  • 如果需要对存量表迁移,使用 ALTER TABLE ... ADD COLUMN IF NOT EXISTS。

    flowchart TD
    Header["脚本头部注释"] --> Create["CREATE TABLE IF NOT EXISTS"]
    Create --> Columns["字段定义与默认值"]
    Columns --> Indexes["索引与唯一约束"]
    Indexes --> Comments["表和列注释"]
    Comments --> Data["幂等初始化数据"]
    Data --> Migration["存量迁移与校验"]
    

图表来源

  • sql/user.sql:1-75

章节来源

  • sql/user.sql:1-75

常见违规问题与自动修复命令

常见违规问题

  • 缩进不一致:混用 Tab 和空格,或缩进不是 2 空格。
  • 分号缺失或多余:不符合 Prettier 的分号规则。
  • 引号不一致:字符串或 JSX 属性引号与配置不符。
  • 尾逗号缺失:对象、数组、函数参数未使用尾逗号。
  • 行宽过长:超过 120 字符未换行。
  • ESLint 规则被忽略:使用了 any、non-null assertion、unused vars 等被关闭的规则,导致类型安全下降。
  • Stylelint 未知伪类/伪元素:使用了未被允许的 CSS 伪类或 Vue 深度选择器。
  • Electron 安全边界不清:渲染进程直接访问 Node/Electron API,但没有通过 preload 桥接。
  • Java 实体缺少注释或注解:表名、主键、字段映射不明确。
  • SQL 缺少注释或幂等性:脚本不可重复执行,或缺少表和列注释。

自动修复命令

在前端工程目录执行:

  • 修复 ESLint:

    pnpm lint:eslint
    
  • 修复 Prettier:

    pnpm lint:prettier
    
  • 修复 Stylelint:

    pnpm lint:stylelint
    
  • 一次性完整检查:

    pnpm lint:all
    

章节来源

  • ai-electron/frontend/package.json:8-20

结论

清鉴 AI 调查工具的代码规范以 Prettier 为格式事实来源,ESLint 负责语法与 Vue/TS 质量,Stylelint 负责样式质量;Electron 当前采用较宽松的渲染进程权限,需在未来逐步收敛到 preload 桥接;后端 Spring Boot 按模块与分层组织,使用 MyBatis-Plus 与 PostgreSQL,强调实体注解、Service 事务、Mapper 简洁、SQL 幂等与注释;前端 Vue 使用组合式 API、Ant Design Vue、UnoCSS,并通过统一脚本命令维护代码质量。遵循这些约定可以降低协作成本、减少风格分歧,并使自动化检查和修复更有效。