| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387 |
- # 杭州第一技师学院智慧校园管理系统 - AI 代码生成规范
- ## 🎯 项目概述
- 本项目是基于 RuoYi-Vue-Plus 框架开发的智慧校园管理系统,主要用于学校的学工管理、宿舍管理、班级管理等业务场景。
- - **项目名称**: 杭州第一技师学院智慧校园管理系统
- - **基础框架**: RuoYi-Vue-Plus 5.4.0
- - **前端**: Vue 3 + TypeScript + Element Plus + Vite
- - **后端**: Spring Boot 3.4.6 + MyBatis-Plus + Sa-Token
- - **主工程代码路径**: 管理端前端在 **`crm/web/`**,Java 后端在 **`crm/backend/`**,主工程 Python 在 **`crm/py-backend/`**;AI 生成路径说明、文档与脚本中的 `web/`、`backend/` 均指以上目录,勿假定仓库根下仍有同名顶层文件夹。
- ---
- ## ⚠️ AI代码生成核心规则
- ### 文档生成规范
- - **禁止主动生成MD文档**:在代码生成过程中,除非用户明确要求,否则不要生成任何Markdown文档(.md文件)
- - **简洁优先原则**:如果必须生成说明文档,内容要极度简洁,只包含关键信息
- - **聚焦代码实现**:将精力集中在代码生成和功能实现上,而非文档编写
- - **例外情况**:仅在以下情况生成文档
- - 用户明确要求生成文档
- - 项目README或API文档等必要文件缺失
- - 复杂功能需要关键说明(限制在50行以内)
- ---
- ## 📦 前端技术栈总结
- ### 核心框架与版本
- - **Vue**: 3.5.13 (使用 Composition API)
- - **TypeScript**: 5.8.3
- - **Vite**: 6.3.2
- - **Element Plus**: 2.9.8
- - **Pinia**: 3.0.2 (状态管理)
- - **Vue Router**: 4.5.0 (路由管理)
- - **Axios**: 1.8.4 (HTTP请求)
- ### 关键工具库
- - **vxe-table**: 4.13.7 (高级表格组件)
- - **UnoCSS**: 66.0.0 (原子化CSS框架)
- - **echarts**: 5.6.0 (数据可视化)
- - **@vueuse/core**: 13.1.0 (Vue组合式工具集)
- - **vue-i18n**: 11.1.3 (国际化)
- - **screenfull**: 6.0.2 (全屏)
- - **nprogress**: 0.2.0 (进度条)
- ### 项目结构
- ```
- crm/web/
- ├── src/
- │ ├── api/ # API接口定义
- │ ├── assets/ # 静态资源
- │ ├── components/ # 公共组件
- │ ├── directive/ # 自定义指令
- │ ├── hooks/ # 组合式函数
- │ ├── lang/ # 国际化语言包
- │ ├── layout/ # 布局组件
- │ ├── plugins/ # 插件配置
- │ ├── router/ # 路由配置
- │ ├── store/ # Pinia状态管理
- │ ├── utils/ # 工具函数
- │ ├── views/ # 页面视图
- │ └── main.ts # 入口文件
- ├── vite/ # Vite插件配置
- ├── index.html
- ├── vite.config.ts
- └── package.json
- ```
- ---
- ## 📦 后端技术栈总结
- ### 核心框架与版本
- - **Spring Boot**: 3.4.6
- - **JDK**: 17+
- - **MyBatis**: 3.5.16
- - **MyBatis-Plus**: 3.5.12
- - **Sa-Token**: 1.42.0 (权限认证)
- - **Hutool**: 5.8.35 (工具库)
- ### 关键技术组件
- - **Redisson**: 3.45.1 (Redis客户端,分布式锁)
- - **Lock4j**: 2.2.7 (分布式锁)
- - **dynamic-datasource**: 4.3.1 (动态多数据源)
- - **p6spy**: 3.9.1 (SQL性能分析)
- - **FastExcel**: 1.2.0 (Excel导入导出)
- - **SpringDoc**: 2.8.8 (API文档生成)
- - **Warm-Flow**: 1.7.3 (国产工作流引擎)
- - **SnailJob**: 1.5.0 (分布式任务调度)
- - **AWS S3**: 2.28.22 (对象存储)
- - **SMS4J**: 3.3.4 (短信发送)
- - **ip2region**: 2.7.0 (IP地址定位)
- - **MapStruct-Plus**: 1.5.0 (对象转换)
- ### 项目结构
- ```
- crm/backend/
- ├── ruoyi-admin/ # 启动模块
- ├── ruoyi-common/ # 通用模块
- │ ├── ruoyi-common-core/ # 核心工具
- │ ├── ruoyi-common-mybatis/ # 数据库配置
- │ ├── ruoyi-common-redis/ # Redis配置
- │ ├── ruoyi-common-satoken/ # 权限配置
- │ ├── ruoyi-common-web/ # Web配置
- │ ├── ruoyi-common-excel/ # Excel工具
- │ └── ... # 其他通用模块
- ├── ruoyi-modules/ # 业务模块
- │ ├── ruoyi-system/ # 系统管理
- │ ├── ruoyi-job/ # 定时任务
- │ ├── ruoyi-workflow/ # 工作流
- │ └── ruoyi-xg/ # 学工管理 ⭐
- └── ruoyi-extend/ # 扩展模块
- ├── ruoyi-monitor-admin/ # 监控中心
- └── ruoyi-snailjob-server/# 任务调度服务
- ```
- ---
- ## 🎓 学工模块(ruoyi-xg)架构规范
- ### 后端模块结构
- ```
- ruoyi-xg/
- └── src/main/java/org/dromara/xg/
- ├── controller/ # 控制器层 - RESTful API
- ├── service/ # 服务层 - 业务逻辑
- │ └── impl/ # 服务实现
- ├── mapper/ # 数据访问层 - MyBatis接口
- ├── domain/ # 数据模型
- │ ├── bo/ # Business Object - 业务对象(接收参数)
- │ └── vo/ # View Object - 视图对象(返回数据)
- ├── convert/ # 对象转换器 - MapStruct
- ├── config/ # 配置类
- ├── utils/ # 工具类
- └── listener/ # 事件监听器
- ```
- ### 前端模块结构
- ```
- crm/web/src/
- ├── api/xg/ # 学工API接口定义
- │ ├── student/ # 学生管理API
- │ ├── xsjcxx/ # 学生基础信息API
- │ ├── xgss/ # 学工宿舍API
- │ ├── studentStatistics.ts # 学生统计API
- │ └── README.md
- └── views/xg/ # 学工页面视图
- ├── xsjcxx/ # 学生基础信息模块
- ├── xgss/ # 学工宿舍模块
- ├── studentStatistics/ # 学生统计模块
- └── README.md
- ```
- ---
- ## 🚀 后端开发规范(学工模块)
- ### 1. Controller 层规范
- ```java
- package org.dromara.xg.controller;
- import cn.dev33.satoken.annotation.SaCheckPermission;
- import jakarta.servlet.http.HttpServletResponse;
- import jakarta.validation.constraints.*;
- import lombok.RequiredArgsConstructor;
- import org.dromara.common.core.domain.R;
- import org.dromara.common.core.validate.AddGroup;
- import org.dromara.common.core.validate.EditGroup;
- import org.dromara.common.excel.utils.ExcelUtil;
- import org.dromara.common.idempotent.annotation.RepeatSubmit;
- import org.dromara.common.log.annotation.Log;
- import org.dromara.common.log.enums.BusinessType;
- import org.dromara.common.mybatis.core.page.*;
- import org.dromara.common.web.core.BaseController;
- import org.springframework.validation.annotation.Validated;
- import org.springframework.web.bind.annotation.*;
- /**
- * XXX管理控制器
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- @Validated
- @RequiredArgsConstructor
- @RestController
- @RequestMapping("/xg/模块名")
- public class XgXxxController extends BaseController {
- private final IXgXxxService xxxService;
- /**
- * 查询列表(分页)
- */
- @SaCheckPermission("xg:xxx:list")
- @GetMapping("/list")
- public TableDataInfo<XgXxxVo> list(XgXxxBo bo, PageQuery pageQuery) {
- return xxxService.queryPageList(bo, pageQuery);
- }
- /**
- * 获取详细信息
- */
- @SaCheckPermission("xg:xxx:query")
- @GetMapping("/{id}")
- public R<XgXxxVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
- return R.ok(xxxService.queryById(id));
- }
- /**
- * 新增
- */
- @SaCheckPermission("xg:xxx:add")
- @Log(title = "XXX管理", businessType = BusinessType.INSERT)
- @RepeatSubmit()
- @PostMapping()
- public R<Void> add(@Validated(AddGroup.class) @RequestBody XgXxxBo bo) {
- return toAjax(xxxService.insertByBo(bo));
- }
- /**
- * 修改
- */
- @SaCheckPermission("xg:xxx:edit")
- @Log(title = "XXX管理", businessType = BusinessType.UPDATE)
- @RepeatSubmit()
- @PutMapping()
- public R<Void> edit(@Validated(EditGroup.class) @RequestBody XgXxxBo bo) {
- return toAjax(xxxService.updateByBo(bo));
- }
- /**
- * 删除
- */
- @SaCheckPermission("xg:xxx:remove")
- @Log(title = "XXX管理", businessType = BusinessType.DELETE)
- @DeleteMapping("/{ids}")
- public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
- return toAjax(xxxService.deleteWithValidByIds(List.of(ids), true));
- }
- /**
- * 导出
- */
- @SaCheckPermission("xg:xxx:export")
- @Log(title = "XXX管理", businessType = BusinessType.EXPORT)
- @PostMapping("/export")
- public void export(XgXxxBo bo, HttpServletResponse response) {
- List<XgXxxVo> list = xxxService.queryList(bo);
- ExcelUtil.exportExcel(list, "XXX数据", XgXxxVo.class, response);
- }
- }
- ```
- **关键点:**
- - 继承 `BaseController` 提供基础工具方法
- - 使用 `@RequiredArgsConstructor` 实现构造器注入
- - 使用 `@SaCheckPermission` 进行权限控制,格式:`xg:模块:操作`
- - 使用 `@Log` 记录操作日志
- - 使用 `@RepeatSubmit` 防止重复提交
- - 使用 `@Validated` 进行参数校验,分组校验使用 AddGroup/EditGroup
- - 分页查询返回 `TableDataInfo<T>`,其他接口返回 `R<T>`
- ### 2. Service 层规范
- ```java
- package org.dromara.xg.service;
- import org.dromara.common.mybatis.core.page.*;
- import org.dromara.xg.domain.bo.XgXxxBo;
- import org.dromara.xg.domain.vo.XgXxxVo;
- import java.util.Collection;
- import java.util.List;
- /**
- * XXX管理Service接口
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- public interface IXgXxxService {
- /**
- * 查询分页列表
- */
- TableDataInfo<XgXxxVo> queryPageList(XgXxxBo bo, PageQuery pageQuery);
- /**
- * 查询列表
- */
- List<XgXxxVo> queryList(XgXxxBo bo);
- /**
- * 根据主键查询
- */
- XgXxxVo queryById(Long id);
- /**
- * 新增
- */
- Boolean insertByBo(XgXxxBo bo);
- /**
- * 修改
- */
- Boolean updateByBo(XgXxxBo bo);
- /**
- * 校验并批量删除
- */
- Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
- }
- ```
- **实现类规范:**
- ```java
- package org.dromara.xg.service.impl;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.toolkit.Wrappers;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import lombok.RequiredArgsConstructor;
- import org.dromara.common.core.utils.MapstructUtils;
- import org.dromara.common.core.utils.StringUtils;
- import org.dromara.common.mybatis.core.page.*;
- import org.dromara.xg.domain.XgXxx;
- import org.dromara.xg.domain.bo.XgXxxBo;
- import org.dromara.xg.domain.vo.XgXxxVo;
- import org.dromara.xg.mapper.XgXxxMapper;
- import org.dromara.xg.service.IXgXxxService;
- import org.springframework.stereotype.Service;
- import java.util.Collection;
- import java.util.List;
- /**
- * XXX管理Service实现
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- @RequiredArgsConstructor
- @Service
- public class XgXxxServiceImpl implements IXgXxxService {
- private final XgXxxMapper baseMapper;
- /**
- * 构建查询条件
- */
- private LambdaQueryWrapper<XgXxx> buildQueryWrapper(XgXxxBo bo) {
- LambdaQueryWrapper<XgXxx> lqw = Wrappers.lambdaQueryWrapper();
- lqw.like(StringUtils.isNotBlank(bo.getName()), XgXxx::getName, bo.getName());
- lqw.eq(bo.getStatus() != null, XgXxx::getStatus, bo.getStatus());
- lqw.between(bo.getBeginTime() != null && bo.getEndTime() != null,
- XgXxx::getCreateTime, bo.getBeginTime(), bo.getEndTime());
- lqw.orderByDesc(XgXxx::getCreateTime);
- return lqw;
- }
- @Override
- public TableDataInfo<XgXxxVo> queryPageList(XgXxxBo bo, PageQuery pageQuery) {
- LambdaQueryWrapper<XgXxx> lqw = buildQueryWrapper(bo);
- Page<XgXxxVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
- return TableDataInfo.build(result);
- }
- @Override
- public List<XgXxxVo> queryList(XgXxxBo bo) {
- LambdaQueryWrapper<XgXxx> lqw = buildQueryWrapper(bo);
- return baseMapper.selectVoList(lqw);
- }
- @Override
- public XgXxxVo queryById(Long id) {
- return baseMapper.selectVoById(id);
- }
- @Override
- public Boolean insertByBo(XgXxxBo bo) {
- XgXxx entity = MapstructUtils.convert(bo, XgXxx.class);
- boolean flag = baseMapper.insert(entity) > 0;
- if (flag) {
- bo.setId(entity.getId());
- }
- return flag;
- }
- @Override
- public Boolean updateByBo(XgXxxBo bo) {
- XgXxx entity = MapstructUtils.convert(bo, XgXxx.class);
- return baseMapper.updateById(entity) > 0;
- }
- @Override
- public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
- if (isValid) {
- // 做删除前的业务校验
- }
- return baseMapper.deleteByIds(ids) > 0;
- }
- }
- ```
- **关键点:**
- - 使用 `@RequiredArgsConstructor` 注入 Mapper
- - 使用 MyBatis-Plus 的 LambdaQueryWrapper 构建查询条件
- - 使用 `MapstructUtils.convert` 进行对象转换
- - 使用 `selectVoPage` 和 `selectVoList` 直接查询VO对象
- ### 3. Domain 层规范
- **Entity(实体类):**
- ```java
- package org.dromara.xg.domain;
- import com.baomidou.mybatisplus.annotation.*;
- import lombok.Data;
- import lombok.EqualsAndHashCode;
- import org.dromara.common.tenant.core.TenantEntity;
- import java.io.Serial;
- import java.time.LocalDateTime;
- /**
- * XXX实体对象 xg_xxx
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- @Data
- @EqualsAndHashCode(callSuper = true)
- @TableName("xg_xxx")
- public class XgXxx extends TenantEntity {
- @Serial
- private static final long serialVersionUID = 1L;
- /**
- * 主键ID
- */
- @TableId(value = "id", type = IdType.ASSIGN_ID)
- private Long id;
- /**
- * 名称
- */
- private String name;
- /**
- * 状态
- */
- private String status;
- /**
- * 备注
- */
- private String remark;
- /**
- * 逻辑删除标志(0存在 1删除)
- */
- @TableLogic
- private Integer delFlag;
- }
- ```
- **BO(业务对象 - 接收前端参数):**
- ```java
- package org.dromara.xg.domain.bo;
- import io.github.linpeilie.annotations.AutoMapper;
- import jakarta.validation.constraints.*;
- import lombok.Data;
- import lombok.EqualsAndHashCode;
- import org.dromara.common.core.validate.AddGroup;
- import org.dromara.common.core.validate.EditGroup;
- import org.dromara.common.mybatis.core.domain.BaseEntity;
- import org.dromara.xg.domain.XgXxx;
- /**
- * XXX业务对象 xg_xxx
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- @Data
- @EqualsAndHashCode(callSuper = true)
- @AutoMapper(target = XgXxx.class, reverseConvertGenerate = false)
- public class XgXxxBo extends BaseEntity {
- /**
- * 主键ID
- */
- @NotNull(message = "主键不能为空", groups = { EditGroup.class })
- private Long id;
- /**
- * 名称
- */
- @NotBlank(message = "名称不能为空", groups = { AddGroup.class, EditGroup.class })
- private String name;
- /**
- * 状态
- */
- private String status;
- /**
- * 备注
- */
- private String remark;
- }
- ```
- **VO(视图对象 - 返回给前端):**
- ```java
- package org.dromara.xg.domain.vo;
- import com.alibaba.excel.annotation.ExcelProperty;
- import io.github.linpeilie.annotations.AutoMapper;
- import lombok.Data;
- import org.dromara.common.excel.annotation.ExcelDictFormat;
- import org.dromara.common.excel.convert.ExcelDictConvert;
- import org.dromara.xg.domain.XgXxx;
- import java.io.Serial;
- import java.io.Serializable;
- import java.time.LocalDateTime;
- /**
- * XXX视图对象 xg_xxx
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- @Data
- @AutoMapper(target = XgXxx.class)
- public class XgXxxVo implements Serializable {
- @Serial
- private static final long serialVersionUID = 1L;
- /**
- * 主键ID
- */
- @ExcelProperty(value = "ID")
- private Long id;
- /**
- * 名称
- */
- @ExcelProperty(value = "名称")
- private String name;
- /**
- * 状态
- */
- @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
- @ExcelDictFormat(dictType = "sys_normal_disable")
- private String status;
- /**
- * 备注
- */
- @ExcelProperty(value = "备注")
- private String remark;
- /**
- * 创建时间
- */
- @ExcelProperty(value = "创建时间")
- private LocalDateTime createTime;
- }
- ```
- ### 4. Mapper 层规范
- ```java
- package org.dromara.xg.mapper;
- import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
- import org.dromara.xg.domain.XgXxx;
- import org.dromara.xg.domain.vo.XgXxxVo;
- /**
- * XXX管理Mapper接口
- *
- * @author Your Name
- * @date 2025-01-XX
- */
- public interface XgXxxMapper extends BaseMapperPlus<XgXxx, XgXxxVo> {
- // 自定义SQL方法在这里定义
- }
- ```
- **对应的 XML(如需自定义SQL):**
- ```xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="org.dromara.xg.mapper.XgXxxMapper">
- <resultMap type="org.dromara.xg.domain.vo.XgXxxVo" id="XgXxxResult">
- <result property="id" column="id"/>
- <result property="name" column="name"/>
- <result property="status" column="status"/>
- <result property="remark" column="remark"/>
- <result property="createTime" column="create_time"/>
- </resultMap>
- </mapper>
- ```
- ---
- ## 🎨 前端开发规范(学工模块)
- ### 1. API 接口定义规范
- ```typescript
- // crm/web/src/api/xg/xxx.ts
- import request from '@/utils/request'
- /**
- * 查询参数接口
- */
- export interface XxxQuery {
- pageNum?: number
- pageSize?: number
- name?: string
- status?: string
- beginTime?: string
- endTime?: string
- }
- /**
- * 表单数据接口
- */
- export interface XxxForm {
- id?: number
- name: string
- status: string
- remark?: string
- }
- /**
- * 视图对象接口
- */
- export interface XxxVO {
- id: number
- name: string
- status: string
- remark?: string
- createTime: string
- updateTime: string
- }
- /**
- * 查询列表
- */
- export function listXxx(query: XxxQuery) {
- return request({
- url: '/xg/xxx/list',
- method: 'get',
- params: query
- })
- }
- /**
- * 查询详细
- */
- export function getXxx(id: number) {
- return request({
- url: `/xg/xxx/${id}`,
- method: 'get'
- })
- }
- /**
- * 新增
- */
- export function addXxx(data: XxxForm) {
- return request({
- url: '/xg/xxx',
- method: 'post',
- data: data
- })
- }
- /**
- * 修改
- */
- export function updateXxx(data: XxxForm) {
- return request({
- url: '/xg/xxx',
- method: 'put',
- data: data
- })
- }
- /**
- * 删除
- */
- export function delXxx(ids: number | number[]) {
- return request({
- url: `/xg/xxx/${ids}`,
- method: 'delete'
- })
- }
- /**
- * 导出
- */
- export function exportXxx(query: XxxQuery) {
- return request({
- url: '/xg/xxx/export',
- method: 'post',
- data: query,
- responseType: 'blob'
- })
- }
- ```
- **关键点:**
- - 接口定义使用 TypeScript interface
- - Query 参数用于列表查询(GET请求的params)
- - Form 用于新增/修改(POST/PUT请求的data)
- - VO 用于展示数据
- - 导出接口需要设置 `responseType: 'blob'`
- ### 2. 列表页面规范
- ```vue
- <!-- crm/web/src/views/xg/xxx/index.vue -->
- <template>
- <div class="app-container">
- <!-- 查询表单 -->
- <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="80px">
- <el-form-item label="名称" prop="name">
- <el-input
- v-model="queryParams.name"
- placeholder="请输入名称"
- clearable
- @keyup.enter="handleQuery"
- />
- </el-form-item>
- <el-form-item label="状态" prop="status">
- <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
- <el-option
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
- </el-form-item>
- </el-form>
- <!-- 工具栏 -->
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- v-hasPermi="['xg:xxx:add']"
- >新增</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate()"
- v-hasPermi="['xg:xxx:edit']"
- >修改</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete()"
- v-hasPermi="['xg:xxx:remove']"
- >删除</el-button>
- </el-col>
- <el-col :span="1.5">
- <el-button
- type="warning"
- plain
- icon="Download"
- @click="handleExport"
- v-hasPermi="['xg:xxx:export']"
- >导出</el-button>
- </el-col>
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
- </el-row>
- <!-- 数据表格 -->
- <el-table
- v-loading="loading"
- :data="xxxList"
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="ID" align="center" prop="id" />
- <el-table-column label="名称" align="center" prop="name" :show-overflow-tooltip="true" />
- <el-table-column label="状态" align="center" prop="status">
- <template #default="scope">
- <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
- </template>
- </el-table-column>
- <el-table-column label="创建时间" align="center" prop="createTime" width="180">
- <template #default="scope">
- <span>{{ parseTime(scope.row.createTime) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
- <template #default="scope">
- <el-tooltip content="修改" placement="top">
- <el-button
- link
- type="primary"
- icon="Edit"
- @click="handleUpdate(scope.row)"
- v-hasPermi="['xg:xxx:edit']"
- />
- </el-tooltip>
- <el-tooltip content="删除" placement="top">
- <el-button
- link
- type="danger"
- icon="Delete"
- @click="handleDelete(scope.row)"
- v-hasPermi="['xg:xxx:remove']"
- />
- </el-tooltip>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <pagination
- v-show="total > 0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
- <!-- 添加或修改对话框 -->
- <el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body>
- <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
- <el-form-item label="名称" prop="name">
- <el-input v-model="form.name" placeholder="请输入名称" />
- </el-form-item>
- <el-form-item label="状态" prop="status">
- <el-radio-group v-model="form.status">
- <el-radio
- v-for="dict in sys_normal_disable"
- :key="dict.value"
- :value="dict.value"
- >{{ dict.label }}</el-radio>
- </el-radio-group>
- </el-form-item>
- <el-form-item label="备注" prop="remark">
- <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
- </el-form-item>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="cancel">取 消</el-button>
- <el-button type="primary" @click="submitForm">确 定</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts" name="Xxx">
- import { listXxx, getXxx, addXxx, updateXxx, delXxx, exportXxx } from '@/api/xg/xxx'
- import type { XxxQuery, XxxForm, XxxVO } from '@/api/xg/xxx'
- // 查询参数
- const queryParams = ref<XxxQuery>({
- pageNum: 1,
- pageSize: 10,
- name: undefined,
- status: undefined
- })
- // 表单数据
- const form = ref<XxxForm>({
- id: undefined,
- name: '',
- status: '0',
- remark: ''
- })
- // 表单校验规则
- const rules = ref({
- name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
- status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
- })
- // 数据列表
- const xxxList = ref<XxxVO[]>([])
- const loading = ref(true)
- const total = ref(0)
- const showSearch = ref(true)
- const single = ref(true)
- const multiple = ref(true)
- const ids = ref<number[]>([])
- // 字典数据
- const { sys_normal_disable } = useDict('sys_normal_disable')
- // 对话框
- const dialog = reactive<DialogOption>({
- visible: false,
- title: ''
- })
- const queryFormRef = ref<ElFormInstance>()
- const formRef = ref<ElFormInstance>()
- /** 查询列表 */
- const getList = async () => {
- loading.value = true
- try {
- const res = await listXxx(queryParams.value)
- xxxList.value = res.rows
- total.value = res.total
- } finally {
- loading.value = false
- }
- }
- /** 搜索按钮操作 */
- const handleQuery = () => {
- queryParams.value.pageNum = 1
- getList()
- }
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value?.resetFields()
- handleQuery()
- }
- /** 多选框选中数据 */
- const handleSelectionChange = (selection: XxxVO[]) => {
- ids.value = selection.map(item => item.id)
- single.value = selection.length !== 1
- multiple.value = !selection.length
- }
- /** 新增按钮操作 */
- const handleAdd = () => {
- reset()
- dialog.visible = true
- dialog.title = '添加XXX'
- }
- /** 修改按钮操作 */
- const handleUpdate = async (row?: XxxVO) => {
- reset()
- const id = row?.id || ids.value[0]
- const res = await getXxx(id)
- Object.assign(form.value, res.data)
- dialog.visible = true
- dialog.title = '修改XXX'
- }
- /** 提交表单 */
- const submitForm = () => {
- formRef.value?.validate(async (valid) => {
- if (valid) {
- try {
- if (form.value.id) {
- await updateXxx(form.value)
- proxy?.$modal.msgSuccess('修改成功')
- } else {
- await addXxx(form.value)
- proxy?.$modal.msgSuccess('新增成功')
- }
- dialog.visible = false
- await getList()
- } catch (error) {
- console.error(error)
- }
- }
- })
- }
- /** 删除按钮操作 */
- const handleDelete = async (row?: XxxVO) => {
- const idList = row?.id ? [row.id] : ids.value
- await proxy?.$modal.confirm('是否确认删除选中的数据?')
- await delXxx(idList)
- proxy?.$modal.msgSuccess('删除成功')
- await getList()
- }
- /** 导出按钮操作 */
- const handleExport = () => {
- proxy?.$download(
- 'xg/xxx/export',
- { ...queryParams.value },
- `xxx_${new Date().getTime()}.xlsx`
- )
- }
- /** 取消按钮 */
- const cancel = () => {
- dialog.visible = false
- reset()
- }
- /** 表单重置 */
- const reset = () => {
- form.value = {
- id: undefined,
- name: '',
- status: '0',
- remark: ''
- }
- formRef.value?.resetFields()
- }
- onMounted(() => {
- getList()
- })
- </script>
- ```
- **关键点:**
- - 使用 `<script setup lang="ts">` 语法
- - 使用 `ref` 和 `reactive` 管理状态
- - 使用 `v-hasPermi` 指令控制按钮权限
- - 使用 `useDict` 获取字典数据
- - 使用 `$modal` 显示消息和确认框
- - 使用 `$download` 下载导出文件
- ### 3. 权限控制
- **权限编码规范:** `xg:模块:操作`
- 示例:
- - `xg:student:list` - 学生列表查询
- - `xg:student:query` - 学生详情查询
- - `xg:student:add` - 学生新增
- - `xg:student:edit` - 学生修改
- - `xg:student:remove` - 学生删除
- - `xg:student:export` - 学生导出
- - `xg:student:import` - 学生导入
- **使用方式:**
- ```vue
- <!-- 按钮权限控制 -->
- <el-button v-hasPermi="['xg:student:add']">新增</el-button>
- <!-- JS中判断权限 -->
- <script setup>
- import { hasPermi } from '@/utils/permission'
- const canEdit = hasPermi(['xg:student:edit'])
- </script>
- ```
- ---
- ## 📝 开发流程指南
- ### 1. 新建学工功能模块完整流程
- #### 后端开发步骤:
- 1. **创建数据库表**(表名格式:`xg_模块名`)
- 2. **创建 Entity 实体类**(`domain/XgXxx.java`)
- 3. **创建 VO 视图对象**(`domain/vo/XgXxxVo.java`)
- 4. **创建 BO 业务对象**(`domain/bo/XgXxxBo.java`)
- 5. **创建 Mapper 接口**(`mapper/XgXxxMapper.java`)
- 6. **创建 Mapper XML**(`resources/mapper/xg/XgXxxMapper.xml`,如需自定义SQL)
- 7. **创建 Service 接口**(`service/IXgXxxService.java`)
- 8. **创建 Service 实现**(`service/impl/XgXxxServiceImpl.java`)
- 9. **创建 Controller 控制器**(`controller/XgXxxController.java`)
- 10. **在菜单管理中配置菜单和权限**
- #### 前端开发步骤:
- 1. **创建 API 接口文件**(`api/xg/xxx.ts`)
- 2. **创建页面文件**(`views/xg/xxx/index.vue`)
- 3. **配置路由**(通过后端菜单管理配置,前端动态加载)
- 4. **测试功能**
- ### 2. 使用代码生成器(推荐)
- 框架提供了强大的代码生成器,可以一键生成所有代码:
- 1. 登录系统,进入 **系统工具 -> 代码生成**
- 2. 点击 **导入表**,选择要生成的数据库表
- 3. 点击 **编辑**,配置生成信息:
- - 基本信息:包名、模块名、作者等
- - 字段信息:字段类型、显示类型、是否必填等
- - 生成信息:生成模板、前端路径等
- 4. 点击 **生成代码**,下载代码包
- 5. 将生成的代码解压到对应目录
- 6. 重启后端服务,刷新前端页面
- ---
- ## 🎯 学工模块常见业务场景
- ### 1. 学生信息管理
- - **表命名**: `xg_student`, `xg_student_msg`
- - **权限前缀**: `xg:student`
- - **API路径**: `/xg/student`
- - **页面路径**: `views/xg/xsjcxx`(学生基础信息)
- ### 2. 宿舍管理
- - **表命名**: `xg_dorm_*`(校区、楼栋、房间、床位等)
- - **权限前缀**: `xg:dorm`
- - **API路径**: `/xg/dorm`
- - **页面路径**: `views/xg/xgss`(学工宿舍)
- ### 3. 班级管理
- - **表命名**: `xg_class_*`
- - **权限前缀**: `xg:class`
- - **API路径**: `/xg/class`
- - **页面路径**: `views/xg/class`
- ### 4. 统计分析
- - **表命名**: 可直接查询其他表统计
- - **权限前缀**: `xg:statistics`
- - **API路径**: `/xg/statistics` 或 `/xg/studentStatistics`
- - **页面路径**: `views/xg/studentStatistics`
- ---
- ## 🔧 常用工具类和方法
- ### 后端常用工具
- **字符串工具 - StringUtils**
- ```java
- import org.dromara.common.core.utils.StringUtils;
- StringUtils.isNotBlank(str) // 判断字符串不为空
- StringUtils.isBlank(str) // 判断字符串为空
- StringUtils.isEmpty(str) // 判断字符串是否为null或空串
- ```
- **对象转换 - MapstructUtils**
- ```java
- import org.dromara.common.core.utils.MapstructUtils;
- // BO 转 Entity
- XgStudent entity = MapstructUtils.convert(bo, XgStudent.class);
- // Entity 转 VO
- XgStudentVo vo = MapstructUtils.convert(entity, XgStudentVo.class);
- // List 转换
- List<XgStudentVo> voList = MapstructUtils.convert(entityList, XgStudentVo.class);
- ```
- **日期工具 - DateUtils**
- ```java
- import org.dromara.common.core.utils.DateUtils;
- DateUtils.parseDate(str) // 解析日期字符串
- DateUtils.parseDateToStr(date) // 日期转字符串
- DateUtils.getNowDate() // 获取当前日期
- ```
- **Excel导出 - ExcelUtil**
- ```java
- import org.dromara.common.excel.utils.ExcelUtil;
- ExcelUtil.exportExcel(list, "标题", XgXxxVo.class, response);
- ```
- ### 前端常用工具
- **日期格式化**
- ```typescript
- import { parseTime } from '@/utils/ruoyi'
- parseTime(new Date()) // 格式化日期时间
- parseTime(date, '{y}-{m}-{d}') // 自定义格式
- ```
- **权限判断**
- ```typescript
- import { hasPermi, hasRole } from '@/utils/permission'
- hasPermi(['xg:student:edit']) // 判断是否有权限
- hasRole(['admin']) // 判断是否有角色
- ```
- **字典标签**
- ```vue
- <dict-tag :options="sys_normal_disable" :value="status" />
- ```
- **文件下载**
- ```typescript
- proxy?.$download('api/url', params, 'filename.xlsx')
- ```
- ---
- ## 🚨 注意事项
- ### 后端开发注意事项
- 1. **权限注解必须添加**:所有 Controller 方法都必须添加 `@SaCheckPermission` 注解
- 2. **操作日志记录**:重要操作(增删改)必须添加 `@Log` 注解
- 3. **防重复提交**:新增/修改操作建议添加 `@RepeatSubmit` 注解
- 4. **参数校验**:使用 `@Validated` 和校验注解(@NotNull、@NotBlank等)
- 5. **事务管理**:涉及多表操作的 Service 方法要添加 `@Transactional` 注解
- 6. **逻辑删除**:删除操作优先使用逻辑删除(delFlag字段)
- 7. **租户隔离**:继承 `TenantEntity` 实现多租户数据隔离
- 8. **SQL注入防护**:使用 MyBatis-Plus 的 Wrapper 构建查询条件,避免字符串拼接
- ### 前端开发注意事项
- 1. **权限控制**:所有操作按钮必须添加 `v-hasPermi` 指令
- 2. **表单校验**:表单提交前必须进行前端校验
- 3. **加载状态**:异步操作要显示 loading 状态
- 4. **错误处理**:API 调用要用 try-catch 捕获异常
- 5. **代码规范**:使用 TypeScript,定义好接口类型
- 6. **组件复用**:相同功能的组件要抽取为公共组件
- 7. **国际化**:涉及到文本的地方考虑国际化支持
- 8. **响应式布局**:页面要考虑不同屏幕尺寸的适配
- ---
- ## 🎨 Web UI 强制规范(bx/bx-web,Fresh Mint 对齐)
- > 本节用于 `bx/bx-web` 前端界面改造与新页面开发,视觉与交互以 `bx/docs/web-admin-ui-spec-fresh-mint.md` 为唯一权威;如与历史样式冲突,以本节和规范文档为准。
- ### 1. 视觉 Token 与基础参数(强制)
- - 主色与语义色:`--primary: #10b981`、`--primary-dark: #059669`、`--primary-bg: #ecfdf5`、`--text: #1e293b`、`--text-muted: #64748b`、`--border: #d9e8e2`、`--table-head: #f8fafc`
- - 正文:`font-size: 14px`、`line-height: 1.5`
- - 圆角:面板/大弹窗 `10px`,按钮/输入 `8px`,行内操作按钮 `6px`
- - 卡片阴影:`0 1px 3px rgba(0,0,0,0.05)`
- ### 2. 页面骨架与列表区(强制)
- - 统一结构:`page-head -> panel -> filter-block -> list-toolbar -> list-body/list-wrap -> pagination(list-pager-bar)`
- - 列表工具栏:仅第一个主动作使用主色实心按钮,其余使用中性描边
- - 操作列必须 `fixed="right"`,并设置足够宽度,禁止按钮换行/截断
- - 分页条必须与表格同容器,`margin-top: 0`,顶部单分割线,禁止脱节
- ### 3. 筛选区规则(强制)
- - 使用网格筛选:默认 4 列,<=1100px 2 列,<=560px 1 列
- - 筛选 label:11px,次级色;控件高度统一 36px
- - “更多筛选”展开区与操作行之间只用间距,不加横向分割线
- - 查询/重置/展开更多按钮必须带 loading 状态(与请求态一致)
- ### 4. 弹窗与详情查看(强制)
- - 详情弹窗优先采用:`hero(标题+状态+摘要) + section 分块 + kv 网格`
- - 详情信息区统一两列键值布局,自适应降为单列;禁止同页混用无规则单列/三列
- - 审批流区域统一 `max-height + overflow-y:auto`
- - 查看弹窗底部仅保留“关闭/返回”类动作,不混入提交语义按钮
- - 长文本默认使用“最多 3 行 + 展开/收起”组件,避免拉长弹窗
- ### 5. 表格型详情区块(强制)
- - 诸如“冲抵记录/冲抵明细/流水”等区块必须复用统一组件(标题+表格+空态)
- - 空数据必须展示统一空态,不允许直接隐藏整个区块导致信息断层
- ### 6. 表单弹窗规则(强制)
- - 新增/编辑弹窗默认两列表单(`label-position="top"`),长文本字段跨整行
- - footer 按钮统一:取消(中性)/确定(主色),图标与文字间距 6px
- - 长表单校验失败时需滚动定位到首个错误项(平滑滚动)
- ### 7. 交互与可访问性(强制)
- - 图片预览、下载、附件区块需统一行为与样式,不得各页自定义分叉
- - 关键按钮与分页切换必须可键盘访问,焦点态清晰可见
- - 颜色语义统一:success=已完成,warning=待处理,danger=异常,info=中性
- ### 8. 改造执行与验收(强制)
- - 改造顺序:Token -> 骨架 -> 组件(筛选/按钮/表格/弹窗)-> 页面微调
- - 每次 UI 改造必须至少覆盖:字号、间距、边框、按钮层级、断点自适应
- - 禁止“只改局部页面样式不抽共用组件”;重复结构优先组件化
- ## 📱 BX Mobile UI 强制规范(bx/bx-mobile,Fresh Mint 对齐)
- > 本节用于 `bx/bx-mobile`(Vant 4 + Vue 3)移动端页面开发与改造。视觉与交互以移动端规范文档 `bx/docs/mobile-ui-spec-fresh-mint.md` 为权威,如与历史页面冲突,以本节和移动端规范文档为准。
- ### 1. 设计 Token 与主题映射(强制)
- - 统一使用 `src/styles/index.css` 中 token,不允许页面内硬编码主色(`#00c98d`、`#10b981` 等)覆盖全局语义。
- - 颜色语义固定:`success=通过/完成`、`warning=待处理`、`danger=异常/驳回`、`info=进行中`、`muted=草稿/中性`。
- - Vant 主题色必须对齐 token:`van-button--primary`、`van-tabs__line`、`van-tabbar-item--active`、`van-nav-bar` 等保持统一薄荷主色链。
- ### 2. 页面骨架与安全区(强制)
- - 页面容器统一使用 `.page` 或同等结构,遵循 `padding: 12px 16px 80px` 的内容节奏。
- - 底部操作区/底栏必须包含 `env(safe-area-inset-bottom)`,避免 iPhone 刘海屏/底部手势区遮挡。
- - 全宽组件(`van-nav-bar`、`van-search`、`van-tabs`、`van-pull-refresh`)按全局样式贴边,不在业务页重复写负 margin。
- ### 3. 卡片与列表规范(强制)
- - 业务列表统一卡片化:白底、`12px` 圆角、`1px` 边框、轻阴影,信息密度优先“标题 + 状态 + 金额 + 时间”。
- - 可点击卡片必须有按下反馈(缩放或底色变化),状态条/左侧强调线使用语义色,不得随页面自定义颜色体系。
- - 卡片内操作按钮遵循“首要操作主色,其余中性/危险”规则;异步按钮必须有 loading 与禁用态。
- ### 4. 表单与交互反馈(强制)
- - 输入控件默认高度 42-46px,`label` 在上、输入在下;错误态必须有红色边框和明确文案。
- - 登录/提交类按钮必须防重复点击(loading + disabled);失败反馈优先“字段错误态 + toast”组合。
- - 密码框、树形选择、费用项联动等交互组件需支持“可逆操作”(清空、收起、回退)与状态回显。
- ### 5. 首页与导航入口(强制)
- - 首页使用“欢迎区 + 菜单卡片 + 待办区”三级层次,禁止菜单入口直接堆叠为无分组长列表。
- - 菜单宫格支持消息红点、待办计数,红点只用于需要用户处理的业务入口。
- - 顶部欢迎区可包含汇总数据(如本月金额、审批进度),强调信息不超过 2-3 个,避免视觉噪音。
- ### 6. 弹层与底部 Sheet(强制)
- - 底部选择器(如一级/二级费用项)统一使用 bottom sheet:遮罩 + 顶部标题栏 + 主体双栏 + 底部确认动作。
- - 选择器必须支持关键词检索和已选路径回显;确认按钮在未完成选择时禁用。
- - 弹层圆角、阴影、遮罩透明度与全局保持一致,禁止页面私有“另一个风格”的弹层。
- ### 7. 移动端验收清单(强制)
- - 至少覆盖:配色统一、卡片层级、按钮 loading、错误态、安全区、窄屏可读性。
- - 真机验收至少覆盖 iOS/Android 各 1 台(或对应模拟器),重点检查底部操作栏、输入焦点和滚动穿透。
- - 新增页面时优先复用已有公共样式/结构(`card`、`status-tag`、`apply-list-item`、`bottom-action-bar`),避免重复造样式。
- ### 学工模块特殊注意
- 1. **学生隐私保护**:身份证号、手机号等敏感信息需要脱敏处理
- 2. **数据权限控制**:根据用户角色(辅导员、班主任等)限制数据访问范围
- 3. **批量操作优化**:大量学生数据的批量导入/导出要考虑性能优化
- 4. **工作流集成**:涉及审批流程的功能需要集成工作流引擎
- 5. **数据统计性能**:统计分析功能要注意查询性能,必要时使用缓存
- ---
- ## 📚 参考资源
- ### 官方文档
- - **RuoYi-Vue-Plus 文档**: https://plus-doc.dromara.org
- - **Vue 3 文档**: https://cn.vuejs.org
- - **Element Plus 文档**: https://element-plus.org/zh-CN
- - **MyBatis-Plus 文档**: https://baomidou.com
- - **Sa-Token 文档**: https://sa-token.cc
- ### 框架特色功能文档
- - **多租户**: https://plus-doc.dromara.org/#/ruoyi-vue-plus/framework/tenant
- - **数据权限**: https://plus-doc.dromara.org/#/ruoyi-vue-plus/framework/data_permission
- - **数据脱敏**: https://plus-doc.dromara.org/#/ruoyi-vue-plus/framework/sensitive
- - **工作流**: https://plus-doc.dromara.org/#/ruoyi-vue-plus/framework/workflow
- - **代码生成器**: https://plus-doc.dromara.org/#/ruoyi-vue-plus/other/generator
- ---
- ## 🎓 总结
- 遵循本规范文件,AI可以:
- 1. **理解项目整体架构**:前后端分离、模块化设计
- 2. **快速生成标准代码**:Controller、Service、Mapper、Vue页面等
- 3. **保持代码风格统一**:命名规范、注解使用、权限控制等
- 4. **处理学工业务场景**:学生管理、宿舍管理、统计分析等
- 5. **避免常见错误**:权限遗漏、参数校验缺失、SQL注入等
- **开发原则**:
- - ✅ 代码规范统一
- - ✅ 安全性优先
- - ✅ 性能优化考虑
- - ✅ 用户体验良好
- - ✅ 可维护性强
- **生成代码时的核心要求**:
- 1. 严格遵循本文档的命名规范和代码结构
- 2. 必须包含完整的权限控制和参数校验
- 3. 前后端接口定义要保持一致
- 4. 注释要清晰完整
- 5. 考虑学工业务的特殊性(隐私保护、数据权限等)
|