opencode4-在已有项目中增加修改功能

本节目标

本节还是以开源项目RuoYi-Vue-Plus 为例,看看如何对已有项目添加和修改功能的一个完整流程。这个开源项目地址:gitee.com/dromara/Ruo...

  • 了解/new命令作用
  • 了解 /init 命令作用
  • 了解 AGENTS.md文件的重要性
  • 仅增加后端接口,不实现前端页面

先让RuoYi-Vue-Plus 跑起来

这个步骤,我们也利用 AI 帮我们做很多事情。比如:

  • 数据库的初始化工作
  • 配置修改工作

这里我选用的大模型是 claude sonnet 4.6 模型。为什么订阅 GitHub copilot ,就是因为它其中包含 Claude 这几个编程模型。非常好用!其中 sonnet 模型用于一般编程工作;而 opus 用于框架设计和复杂编程工作。不过这里是需要科学上网才能使用。这个要想用的话,需要自行解决。

数据库初始化

按照上节中提到的思路,让 opencode 通过官方文档进行学习。自动帮我们进行数据库初始化工作。

官方学习文档:plus-doc.dromara.org/#/_readme

  • 提示词

    bash 复制代码
    帮我在远程的 mysql 数据库上创建本项目所需的数据库。
    官方学习文档:https://plus-doc.dromara.org/#/_readme
    我的 mysql 数据库的相关信息如下:
    mysql服务器 ip:your mysql server ip
    端口:3306
    用户名:root
    密码:your password
    根据官网文档介绍,帮我创建所需的库和表吧。这里特别说明下,我仅仅需要ruoyi-vue-plus的基础库表。
  • 执行结果

    补充说明:

    其实我开始用的是一个opencode免费的模型MiniMax M2.5 Free模型。结果这个模型,告诉我无法直接操作远程的mysql数据库。它找不到对应的mysql客户端工具。但是用claude的模型它就能通过安装Node.js的mysql2包来连接mysql数据库。虽然免费的模型最后也能给我所有执行的脚本和完整步骤,但是依然没有"全自动"创建库表。所以,一个好的模型是灵魂。

配置文件修改

由于还是在这个上下文中沟通,所以不用再特别强调官方学习文档地址了。

  • 提示词

    yaml 复制代码
    帮我修改dev环境的配置文件,仅仅保留最基础的功能,其他功能都先关闭。
    修改数据库连接为刚才创建的库连接。
    redis相关信息如下:
    host: your redis host ip
    port: 6379
    password: your redis password
  • 执行结果

在 idea 中跑起来

这个 5.X 版本最低也要 JDK17 版本,我的环境是 JDK21 的。完全满足。启动最后打印的内容如下:

/new 命令

在 opencode 中,/new表示开始新的会话。这个命令会清空上下文记忆。也就是再次和模型对话时省 token 了。但是也失去了历史的上下文记忆了。特别适合在新功能开发;或者提交代码后的 bug 修复。总之是任务告一段落了。

和在UI 中点击新建会话一样:

我们这里用/new是表示,前期的准备告一段落了。在和大模型沟通的上下文中不用包含历史对话信息了。

/init 命令

这个命令会给项目做一个全面扫描,了解项目后生成一个 AGENTS.md文档。如果已经存在这个AGENTS.md文档,再次执行/init 命令时,该命令会尝试在其基础上进行补充。我们来执行这个命令,并且大概看下它生成的文档。记住哈,这一步很重要,新加功能和修改已有功能都基于此文档中定义的规则和约束进行的。

看下执行结果:

看起来还不错,只不过都是英文的。我们可以让 opencode 转为中文。当然为了避免这种情况,我们可以在全局规则中增加简体中文的交互规则。

AGENTS.md 文件

这个AGENTS.md文件,你可以理解成大模型的参考手册。是用于定义、配置和规范 AI Agent(智能体)的行为准则与技术细节的文档。这个文件可以是在项目下的,也可以在用户目录下的。一般在用户目录下的AGENTS.md就是全局的规则文件了。

生成全局 AGENTS.md文件

这步我们可以在 opencode 中直接让它来帮我们创建出来。

  • 提示词

    复制代码
    在全局规则中增加始终使用简体中文与我交流
  • 执行结果

  • 全局规则文件内容

    C:\Users\mayuanfei.config\opencode\AGENTS.md

    bash 复制代码
    # 全局规则
    ​
    始终使用简体中文与用户交流。
  • 可以增加更多自己的配置信息

    markdown 复制代码
    # 语言要求 
    * 始终使用简体中文与我交流。 
    * 思考过程(Thinking)和最终回答都必须使用中文。 
    * 即便我用英文提问,也请用中文回答。
    ​
    # JAVA环境
    * JDK21在/Users/mayuanfei/.sdkman/candidates/java/21.0.8-zulu目录。默认JDK21环境。
    * JDK8在/Users/mayuanfei/.sdkman/candidates/java/8.0.442-zulu。根据当前项目使用。
    ​
    # MAVEN环境
    * maven在/Users/mayuanfei/apache-maven-3.8.3
    * maven的默认配置文件在/Users/mayuanfei/apache-maven-3.8.3/conf/settings-jdk21.xml
    * 编译项目时加上-DskipTests,来排除测试类。
    ​
    # 编码整体要求
    * 一个方法不能超过40行
    * 如果是JDK21的项目,语法尽量使用JDK21新的语法。

    注意:这个全局规则文件尽量不要太长,因为它是所有项目都要遵循的规则。

