jeecgboot/jeecg-uniapp-codegen
JeecgBoot UniApp3 移动端 CRUD 代码生成器。Use when user asks to generate UniApp3/mobile/APP CRUD pages, create mobile list/form pages, or says '生成移动端代码', '生成APP页面', 'uniapp代码生成', '移动端CRUD', '生成uniapp页面', '手机端页面', '移动端模块', 'generate uniapp code', 'mobile CRUD', 'uniapp page', 'APP端代码', '生成小程序页面', '生成H5页面'. Also triggers when user mentions generating mobile pages for an existing backend module, or wants to add mobile support to JeecgBoot modules. Even if user just says '给XX模块加个移动端页面' or '做个手机端的XX功能', this skill should trigger.
npx skills add https://github.com/jeecgboot/skills --skill jeecg-uniapp-codegen
将自然语言需求或已有后端接口信息转换为 JeecgBoot UniApp3 移动端全套 CRUD 代码(列表页 + 表单页 + 数据定义),支持单表 CRUD、一对多主子表、树表等场景。
> 项目路径: <uniapp_project_root>(动态,使用前需向用户确认,见 Step 0)
> 后端模板参考: <uniapp_project_root> 同级目录下的后端项目(如有)
生成代码前必须理解以下项目核心约定,具体细节见 references/ 目录下的参考文件:
| 参考文件 | 内容 |
|---------|------|
| references/project-architecture.md | 项目结构、目录约定、页面注册机制 |
| references/component-patterns.md | 组件库用法、表单控件映射、在线组件清单 |
| references/code-templates.md | 三个核心前端文件的完整模板和变量说明 |
在执行任何操作之前,必须先询问用户以下信息(一次性展示,用户说"确认"使用默认值):
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| UniApp3 项目根目录 | —(必填) | 如 D:\projects\jeecgboot-uniapp3 |
用户回复后,记为:
<uniapp_project_root> — 前端项目根目录> 路径记忆规则: 同一对话中用户提供一次后,后续步骤直接复用,不再重复询问。
场景 A — 已有后端接口(用户给了表名/实体名/接口路径):
/test/demo)Demo)、包路径(如 test)、字段列表场景 B — 从需求描述生成前端:
classType一次性展示所有选项及默认值,用户说"确认"即可全部采用:
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| 实体名 | 从需求推导(PascalCase) | 如 BizGoods |
| 功能描述 | 从需求推导 | 导航栏标题,如 "商品管理" |
| 页面目录 | <uniapp_project_root>/src/pages-home/{模块名}/ | 生成文件的存放目录 |
| API路径前缀 | /{模块包路径}/{实体名首字母小写} | 如 /biz/bizGoods |
| 列表展示字段 | 前3个非id非系统字段 | 列表卡片上显示的字段 |
每个单表 CRUD 模块生成 3 个文件,路径基于 <uniapp_project_root>:
<uniapp_project_root>/src/pages-home/{模块名}/
├── {EntityName}List.vue # 列表页(分页 + 滑动删除 + 新增入口)
├── {EntityName}Form.vue # 表单页(新增/编辑 + 表单校验 + 提交)
└── {EntityName}Data.ts # 列表字段列定义
在 <uniapp_project_root>/src/pages.json 的 subPackages 中注册新页面(如果目标目录已是 subPackage 则追加 pages,否则新增 subPackage)。
展示生成的文件清单、页面路由配置、后续操作说明。
根据字段信息推导 classType(决定表单使用哪个组件):
| 字段特征 | classType | 表单组件 |
|----------|-----------|----------|
| 名称含"图片/头像/照片/logo" | image | <online-image> |
| 名称含"文件/附件/简历" | file | <online-file-custom> |
| 名称含"日期" 且无"时间" | date | <online-date> |
| 名称含"时间" 或 "datetime" | datetime | <DateTime> |
| 名称含"开关/启用/是否" | switch | <wd-switch> |
| 有字典值(枚举选项 <= 5个) | radio | <online-radio> |
| 有字典值(枚举选项 > 5个) | list | <online-select> |
| 名称含"多选" 或需多选字典 | checkbox | <online-checkbox> |
| 名称含"备注/描述/内容/简介" | textarea | <wd-textarea> |
| 名称含"密码" | password | <wd-input show-password> |
| 名称含"省市区/地址" | pca | <online-pca> |
| 名称含"部门" | sel_depart | <SelectDept> |
| 名称含"用户/人员/负责人" | sel_user | <SelectUser> |
| 名称含"分类" 且有树结构 | cat_tree | <CategorySelect> |
| DB类型为 int/long/double/BigDecimal | 数字输入 | <wd-input inputMode="numeric"> |
| 默认(字符串类型) | 文本输入 | <wd-input> |
| 场景 | 校验规则 |
|------|----------|
| 必填字段(nullable=N) | { required: true, message: '请输入${comment}!' } |
| 手机号 | { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!' } |
| 邮箱 | { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}\|)$/, message: '请输入正确的电子邮件!' } |
| 网址 | { pattern: /^((ht\|f)tps?):\/\/.../, message: '请输入正确的网址!' } |
| 数字 | { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!' } |
| 整数 | { pattern: /^-?\d+$/, message: '请输入整数!' } |
| 金额 | { pattern: /^(([1-9][0-9]*)\|([0]\.\d{0,2}\|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!' } |
关键特征:
- 使用 <route> 标签声明页面路由信息(layout、style、navigationBarTitleText)
- 使用 <PageLayout> 包裹,设置 navTitle 和 backRouteName
- 使用 z-paging 实现分页加载
- 使用 wd-swipe-action 实现左滑删除
- 使用 usePageList hook 管理列表数据加载
- 引入 {EntityName}Data.ts 的 columns 定义
- 列表卡片默认展示前3个字段
- 固定定位的"+"按钮用于新增
- uni.$on('refreshList') 监听表单提交后的列表刷新
详细模板见 references/code-templates.md 的"列表页模板"章节。
关键特征:
- 使用 <route> 标签声明页面路由信息
- 使用 <PageLayout> 包裹,navTitle 动态切换"新增/编辑"
- 使用 wd-form + wd-cell-group 组织表单
- 通过 onLoad 获取 route params 中的 dataId 判断新增/编辑
- 编辑时调用 queryById 接口加载数据
- 表单数据用 reactive({}) 定义
- 提交时先 form.validate(),再根据 dataId 调用 add 或 edit 接口
- 提交成功后 uni.$emit('refreshList') 通知列表刷新,然后 router.back()
- 根据字段 classType 渲染对应组件(见组件映射表)
- 支持唯一性校验(调用 duplicateCheck API)
- label 超过4个字符时自动截断(get4Label)
详细模板见 references/code-templates.md 的"表单页模板"章节。
关键特征:
- 导出 columns 数组,定义列表显示的字段
- 每个字段包含 title(显示名)和 dataIndex(字段名)
- 字典类型字段的 dataIndex 使用 `${fieldName}_dictText` 后缀
- 图片类型字段添加 customRender: render.renderImage
- 开关类型字段添加 customRender 渲染是/否文本
- Blob 类型字段的 dataIndex 使用 `${fieldName}String` 后缀
详细模板见 references/code-templates.md 的"数据定义模板"章节。
生成的页面需要在 src/pages.json 的 subPackages 中注册。使用 <route> 标签方式(uni-pages 插件自动解析),或手动在 pages.json 中添加。
<route> 标签格式(推荐,写在 .vue 文件顶部):
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationBarTitleText: '功能标题',
navigationStyle: 'custom',
},
}
</route>
如果目标目录不在已有 subPackages 中,需要手动在 pages.json 添加:
{
"root": "pages-home",
"pages": [
{
"path": "模块目录/EntityNameList",
"type": "page",
"layout": "default",
"style": {
"navigationBarTitleText": "功能标题",
"navigationStyle": "custom"
}
},
{
"path": "模块目录/EntityNameForm",
"type": "page",
"layout": "default",
"style": {
"navigationBarTitleText": "功能标题",
"navigationStyle": "custom"
}
}
]
}
JeecgBoot 后端标准 CRUD 接口路径:
| 操作 | 方法 | 路径 |
|------|------|------|
| 分页列表 | GET | /{packagePath}/{entityName}/list |
| 查询单条 | GET | /{packagePath}/{entityName}/queryById?id=xxx |
| 新增 | POST | /{packagePath}/{entityName}/add |
| 编辑 | POST | /{packagePath}/{entityName}/edit |
| 删除 | DELETE | /{packagePath}/{entityName}/delete?id=xxx |
| 唯一性校验 | GET | /sys/duplicate/check |
HTTP 工具使用 @/utils/http 的 http 对象,支持 http.get() / http.post() / http.delete() / http.put() 方法。
import { ref, onMounted, computed } from 'vue'
import { http } from '@/utils/http'
import usePageList from '@/hooks/usePageList'
import { columns } from './{EntityName}Data'
import { onLoad } from '@dcloudio/uni-app'
import { http } from '@/utils/http'
import { useToast } from 'wot-design-uni'
import { useRouter } from '@/plugin/uni-mini-router'
import { ref, onMounted, computed, reactive } from 'vue'
import { duplicateCheck } from '@/service/api'
| classType | 导入语句 |
|-----------|----------|
| image | import OnlineImage from '@/components/online/view/online-image.vue' |
| file | import OnlineFileCustom from '@/components/online/view/online-file-custom.vue' |
| datetime / time | <DateTime> 组件(easycom 自动注册,位于 @/components/DateTime/DateTime.vue) |
| date | import OnlineDate from '@/components/online/view/online-date.vue' |
| list / sel_search | import OnlineSelect from '@/components/online/view/online-select.vue' |
| checkbox | import OnlineCheckbox from '@/components/online/view/online-checkbox.vue' |
| radio | import OnlineRadio from '@/components/online/view/online-radio.vue' |
| list_multi | import OnlineMulti from '@/components/online/view/online-multi.vue' |
| textarea | 无需导入(使用 wot-design-uni 的 <wd-textarea>,easycom 自动注册) |
| password | 无需导入(使用 <wd-input show-password>,easycom 自动注册) |
| pca | import OnlinePca from '@/components/online/view/online-pca.vue' |
| sel_depart | import SelectDept from '@/components/SelectDept/SelectDept.vue' |
| sel_user | import SelectUser from '@/components/SelectUser/SelectUser.vue' |
| popup_dict | <PopupDict> 组件(easycom 自动注册,位于 @/components/PopupDict/PopupDict.vue) |
| popup | <Popup> 组件(easycom 自动注册,位于 @/components/Popup/Popup.vue) |
| link_table | import OnlinePopupLinkRecord from '@/components/online/view/online-popup-link-record.vue' |
| cat_tree | <CategorySelect> 组件(easycom 自动注册,位于 @/components/CategorySelect/CategorySelect.vue) |
| sel_tree | <TreeSelect> 组件(easycom 自动注册,位于 @/components/TreeSelect/TreeSelect.vue) |
| switch | 无需导入(使用 <wd-switch>,easycom 自动注册) |
> easycom 说明: 位于 src/components/ 下且目录名与组件名一致的组件会被 easycom 自动注册,无需手动 import。
> wd-* 前缀的组件由 wot-design-uni 提供,也通过 easycom 自动注册。
> online-* 前缀的组件位于 src/components/online/view/,不符合 easycom 规则,必须手动 import。
当前后端代码生成模板仅有单表模板,一对多场景需手动编写。核心模式:
这是高级场景,参考 references/advanced-patterns.md(如需要时创建)。
当前后端代码生成模板无树表 uniapp3 模板。树表移动端通常采用:
<TreeSelect> 组件展示树形数据这是高级场景,参考 references/advanced-patterns.md(如需要时创建)。
> wd-input / wd-textarea 等表单组件的 name 和 prop 属性值必须直接写字段名,禁止用单引号包裹。
>
> `vue
> <!-- ✅ 正确 -->
> <wd-input name="productName" prop="productName" ... />
>
> <!-- ❌ 错误 — 单引号包裹导致 wot-design-uni 校验失效 -->
> <wd-input name="'productName'" prop="'productName'" ... />
> `
>
> Why: wot-design-uni 的 wd-form 校验时用 name/prop 的字面值去匹配 :rules 中的规则和 myFormData 的键。若写成 name="'productName'",传入的是带单引号的字符串字面量 'productName',而不是 productName,导致校验规则永远匹配不上,表单即使有值也提示必填错误。
>
> How to apply: 生成每一个表单字段时,name= 和 prop= 后面的双引号内只写驼峰字段名本身,不加任何额外引号或花括号。
生成代码后自查:
.vue 文件顶部有 <route> 标签defineOptions 中的 name 与文件名一致usePageList 参数路径正确(与后端 API 匹配)backRouteName 指向列表页名称handleAdd 跳转到 {EntityName}Formadd/edit/queryById API 路径正确dict 属性值:required="true" 和 rules{EntityName}Data.ts 中字典字段的 dataIndex 使用了 _dictText 后缀<route> 标签能被 uni-pages 插件识别)name= 和 prop= 均为裸字段名,无多余单引号(如 name="fieldName",而非 name="'fieldName'")Take jeecgboot/jeecg-uniapp-codegen from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.