首页 文章 精选 留言 我的

精选列表

搜索[聚类],共10000篇文章
优秀的个人博客,低调大师

实战|借助 CodeBuddy 开发 AI 课课通微信小程序,教育类小程序提效全流程

## 前言 最近我独立开发一款面向中小学的 AI 教学小程序 ——AI 课课通,核心功能是 AI 习题生成、在线刷题、错题本、知识点解析。作为个人独立开发者,一个人承担产品设计、前端开发、接口对接、调试排错全部工作,项目压力很大。在接触腾讯云 CodeBuddy 之后,极大降低了小程序的开发门槛,把大量重复编码、页面布局、bug 排查工作交给 AI 代码助手,大幅缩短项目周期。本文完整记录我使用 CodeBuddy 开发 AI 课课通小程序的实战经验,分享 Craft 多文件生成、代码补全、bug 修复、省积分的实操技巧。 ## 一、项目简介:AI 课课通小程序 AI 课课通是面向中小学师生的 AI 辅助学习小程序,核心功能清单: 1. 用户登录:微信一键授权登录,自动获取用户信息 1. 课程与知识点分类:按年级、学科筛选学习内容 1. AI 习题生成:输入知识点,自动生成对应练习题 1. 在线答题模块:选择题、填空题作答,即时判分 1. 错题本:自动保存做错题目,支持复习回看 1. AI 解析:对习题给出详细知识点讲解 技术栈:微信原生小程序(WXML+WXSS+JS),腾讯云开发 CloudBase 作为后端数据库,使用**微信开发者工具 + CodeBuddy 插件**进行开发。 > 开发痛点:独立开发者,页面多、交互逻辑繁杂,手写大量模板、表单、数据渲染代码非常消耗时间;很多小程序生命周期、云函数、数据库查询代码记忆不牢,频繁查阅文档。这也是我引入 CodeBuddy 的核心原因。 ## 二、环境准备:微信开发者工具安装 CodeBuddy 插件 1. 下载并打开微信开发者工具,导入小程序项目 1. 左侧扩展市场,搜索:**腾讯云代码助手 CodeBuddy**,认准腾讯云官方出品,点击安装 1. 安装完成重启开发者工具,侧边栏出现 CodeBuddy 图标,即可打开对话面板 1. 登录账号:使用[codebuddy.cn](https://codebuddy.cn)相同微信账号登录,积分互通,免费额度直接可用 > 小提示:CodeBuddy 的行间实时代码补全**不消耗积分**,写 wxml、wxss、js 时自动提示代码,写页面的时候我几乎全程开启,节约大量基础代码编写时间。 ## 三、核心实战:使用 Craft 智能体一次性生成小程序页面 CodeBuddy 最强大的功能就是 Craft 多文件生成智能体,一句话需求直接生成一整套页面多文件代码(wxml/wxss/js/json),非常适合小程序开发,我开发 AI 课课通首页、刷题页、错题本页面,大量使用 Craft。 ### 我的 Craft 提示词示例(直接复制给 CodeBuddy) ```javascript 帮我开发AI课课通小程序【刷题页面】,原生微信小程序,不要框架。 页面功能: 1. 顶部展示当前知识点名称、题号 2. 中间展示题目题干、选择题选项ABCD 3. 用户选择选项,点击提交答案,即时给出对错反馈 4. 下方有查看解析按钮,点击展开AI解析文本 5. 底部上一题、下一题按钮,切换题目 6. 样式简洁教育风,适配手机,做好安全区适配 输出完整的 page 4个文件:index.wxml、index.wxss、index.js、index.json ``` 发送之后,Craft 会自动分析需求,一次性生成整套页面 4 个文件,直接在项目内新建页面,粘贴代码,简单微调就能跑起来。 > 踩坑经验: > 1. 需求描述尽量清晰,写清楚页面交互、风格、字段,需求模糊会导致生成代码需要大量修改; 1. Craft 生成多文件消耗积分较高,简单页面优先用普通对话模式,减少积分消耗; 1. 生成代码后不要直接上线,重点检查数据绑定、云数据库读取逻辑,AI 生成代码可以快速搭建骨架,但业务逻辑需要人工校验。 ## 四、开发中高频场景:CodeBuddy 帮我调试 AI 课课通项目 ### 场景 1:代码解释与阅读理解 项目里云函数读取数据库、错题列表分页查询代码逻辑复杂。选中代码片段,右键选择 CodeBuddy - 解释代码,快速看懂逻辑,也可以让它生成代码注释。对历史代码维护非常友好。 ### 场景 2:Bug 快速定位修复 在开发错题本模块时,遇到一个棘手 bug:切换题目时,页面数据不刷新。我直接框选全部 js 代码,发送指令:`帮我查找代码bug,为什么切换题目,页面数据不会更新,给出修复后的完整代码`。CodeBuddy 快速定位是 setData 调用时机问题,给出修复方案,节省大量调试时间。 ### 场景 3:生成工具函数 项目需要很多通用工具:时间格式化、题目数据处理、答案校验函数。直接一句话生成工具函数,复制到 utils.js 中,不用手动手写。 ## 五、免费使用 CodeBuddy 的心得与省积分技巧 在开发 AI 课课通整个周期,我主要依靠 CodeBuddy 免费版每月 500 积分来做开发,这里分享我的省钱省积分实战经验: 1. 简单代码、标签、样式,依靠**行间自动代码补全**,完全不扣积分,写页面首选; 1. 复杂页面才使用 Craft,不要频繁反复生成完整项目,Craft 消耗积分最高; 1. 提问精简,一次性把需求、上下文、代码全部粘贴,减少多次对话消耗 token; 1. 模型选择:简单需求优先轻量模型,复杂业务逻辑再切换高级模型; 1. 积分不足时,可以通过腾讯云开发者社区发布实战文章,获取额外 CodeBuddy 积分奖励。 ## 六、总结与感受 AI 课课通这个教育小程序,从需求原型到页面开发、联调 bug,CodeBuddy 作为独立开发者的搭档,把大量重复、机械编码工作接管。以前开发一套小程序页面,从写模板、写样式、写 js 交互,需要半天,现在借助 Craft + 代码补全,几十分钟就能拿到可用页面骨架,开发者重心从敲代码转移到产品逻辑、业务设计上。 CodeBuddy 非常适合个人独立开发者、小程序创业者。免费额度足够支撑日常迭代,用好插件 + Craft 能力,单人也可以高效完成小程序项目开发。后续我会继续迭代 AI 课课通,继续用 CodeBuddy 开发更多 AI 答题、学习数据分析相关模块。