项目AGENTS.md文件

尽量将全局配置的内容和项目配置的区分开。尽量不要配置冲突项。比如:全局配置一个方法不能超过40行代码;而你在项目的规则文件中定义一个方法不能超过20行。那么本地的约束>全局的配置。

  • 翻译为中文

    复制代码
    把当前项目的AGENTS.md文档都翻译为中文
  • 添加自己的规则

    这个可以按照自己平时项目中的规则,增加相应的约束。比如我这里在公有方法和私有方法之间增加个分割线。

    csharp 复制代码
    ## 公私有方法分割线
    在类的公有方法和私有方法 中间加上"//////////////////////////////////////公私有方法分割线//////////////////////////////////"。例如:
    ​
    ```java
    public String publicA() {
    return "";
    }
    public String publicB() {
    return "";
    }
    ​
    //////////////////////////////////////公私有方法分割线//////////////////////////////////
    ​
    private String privateA() {
    ​
    }
    private String privateB() {
    ​
    }
    ```
    但是如下情况不用加分割线标识:
    1. 接口类不用加
    2. 如果一个类中只有public方法,那么结尾不用加

增加新接口

业务功能

这里假设做一个商品类别的增删改查接口吧。商品类别的表名:t_goods_category。结构如下:

字段名 数据类型 约束 备注
id bigint PK, 自增 分类ID (雪花算法值)
parent_id bigint Not Null 父分类ID (一级分类为 0)
name varchar(64) Not Null 分类名称
level tinyint Not Null 层级 (1-一级, 2-二级, 3-三级)
sort_order int Default 0 排序值 (数值越小越靠前)
icon varchar(255) - 图标地址
is_visible tinyint(1) Default 1 是否显示 (0-隐藏, 1-显示)
remark varchar(200) - 备注说明
create_time datetime Not Null 创建时间
update_time datetime - 更新时间
deleted_flag tinyint(1) Default 0 逻辑删除 (0-正常, 1-已删除)

这个表就是在 md 文档中直接进行设计的。下面也会用这个设计内容直接创建表和测试数据。

创建表和测试数据

这步还是利用 opencode 帮我们来创建。

  • 执行/new 来创建一个新会话

  • 提示词

    scss 复制代码
    结合当前项目 dev 环境配置的 mysql连接相关配置信息。做如下事情:
    1. 在库中创建t_goods_category表,表结构如下:
    | **字段名**       | **数据类型**   | **约束**  | **备注**                      |
    | ---------------- | -------------- | --------- | ----------------------------- |
    | **id**           | `bigint`       | PK, 自增  | 分类ID (雪花算法值)           |
    | **parent_id**    | `bigint`       | Not Null  | 父分类ID (一级分类为 0)       |
    | **name**         | `varchar(64)`  | Not Null  | 分类名称                      |
    | **level**        | `tinyint`      | Not Null  | 层级 (1-一级, 2-二级, 3-三级) |
    | **sort_order**   | `int`          | Default 0 | 排序值 (数值越小越靠前)       |
    | **icon**         | `varchar(255)` | -         | 图标地址                      |
    | **is_visible**   | `tinyint(1)`   | Default 1 | 是否显示 (0-隐藏, 1-显示)     |
    | **remark**       | `varchar(200)` | -         | 备注说明                      |
    | **create_time**  | `datetime`     | Not Null  | 创建时间                      |
    | **update_time**  | `datetime`     | -         | 更新时间                      |
    | **deleted_flag** | `tinyint(1)`   | Default 0 | 逻辑删除 (0-正常, 1-已删除)   |
    2. 在t_goods_category表中创建 10 条测试数据
  • 创建结果

    在 ry-vue 库中多了一个 t_goods_category 表,并且已经有 10 条测试记录了。

生成商品分类表的接口方法

  • 提示词

    复制代码
    结合当前项目的开发规范,在项目的合适包中,生成针对t_goods_category 表的增删改查接口。
  • 生成代码结果

测试生成的新代码

  • 让框架不验证权限

    bash 复制代码
    我要通过reqable工具来请求/goods/category/listAll,帮我设置一下不校验相关的权限。

    这里看到它用@SaIgnore 注解来忽略权限校验了

  • 通过 reqable 测试接口

    说明:

    我是一边操作一边来写这篇文档的。这里能一次测试通过,也的确是没有想到。说明这个 opus 模型是真的厉害。

浏览下生成的代码

