规范说明.md 11 KB

艾灸椅管理后台 — 框架规范说明

本文档供 AI 写代码时遵循,描述框架封装位置和编码规范。


一、项目结构

openspec/
├── backend/          后端 Spring Boot 项目
└── frontend/         前端 Vue3 项目

二、后端框架规范

技术栈

  • Java 1.8 + Spring Boot 2.7.18
  • MyBatis Plus 3.5.3
  • Redis(Spring Data Redis + Lettuce)
  • JWT(jjwt 0.9.1)+ FastJSON 1.2.83

包结构

com.aijiuyi.admin/
├── AijiuyiAdminApplication.java          启动类
├── common/
│   ├── annotation/
│   │   ├── Log.java                      操作日志注解
│   │   └── NoAuth.java                   免鉴权注解
│   ├── aspect/
│   │   └── LogAspect.java                日志 AOP 切面(拦截所有 Controller)
│   ├── config/
│   │   ├── AsyncConfig.java              异步线程池配置
│   │   ├── AuthProperties.java           鉴权白名单配置属性
│   │   ├── MybatisPlusConfig.java        MP 分页插件
│   │   ├── RedisConfig.java              Redis 序列化配置
│   │   └── WebMvcConfig.java             拦截器 + 跨域配置
│   ├── constant/
│   │   └── ResultCode.java               ★ 所有错误码和错误信息集中定义
│   ├── context/
│   │   └── RequestContext.java           ThreadLocal(requestId/userId/userName)
│   ├── entity/
│   │   ├── Result.java                   统一接口返回对象
│   │   └── SysLog.java                   操作日志实体
│   ├── enums/
│   │   └── OperationType.java            操作类型枚举(查询/新增/更新/删除/其他)
│   ├── exception/
│   │   ├── BusinessException.java        业务异常类
│   │   └── GlobalExceptionHandler.java   全局异常处理器
│   ├── handler/
│   │   └── MyMetaObjectHandler.java      MP 时间自动填充
│   ├── interceptor/
│   │   └── TokenInterceptor.java         Token 鉴权拦截器
│   ├── service/
│   │   ├── SysLogService.java            日志 Service 接口
│   │   └── impl/SysLogServiceImpl.java   日志 Service 实现(异步保存)
│   └── util/
│       ├── IpUtil.java                   IP 获取工具
│       ├── LogUtil.java                  ★ 统一日志工具(自动携带 requestId)
│       ├── RedisUtil.java                ★ Redis 统一操作工具
│       └── TokenUtil.java               JWT Token 工具
├── controller/                           Controller 层(业务)
│   ├── dto/                              请求参数 DTO
│   └── AuthController.java              示例:认证接口
├── entity/                               业务实体类
│   └── SysUser.java
├── mapper/                               MyBatis Plus Mapper
│   ├── SysLogMapper.java
│   └── SysUserMapper.java
└── service/                              业务 Service
    ├── SysUserService.java
    └── impl/SysUserServiceImpl.java

配置文件

文件 说明
application.yml 共享配置:端口、Jackson、MyBatis Plus、鉴权白名单
application-dev.yml 开发环境:DB、Redis、日志(DEBUG级别,打印SQL)
application-prod.yml 生产环境:DB、Redis、日志(INFO级别,不打印SQL)

切换环境:修改 application.yml 中的 spring.profiles.active


规范一览

1. 统一返回格式

所有 Controller 必须返回 Result<T>,禁止直接返回业务对象。

// ✅ 正确
return Result.success(data);
return Result.error(ResultCode.USER_NOT_FOUND);

// ❌ 错误
return user;

2. 错误码管理

所有错误码和错误信息必须在 ResultCode.java 中定义,禁止在其他地方硬编码。

// 在 ResultCode.java 新增
MY_ERROR(2001, "自定义错误信息"),

// 在业务代码中使用
throw new BusinessException(ResultCode.MY_ERROR);

3. 日志记录

使用 LogUtil 工具类,禁止直接用 @Slf4jLoggerFactory(否则 requestId 不自动注入)。

// ✅ 正确(自动带 requestId)
LogUtil.info(MyService.class, "处理完成: userId={}", userId);
LogUtil.error(MyService.class, "保存失败", e);

// ❌ 错误
log.info("处理完成");

4. Controller 接口日志注解

所有 Controller 方法上都应添加 @Log 注解,明确接口说明和操作类型。

@GetMapping("/list")
@Log(value = "查询用户列表", module = "用户管理", operationType = OperationType.QUERY)
public Result<List<SysUser>> list() { ... }

5. 免鉴权接口

两种方式,推荐用注解(@NoAuth),也可在 application.ymlauth.white-list 中配置。

// 方式一:注解(推荐,精确到方法)
@PostMapping("/login")
@NoAuth
public Result<?> login(...) { ... }

// 方式二:配置文件(适合整批免鉴权路径)
# application.yml
auth:
  white-list:
    - /api/auth/login

6. 数据库操作

只能用 MyBatis Plus,禁止手写 SQL(简单查询);复杂查询写在 mapper/ 目录对应的 XML 文件中。

// ✅ 简单查询用 Lambda
userMapper.selectOne(
    new LambdaQueryWrapper<SysUser>()
        .eq(SysUser::getUsername, username)
);

// ✅ 也可用 ServiceImpl 提供的 lambdaQuery
SysUser user = lambdaQuery().eq(SysUser::getUsername, username).one();

// ✅ 复杂查询写 XML(放 resources/mapper/XxxMapper.xml)

7. 实体类规范