优秀的个人博客,低调大师

从零开始编写一个类nginx工具, 配置数据的热更新原理及实现

wmproxy wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来, 感兴趣的可以一起造个轮子法 项目地址 gite: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 配置数据 数据通常配置在配置文件中,如果需要变更配置,我们通常将配置文件进行更新,并通知程序重新加载配置以便生效。 nginx的变更方式 在nginx中,我们通常用 nginx -s reload 进行数据的安全无缝的重载。在nginx中,是多进程的模式,也就是在nginx -s reload信号发出后master进程通知之前的work进程停止接收新的流,也就是accpet暂停,但是会服务完当前的数据请求,并同时会启用新的work进程来接受新的请求 缺点:nginx只能整体的配置做全部重置,且无法查看当前的配置(除非看配置文件,配置可能被重新修改过和内存中的值可能不匹配) 当前选取的方式 当前选择的是用HTTP请求的方式,也就是对本地的端口进行监听(http://127.0.0.1:8837),对本地端口监听也不会造成对外暴露端口带来的安全问题,这样子可以高度的自定义。具有比较高的活跃性,也可以实时查询内存中的数据。 例如访问: http://127.0.0.1:8837/reload即可通知目标进程重载当前的配置 http://127.0.0.1:8837/now即可以知道当前的所有的配置列表 http://127.0.0.1:8837/stop即可以关闭当前的进程,停止服务,类似于nginx中的nginx -s stop。 http://127.0.0.1:8837/adapt加载当前配置,看是否错误,但是不进行应用。 等功能。 功能实现的原理 单进程 单进程模式的缺点:如果存在内存泄漏之类的情况,无论如何重载进程都无法将内存恢复,会始终保持较高的内存值直到最终不可用的阶段。如果发生未正确处理的异常,可能会使该进程崩溃的风险,处于无服务状态。 单进程模式的优点:在当前进程存储的一些有利于加速服务的将会很好的被保留下来(如健康检查的数据),异步进程里正在处理的数据等。无需进行进程间通讯,配合tokio的异步处理可以将单进程的优势完美发挥出来。 端口复用 无论哪种模式,都需要处理数据重载时,绑定对象的转移TcpListener或者重新绑定TcpListener,在Rust中转移绑定对象相对来说较麻烦后续如果拓展成多进程模式也无法进行转移,所以不考虑用转移所有权的问题。那么此时我们的解决方法就是set_reuse_address及set_reuse_port,不同平台该方法上有不同的表现,我们用的是socket2的封装,用该方法的注意事项: 在windows平台上,不存在set_reuse_port方法,仅调用set_reuse_address即可实现一个地址多次绑定 在linux上,不同的版本上,有些只需调用set_reuse_address即可端口复用,有些需要同时调用set_reuse_port 在macos上,需要调用set_reuse_address和set_reuse_port函数才可实现端口复用 所以这里涉及一个分平台的编码,我们在此使用的是,这和C/C++中的#ifdef WINDOWS类似,但是只能在函数级的做调整,所以此处额外在封装了两个函数来做调用。 /// 非windows平台 #[cfg(not(target_os = "windows"))] fn set_reuse_port(socket: &Socket, reuse: bool) -> io::Result<()> { socket.set_reuse_port(true)?; Ok(()) } /// windows平台,空实现 #[cfg(target_os = "windows")] fn set_reuse_port(_socket: &Socket, _sreuse: bool) -> io::Result<()> { Ok(()) } 然后将原来的TcpListener::bind(addr)函数改成Helper::bind即可无缝切换到支持端口复用的功能,针对代理端及反向代理端: /// 可端口复用的绑定方式,该端口可能被多个进程同时使用 pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { let socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; socket.set_nonblocking(true)?; let _ = socket.set_only_v6(false); socket.set_reuse_address(true)?; Self::set_reuse_port(&socket, true)?; socket.bind(&addr.into())?; match socket.listen(128) { Ok(_) => { let listener: std::net::TcpListener = socket.into(); return TcpListener::from_std(listener); } Err(e) => { log::info!("绑定端口地址失败,原因: {:?}", addr); last_err = Some(e); } } } Err(last_err.unwrap_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, "could not resolve to any address", ) })) } 测试功能 测试配置加载reload,一开始我们绑定81的端口 进程启动后改为绑定82的端口,然后调用reload(curl.exe http://127.0.0.1:8837/reload) 此时,再调用stop(curl.exe http://127.0.0.1:8837/stop),正确的预期应该显示关闭,且82端口不可再访问 符合功能预期,初步测试完毕 相关源码实现 以下是启动及发送重载配置的流程示意图 以下是中控的定义,消息的通知主要通过Sender/Receiver来进行数据的通知。 /// 控制端,可以对配置进行热更新 pub struct ControlServer { /// 控制端当前的配置文件,如果部分修改将直接修改数据进行重启 option: ConfigOption, /// 通知服务进行关闭的Sender,服务相关如果收到该消息则停止Accept server_sender_close: Option<Sender<()>>, /// 通知中心服务的Sender,每个服务拥有一个该Sender,可反向通知中控关闭 control_sender_close: Sender<()>, /// 通知中心服务的Receiver,收到一次则将当前的引用计数-1,如果为0则表示需要关闭服务器 control_receiver_close: Option<Receiver<()>>, /// 服务的引用计数 count: i32, } 启动控制终端,接收HTTP的指令和关闭的指令,此时control已经变成了Arc<Mutex<ControlServer>>,方便在各各线程间传播,同步修改数据。 pub async fn start_control(control: Arc<Mutex<ControlServer>>) -> ProxyResult<()> { let listener = { let value = &control.lock().await.option; TcpListener::bind(format!("127.0.0.1:{}", value.control)).await? }; loop { let mut receiver = { let value = &mut control.lock().await; value.control_receiver_close.take() }; tokio::select! { Ok((conn, addr)) = listener.accept() => { let cc = control.clone(); tokio::spawn(async move { let mut server = Server::new_data(conn, Some(addr), cc); if let Err(e) = server.incoming(Self::operate).await { log::info!("反向代理:处理信息时发生错误:{:?}", e); } }); let value = &mut control.lock().await; value.control_receiver_close = receiver; } _ = Self::receiver_await(&mut receiver) => { let value = &mut control.lock().await; value.count -= 1; log::info!("反向代理:控制端收到关闭信号,当前:{}", value.count); if value.count <= 0 { break; } value.control_receiver_close = receiver; } } } Ok(()) } 处理相关消息: if req.path() == "/reload" { // 将重新启动服务器 let _ = value.do_restart_serve().await; return Ok(Response::text() .body("重新加载配置成功") .unwrap() .into_type()); } if req.path() == "/stop" { // 通知控制端关闭,控制端阻塞主线程,如果控制端退出后进程退出 if let Some(sender) = &value.server_sender_close { let _ = sender.send(()).await; } return Ok(Response::text() .body("关闭进程成功") .unwrap() .into_type()); } 以下是主要的启动代码: async fn inner_start_server(&mut self, option: ConfigOption) -> ProxyResult<()> { let sender = self.control_sender_close.clone(); let (sender_no_listen, receiver_no_listen) = channel::<()>(1); let sender_close = self.server_sender_close.take(); // 每次启动的时候将让控制计数+1 self.count += 1; tokio::spawn(async move { let mut proxy = Proxy::new(option); // 将上一个进程的关闭权限交由下一个服务,只有等下一个服务准备完毕的时候才能关闭上一个服务 if let Err(e) = proxy.start_serve(receiver_no_listen, sender_close).await { log::info!("处理失败服务进程失败: {:?}", e); } // 每次退出的时候将让控制计数-1,减到0则退出 let _ = sender.send(()).await; }); self.server_sender_close = Some(sender_no_listen); Ok(()) } 结语 此时以不同于nginx的另一种配置的加载已经开发完毕,配置的热加载可以让您更从容的保护好您的系统。 点击 <font color=green>[关注]</font>,<font color=green>[在看]</font>,<font color=green>[点赞]</font> 是对作者最大的支持

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册