16 KiB
16 KiB
AI协作工作流程指南
目标:通过图片快速实现菜单功能的高效开发流程
更新时间:2024-12-04
📋 目录
🎯 工作流程总览
核心原则
- 用户提供:功能截图 + 菜单路径
- AI执行:7步标准流程 + 完整日志输出
- 最小化MCP:最小可行代码实现,无需复杂业务逻辑
标准输出格式
每次完成后输出:
- ✅ 完成的工作清单(数据库、后端、前端、文档)
- 📊 数据库字段说明
- 🎯 表格列说明
- 🚀 测试步骤
- 📋 菜单更新记录
🔧 标准操作步骤(7步流程)
步骤1:创建数据库表
-- 1. 创建表结构(根据图片字段设计)
CREATE TABLE IF NOT EXISTS eb_xxx_xxx (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '主键',
-- 根据图片添加字段
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='XXX表';
-- 2. 插入测试数据(至少10条)
INSERT INTO eb_xxx_xxx (...) VALUES (...);
-- 3. 验证数据
SELECT COUNT(*) as total FROM eb_xxx_xxx;
执行命令:
mysql -h 1.15.149.240 -u zhibo -pzCETFpGMwYN3CNeH zhibo -e "SQL语句"
步骤2:创建后端Controller(最小化MCP)
文件路径:zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/XxxController.java
模板代码:
package com.zbkj.admin.controller;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.result.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("api/admin/xxx")
@Api(tags = "XXX管理")
@Validated
public class XxxController {
@Autowired
private JdbcTemplate jdbcTemplate;
// 列表查询(必须)
@ApiOperation(value = "列表")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public CommonResult<CommonPage<Map<String, Object>>> getList(...) {
// 使用JdbcTemplate直接查询
}
// 详情查询(可选)
@ApiOperation(value = "详情")
@RequestMapping(value = "/detail/{id}", method = RequestMethod.GET)
public CommonResult<Map<String, Object>> getDetail(@PathVariable Integer id) {...}
// 添加(如果有添加按钮)
@ApiOperation(value = "添加")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public CommonResult<String> add(@RequestBody Map<String, Object> params) {...}
// 更新(如果有编辑按钮)
@ApiOperation(value = "更新")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult<String> update(@RequestBody Map<String, Object> params) {...}
// 删除(如果有删除按钮)
@ApiOperation(value = "删除")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
public CommonResult<String> delete(@PathVariable Integer id) {...}
// 状态切换(如果有状态开关)
@ApiOperation(value = "切换状态")
@RequestMapping(value = "/status/{id}", method = RequestMethod.POST)
public CommonResult<String> toggleStatus(@PathVariable Integer id, @RequestBody Map<String, Object> params) {...}
}
步骤3:创建前端API文件
文件路径:admin/src/api/xxx.js
模板代码:
import request from '@/utils/request'
// 列表(必须)
export function xxxListApi(params) {
return request({
url: '/admin/xxx/list',
method: 'get',
params
})
}
// 详情(可选)
export function xxxDetailApi(id) {
return request({
url: `/admin/xxx/detail/${id}`,
method: 'get'
})
}
// 添加(如果有)
export function xxxAddApi(data) {
return request({
url: '/admin/xxx/add',
method: 'post',
data
})
}
// 更新(如果有)
export function xxxUpdateApi(data) {
return request({
url: '/admin/xxx/update',
method: 'post',
data
})
}
// 删除(如果有)
export function xxxDeleteApi(id) {
return request({
url: `/admin/xxx/delete/${id}`,
method: 'post'
})
}
// 状态切换(如果有)
export function xxxStatusApi(id, data) {
return request({
url: `/admin/xxx/status/${id}`,
method: 'post',
data
})
}
步骤4:创建前端Vue组件
文件路径:admin/src/views/xxx/xxx/index.vue
组件结构:
<template>
<div class="divBox">
<el-card shadow="never" class="ivu-mt">
<div class="padding-add">
<!-- 1. 添加按钮区(如果有) -->
<div class="mb20">
<el-button type="primary" size="small" @click="handleAdd">+ 添加</el-button>
</div>
<!-- 2. 搜索表单(根据图片) -->
<el-form inline size="small" :model="searchForm" class="mb20">
<!-- 根据图片添加搜索字段 -->
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
<!-- 3. 数据表格(根据图片列) -->
<el-table :data="tableData" v-loading="loading" border>
<!-- 根据图片添加列 -->
</el-table>
<!-- 4. 分页 -->
<el-pagination
v-if="total > 0"
class="mt20"
background
:current-page="searchForm.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="searchForm.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-card>
<!-- 5. 添加/编辑弹窗(如果有) -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
<el-form :model="form" ref="form" label-width="100px">
<!-- 根据图片添加表单字段 -->
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">返回</el-button>
<el-button type="primary" @click="handleSubmit">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { xxxListApi, xxxAddApi, xxxUpdateApi } from '@/api/xxx';
export default {
name: 'XxxList',
data() {
return {
searchForm: { page: 1, limit: 10 },
tableData: [],
total: 0,
loading: false,
dialogVisible: false,
dialogTitle: '添加',
form: {},
};
},
mounted() {
this.getList();
},
methods: {
getList() {
this.loading = true;
xxxListApi(this.searchForm)
.then((res) => {
this.tableData = res.list || [];
this.total = res.total || 0;
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
handleSearch() {
this.searchForm.page = 1;
this.getList();
},
handleSizeChange(val) {
this.searchForm.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.searchForm.page = val;
this.getList();
},
},
};
</script>
步骤5:添加数据库菜单配置
-- 1. 插入菜单
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show) VALUES
(父菜单ID, '菜单名称', '', NULL, '/路由路径', 'C', 排序号, 1);
SET @menu_id = LAST_INSERT_ID();
-- 2. 分配权限给所有角色
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
SELECT DISTINCT rid, @menu_id FROM eb_system_role_menu;
-- 3. 查询结果
SELECT @menu_id as new_menu_id;
-- 4. 查看父菜单完整结构
SELECT id, pid, name, component, menu_type, sort FROM eb_system_menu
WHERE id = 父菜单ID OR pid = 父菜单ID
ORDER BY pid, sort;
执行命令:
mysql -h 1.15.149.240 -u zhibo -pzCETFpGMwYN3CNeH zhibo -e "SQL语句"
步骤6:更新前端路由配置
文件路径:admin/src/router/modules/xxx.js
如果是独立一级菜单:
import Layout from '@/layout';
const xxxRouter = {
path: '/xxx',
component: Layout,
redirect: '/xxx/list',
name: 'Xxx',
alwaysShow: true,
meta: { title: 'XXX管理', icon: 'el-icon-xxx' },
children: [
{
path: 'list',
component: () => import('@/views/xxx/list/index'),
name: 'XxxList',
meta: { title: 'XXX列表', icon: '' },
},
],
};
export default xxxRouter;
在主路由注册(admin/src/router/index.js):
// 1. 导入
import xxxRouter from './modules/xxx';
// 2. 注册(在合适位置)
export const asyncRoutes = [
// ...其他路由
xxxRouter,
// ...
];
如果是子菜单: 直接在父路由文件中添加子路由即可。
步骤7:更新菜单结构文档
文件路径:小张/行动/系统菜单结构总览.md
更新两个位置:
- 完整菜单树
- 本次会话新增菜单
📚 关键文件说明
1. 系统菜单结构总览.md
作用:记录所有菜单的树形结构和本次会话新增内容
格式:
# 系统菜单结构总览
## 完整菜单树
├─ 一级菜单 ▼
│ ├─ 子菜单1
│ └─ 子菜单2
## ⭐ 2024-12-04 新增菜单
├─ XXX管理 ▼ ← 新增
│ └─ XXX列表
2. 菜单配置操作步骤.md
作用:记录菜单配置的详细步骤
内容:
- 数据库菜单表结构
- 前端路由配置方法
- 权限分配方法
3. AI提示词模板.md
作用:提示词参考模板
🗄️ 数据库配置
连接信息
host: 1.15.149.240
user: zhibo
password: zCETFpGMwYN3CNeH
database: zhibo
核心表说明
eb_system_menu(菜单表)
id -- 菜单ID
pid -- 父菜单ID(0=一级菜单)
name -- 菜单名称
icon -- 图标
perms -- 权限标识
component -- 路由路径
menu_type -- 菜单类型(M=目录, C=菜单, A=接口)
sort -- 排序号
is_show -- 是否显示(0=隐藏, 1=显示)
eb_system_role_menu(角色菜单关系表)
rid -- 角色ID
menu_id -- 菜单ID
常见父菜单ID
财务管理: 9
用户管理: ...(查询数据库获取)
📁 项目结构
zhibo-1201/
├─ admin/ # 前端项目
│ ├─ src/
│ │ ├─ api/ # API接口
│ │ │ └─ xxx.js
│ │ ├─ views/ # 页面组件
│ │ │ └─ xxx/
│ │ │ └─ list/
│ │ │ └─ index.vue
│ │ └─ router/ # 路由配置
│ │ ├─ index.js # 主路由
│ │ └─ modules/ # 子路由模块
│ │ └─ xxx.js
│
├─ zhibo-h/ # 后端项目
│ └─ crmeb-admin/
│ └─ src/main/java/com/zbkj/admin/
│ └─ controller/
│ └─ XxxController.java
│
└─ 小张/
└─ 行动/ # 工作文档目录
├─ 系统菜单结构总览.md # ✅ 必须更新
├─ 菜单配置操作步骤.md
└─ AI提示词模板.md
🎨 常见操作模板
1. 只读列表(无CRUD)
- 步骤1: 数据库表 + 测试数据
- 步骤2: Controller(只实现list)
- 步骤3: API(只有listApi)
- 步骤4: Vue组件(搜索 + 表格 + 分页)
- 步骤5-7: 菜单配置和文档更新
2. 完整CRUD列表
- 步骤1: 数据库表 + 测试数据
- 步骤2: Controller(list + detail + add + update + delete)
- 步骤3: API(全套接口)
- 步骤4: Vue组件(搜索 + 表格 + 弹窗 + 分页)
- 步骤5-7: 菜单配置和文档更新
3. 带状态管理的列表
- 在CRUD基础上增加:
- Controller: toggleStatus方法
- API: statusApi
- Vue: el-switch组件 + handleStatusChange方法
⚠️ 注意事项
1. 数据库操作
- ✅ 使用JdbcTemplate,不需要创建实体类
- ✅ SQL防注入:使用replace("'", "''")
- ✅ 测试数据至少10条
- ❌ 不要创建Service层
2. 后端开发
- ✅ 最小化MCP:只实现必要功能
- ✅ 统一返回CommonResult
- ✅ 统一分页CommonPage
- ❌ 不要添加复杂业务逻辑
3. 前端开发
- ✅ 严格按照图片实现UI
- ✅ 搜索条件与图片一致
- ✅ 表格列与图片一致
- ✅ 图片字段使用el-image支持预览
- ✅ 状态字段使用el-switch或el-tag
- ❌ 不要添加图片没有的功能
4. 菜单配置
- ✅ 菜单名称与用户描述一致
- ✅ sort值从小到大排序
- ✅ 一级菜单menu_type='M'
- ✅ 子菜单menu_type='C'
- ✅ 必须分配权限给所有角色
5. 文档更新
- ✅ 必须更新:系统菜单结构总览.md
- ✅ 在两个位置更新:完整树 + 新增列表
- ✅ 使用▼标识有子菜单
- ✅ 使用←标识新增
🚀 快速开始示例
用户输入
这是财务管理下面的XXX明细菜单
[附带截图]
AI响应流程
1. 分析图片
- 识别表格列
- 识别搜索条件
- 识别按钮功能
- 确定数据类型
2. 执行7步流程
步骤1:创建数据库表
步骤2:创建后端Controller
步骤3:创建前端API
步骤4:创建前端Vue组件
步骤5:添加数据库菜单
步骤6:更新前端路由
步骤7:更新菜单文档
3. 输出完成日志
## ✅ XXX明细功能已完成!
### 📊 完成的工作
...
### 🚀 测试步骤
...
### 📋 菜单已更新
...
📖 使用示例
示例1:财务管理 - 送礼物明细
用户输入:
这是财务管理下面的送礼物明细菜单
[图片显示:用户ID、用户图片、用户昵称、用户手机、礼物ID、礼物数量、礼物名称、礼物图片、礼物价值点、收礼人ID、收礼人昵称、收礼人头像、收礼人电话、送礼时间]
AI执行:
- 创建表eb_gift_detail(13个字段)
- 创建GiftDetailController(list接口)
- 创建giftDetail.js API
- 创建giftDetail/index.vue(搜索5个条件 + 13列表格)
- 在财务管理(id=9)下添加菜单
- 在financial.js中添加路由
- 更新系统菜单结构总览.md
输出:完整日志 + 测试步骤
示例2:独立菜单 - 邀请管理
用户输入:
这是邀请管理菜单下面的邀请列表
[图片显示:...]
AI执行:
- 创建表eb_invite
- 创建InviteController
- 创建invite.js API
- 创建invite/list/index.vue
- 创建独立一级菜单"邀请管理"
- 创建invite.js路由并注册到index.js
- 更新文档
🎯 成功标准
完成标志
- ✅ 数据库表创建成功(有测试数据)
- ✅ 后端接口可访问
- ✅ 前端页面显示正确
- ✅ 菜单显示在左侧导航
- ✅ 文档已更新
质量标准
- ✅ 代码简洁(最小化MCP)
- ✅ UI与图片一致
- ✅ 功能完整可用
- ✅ 日志清晰完整
📝 版本历史
| 日期 | 版本 | 说明 |
|---|---|---|
| 2024-12-04 | v1.0 | 初始版本,记录完整工作流程 |
💡 最佳实践
- 看图说话:严格按照用户提供的截图实现,不要添加额外功能
- 最小化实现:只实现图片显示的功能,不要过度设计
- 完整日志:每次完成后输出完整的工作日志和测试步骤
- 及时更新文档:必须更新系统菜单结构总览.md
- 测试数据充足:至少10条测试数据,覆盖不同场景
- 状态标识清晰:使用颜色区分不同状态(成功=绿色、危险=红色、警告=橙色)
- 图片支持预览:所有图片字段支持点击预览
🔄 持续改进
如果遇到新的场景或问题,请更新此文档,确保流程始终保持高效!
记住:这是一个经过验证的高效流程,按照这个流程可以快速实现任何菜单功能!🎉