@Data
@TableName("表名")
public class XxxEntity {
    @TableId(type = IdType.AUTO)
    private Long id;

    // 逻辑删除字段
    @TableLogic
    private Integer deleted;

    // 自动填充时间
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}

8. 获取当前用户

在 Service/Controller 中通过 RequestContext 获取当前登录用户,无需额外传参。

Long userId   = RequestContext.getUserId();
String userName = RequestContext.getUserName();
String requestId = RequestContext.getRequestId();

9. Redis 操作

统一使用 RedisUtil,禁止直接注入 RedisTemplate

@Autowired
private RedisUtil redisUtil;

redisUtil.set("key", value, 3600);   // 设置1小时过期
redisUtil.get("key");                // 获取
redisUtil.del("key");                // 删除
redisUtil.expire("key", 7200);       // 修改过期时间

10. 注释规范

所有方法(包括私有方法)必须有中文注释,格式参考:

/**
 * 根据用户名查询用户信息
 *
 * @param username 用户名
 * @return 用户对象,不存在返回 null
 */
public SysUser findByUsername(String username) { ... }

三、前端框架规范

技术栈

  • Vue 3 + Vite + Composition API
  • Element Plus(中文语言包)
  • Vue Router 4
  • Pinia(状态管理)
  • Axios(HTTP 请求封装)
  • XLSX/SheetJS(Excel 纯前端处理)
  • Sass(CSS 预处理器)

目录结构

frontend/src/
├── api/
│   ├── index.js        API 统一导出入口
│   └── auth.js         认证模块 API(示例)
│   └── xxx.js          新业务模块 API(按模块建文件)
├── components/
│   ├── ExcelImport.vue  Excel 导入组件
│   └── ExcelExport.vue  Excel 导出按钮组件
├── layout/
│   └── index.vue        主布局(侧边栏 + 顶栏 + 内容区)
├── router/
│   └── index.js         路由配置(含登录守卫)
├── store/
│   └── user.js          用户状态 Store(Pinia)
├── utils/
│   ├── excel.js         Excel 导入导出工具函数
│   ├── request.js       Axios 封装(自动 Token + 统一错误处理)
│   └── storage.js       localStorage 封装(Token/用户信息)
└── views/
    ├── login/index.vue  登录页
    ├── dashboard/index.vue 控制台
    └── 404.vue          404 页面

规范一览

1. API 请求规范

每个业务模块创建独立的 API 文件,在 api/index.js 统一导出。

// 新建 src/api/user.js
import request from '@/utils/request'

export function getUserList(params) {
  return request.get('/user/list', { params })
}

// 在 api/index.js 追加
export * as userApi from './user'

// 页面中使用
import { userApi } from '@/api'
const res = await userApi.getUserList({ page: 1, size: 10 })

2. 路由配置规范

需要登录的页面都放在 Layout 的 children 下,meta.requiresAuth = true(默认)。 不需要登录的页面配置 meta: { requiresAuth: false }

// router/index.js 中添加子路由
{
  path: 'user',
  name: 'User',
  component: () => import('@/views/user/index.vue'),
  meta: { requiresAuth: true, title: '用户管理', icon: 'User' }
}

meta.icon 的值是 Element Plus 图标名(会自动显示在左侧菜单)。

3. Excel 导出使用

<ExcelExport
  :headers="[
    { label: '姓名', prop: 'name' },
    { label: '手机号', prop: 'phone' }
  ]"
  :data="tableData"
  file-name="用户列表"
/>

4. Excel 导入使用

<ExcelImport
  :on-import="handleImport"
  button-text="导入用户"
  @success="onImportSuccess"
/>

// handleImport 接收解析后的数组,执行业务逻辑(如调用后端接口批量保存)
async function handleImport(data) {
  await userApi.batchImport(data)
}

5. 用户状态获取

import { useUserStore } from '@/store/user'
const userStore = useUserStore()

userStore.nickname   // 用户昵称
userStore.username   // 用户名
userStore.avatar     // 头像
userStore.isLoggedIn // 是否已登录
await userStore.logout()  // 退出登录

四、数据库

连接信息

url:      jdbc:mysql://localhost:3306/aijiuyi_admin
账号:     root
密码:     root
字符集:   utf8mb4

初始化

执行 backend/src/main/resources/sql/init.sql,创建所有表结构和初始数据。

默认管理员账号:

  • 用户名:admin
  • 密码:admin123

五、Redis

地址:    localhost:6379
密码:    无(如有密码,在 application-dev.yml 的 spring.redis.password 中配置)
数据库:  0

六、启动说明

后端

cd backend
mvn spring-boot:run
# 或用 IDE 运行 AijiuyiAdminApplication.java
# 服务地址:http://localhost:8080/api

前端

cd frontend
nvm use 22     # 切换到 Node.js 22
npm run dev    # 开发服务器:http://localhost:3000
npm run build  # 构建生产包

七、请求流程说明

HTTP 请求
    ↓
TokenInterceptor(生成 requestId,写入 ThreadLocal + MDC)
    ↓
Token 验证(白名单/NoAuth 注解跳过)
    ↓
Controller 方法
    ↓
LogAspect(AOP 环绕,记录请求参数/结果/耗时)
    ↓
Service → Mapper(所有日志自动带 requestId,含 SQL 日志)
    ↓
返回 Result<T>
    ↓
LogAspect 异步保存操作日志到 sys_log 表
    ↓
TokenInterceptor afterCompletion(清理 ThreadLocal + MDC)

所有涉及数据库删除都是软删除