perl 复制代码
package org.dromara.system.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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.GoodsCategory;
import org.dromara.system.domain.bo.GoodsCategoryBo;
import org.dromara.system.domain.vo.GoodsCategoryVo;
import org.dromara.system.mapper.GoodsCategoryMapper;
import org.dromara.system.service.IGoodsCategoryService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * 商品分类 服务层实现
 *
 * @author mayuanfei
 */
@RequiredArgsConstructor
@Service
public class GoodsCategoryServiceImpl implements IGoodsCategoryService {

    private final GoodsCategoryMapper baseMapper;

    /**
     * 分页查询商品分类列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 商品分类分页列表
     */
    @Override
    public TableDataInfo<GoodsCategoryVo> selectPageCategoryList(GoodsCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<GoodsCategory> lqw = buildQueryWrapper(bo);
        Page<GoodsCategoryVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(page);
    }

    /**
     * 查询商品分类详情
     *
     * @param id 分类ID
     * @return 商品分类信息
     */
    @Override
    public GoodsCategoryVo selectCategoryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询商品分类列表
     *
     * @param bo 查询条件
     * @return 商品分类集合
     */
    @Override
    public List<GoodsCategoryVo> selectCategoryList(GoodsCategoryBo bo) {
        LambdaQueryWrapper<GoodsCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 新增商品分类
     *
     * @param bo 商品分类信息
     * @return 结果
     */
    @Override
    public int insertCategory(GoodsCategoryBo bo) {
        GoodsCategory category = MapstructUtils.convert(bo, GoodsCategory.class);
        return baseMapper.insert(category);
    }

    /**
     * 修改商品分类
     *
     * @param bo 商品分类信息
     * @return 结果
     */
    @Override
    public int updateCategory(GoodsCategoryBo bo) {
        GoodsCategory category = MapstructUtils.convert(bo, GoodsCategory.class);
        return baseMapper.updateById(category);
    }

    /**
     * 删除商品分类
     *
     * @param id 分类ID
     * @return 结果
     */
    @Override
    public int deleteCategoryById(Long id) {
        return baseMapper.deleteById(id);
    }

    /**
     * 批量删除商品分类
     *
     * @param ids 需要删除的分类ID
     * @return 结果
     */
    @Override
    public int deleteCategoryByIds(Long[] ids) {
        return baseMapper.deleteByIds(Arrays.asList(ids));
    }

    //////////////////////////////////////公私有方法分割线//////////////////////////////////

    /**
     * 构建查询条件
     *
     * @param bo 查询条件对象
     * @return LambdaQueryWrapper
     */
    private LambdaQueryWrapper<GoodsCategory> buildQueryWrapper(GoodsCategoryBo bo) {
        LambdaQueryWrapper<GoodsCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, GoodsCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), GoodsCategory::getName, bo.getName());
        lqw.eq(bo.getLevel() != null, GoodsCategory::getLevel, bo.getLevel());
        lqw.eq(bo.getIsVisible() != null, GoodsCategory::getIsVisible, bo.getIsVisible());
        lqw.orderByAsc(GoodsCategory::getSortOrder);
        return lqw;
    }

}

说明:

1.生成的代码很符合咱们在 AGENTS.md 文件定义的公私有方法中有分割线。

2.但是很多生成的代码在 ruoyi-system 模块中了。理论上需要新增自己的业务模块。

本节总结

  • 我们用 RuoYi-Vue-Plus 做示例项目,用 opencode 让它跑起来。
  • 了解一个项目的最快方式就是让 AI 直接告诉你
  • /new 新开一个会话
  • /init 创建或更新 AGENTS.md 文件
  • 全局AGENTS.md是给所有项目的规约
  • 一个好用的大模型,是愉快 coding 的前提
相关推荐
善良勤劳勇敢而又聪明的老杨2 分钟前
【AI编程系列】MCP 常用设计模式解读
设计模式·ai编程
wdfk_prog3 分钟前
lely-canopen-rtt:为什么推荐在 RT-Thread 上使用 Lely CANopen 构建主站
java·运维·缓存·docker·容器
海盗12347 分钟前
DSH 接入 OpenCode Go 报 400 MissingSessionID:从 LLM 语义层退到 fetch 传输层的完整排障
开发语言·后端·golang
Token掘金室8 分钟前
JSON模式结构化输出报错
java·服务器·json
秋饼14 分钟前
Spring AI 2.0 接入 DeepSeek V4.1 Flash 生产级实战
java·ai·技术分享·后端开发
IT枫斗者枫哥14 分钟前
Java 分批导出仍然 OOM?用 32 MiB 堆复现三种 CSV 写法
java
一木 之林16 分钟前
第 3 节 在 AI 行业中,C/C++ 编程中的动态库和静态库
c语言·c++·后端
skywalkerch22 分钟前
Spring 循环依赖与三级缓存
后端
shehuiyuelaiyuehao23 分钟前
算法43,外观数列,模拟算法+双指针
java·算法
VIP_CQCRE40 分钟前
把 OpenCode 接入 Ace Data Cloud:让 AI 编程能力真正进入 IDE 工作流
大模型·ai编程·开发工具·opencode·acedatacloud