• [问题求助] 并发会话数已达上限
    您好!我使用VSCode工具的云道码插件,阅读本地文件后就会提示这些信息{"error_code":"TM.00001041","error_msg":"并发会话数已达上限(3个),请关闭部分会话后重试。"},新开会话也没用。
  • [问题求助] 部分.cs文件无法打开,请修复问题
    部分.cs文件无法打开,请修复问题
  • [交流吐槽] 怎么GLM5.2模型还是200k不是1m上下文?
    怎么时候能变成1m呢?还有准备上k3还是dsv4pro呢
  • HarmonyOS PC端的CodeArts IDE链接数据库报错 command 'huaweicloud.createConnection' not found怎么解决
    HarmonyOS PC端的CodeArts IDE链接数据库报错 command 'huaweicloud.createConnection' not found怎么解决   
  • [问题求助] 一直没敢更新,今天更新后,思考变慢了,一看思考内容全是乱码,早知道不更新了
    一直没敢更新,今天更新后,思考变慢了,点开详情一看,输出的内容全是乱码,早知道不更新了,现在工具完全废了的状态
  • [交流吐槽] 华为云码道(CodeArts)今晚更新什么模型?GLM 5.2还是KIMI K3?
     华为云码道(CodeArts)今晚更新什么模型?GLM 5.2还是KIMI  K3?
  • [问题求助] 码道今天更新吗
    码道今天会更新吗,大概什么时候会更新,会上新模型吗
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的ForumAdmin:论坛管理系统
    基于华为云码道(CodeArts)代码智能体的ForumAdmin:论坛管理系统一、项目简介本次实战我使用华为云码道(CodeArts)代码智能体完成了 ForumAdmin 论坛管理系统。项目围绕"管理员、版主、会员"三种角色展开,实现了登录、发帖、跟帖、删帖、置顶等论坛基础功能,同时实现了DFA敏感词过滤算法、管理员禁言与用户拉黑双层机制、BCrypt密码加密存储,以及Discourse风格的现代论坛UI,形成了功能完备、权限清晰、内容安全的论坛管理系统。代码仓库:ForumAdmin(GitCode)前端:Vue 3 + Vite + Element Plus + Pinia + Vue Router + Axios后端:Java 17 + Spring Boot 3 + MyBatis-Plus + Sa-Token + BCrypt + Druid数据库:MySQL 9.4ForumAdmin 首页二、原始任务与完成情况原题为:论坛管理。实现论坛的版主管理、版块管理、内容管理。需要登陆进入论坛,可以发帖、跟帖和删帖以及置顶等功能。同时能够对敏感词汇进行过滤,拉黑某些会员。我将原题拆成了可验收的功能项,并为每项建立"页面操作 + 后端权限"的证据闭环:原题要求实现方式对应证据登录进入论坛Sa-Token 会话管理、BCrypt 密码加密、注册、退出登录页、注册页版主管理ADMIN 分配版主;MODERATOR 可进入后台管理版块管理页、角色标签显示版块管理创建、编辑、删除、排序、版主绑定版块管理页内容管理帖子/回复分页管理、置顶、删除帖子列表、帖子详情页发帖登录会员选择版块并发布,发布前完成禁言校验和敏感词过滤发帖弹窗、发帖接口跟帖帖子详情页回复,禁言用户和被拉黑用户不可回复帖子详情页、回复区域删帖作者或管理者可删除;逻辑删除删除按钮、删除接口置顶ADMIN 或 MODERATOR 可置顶/取消置顶,置顶优先排序置顶按钮、帖子列表排序敏感词过滤DFA 算法 O(n) 时间复杂度,词库动态重载敏感词管理页、发帖过滤效果拉黑会员管理员禁言(全站) + 用户拉黑(个人);发帖和回复前后端拦截黑名单页、禁言操作、拉黑按钮三、码道代码智能体开发实录我全程使用华为云码道(CodeArts)代码智能体进行开发,从项目初始化到最终UI改造,智能体深度参与了每个阶段。以下是按时间顺序的开发实录:3.1 项目创建与任务理解在码道代码智能体中创建项目后,我将原始任务描述提交给智能体:"实现论坛的版主管理、版块管理、内容管理。需要登陆进入论坛,可以发帖、跟帖和删帖以及置顶等功能。同时能够对敏感词汇进行过滤,拉黑某些会员。"智能体准确理解了需求,并主动拆解为以下模块:用户认证与权限管理(登录/注册/角色控制)版块管理(CRUD + 版主绑定)帖子与回复(发帖/跟帖/删帖/置顶)敏感词过滤(DFA算法)拉黑会员(用户屏蔽机制)3.2 后端项目搭建智能体一步完成了 Spring Boot 3 后端项目初始化,包括:引入 spring-boot-starter-web、mybatis-plus-spring-boot3-starter、sa-token-spring-boot3-starter、druid-spring-boot-3-starter、spring-security-crypto 等核心依赖配置 application.yml(数据源、MyBatis-Plus逻辑删除、Sa-Token会话参数)创建 Result 统一响应封装和 GlobalExceptionHandler 全局异常处理设计6张数据库表(user / section / post / reply / sensitive_word / user_block),编写 init.sql3.3 前端项目搭建智能体使用 Vite 脚手架创建 Vue 3 前端项目,集成:Element Plus 组件库及图标库Pinia 状态管理(用户token和userInfo持久化)Axios 请求封装(baseURL代理、token拦截器、401自动跳转)Vue Router 路由配置(含登录守卫)3.4 核心功能实现智能体按模块逐步生成完整CRUD代码:5组 Entity + Mapper + Service + Controller:User、Section、Post、Reply、SensitiveWordSa-Token RBAC权限:实现 StpInterface 接口,根据用户uid动态返回角色列表BCrypt密码加密:注册时加密存储,登录时matches验证;DataInitializer启动自动检测并转换明文密码DFA敏感词过滤算法:智能体独立实现了确定有限自动机,包括字典构建、匹配检测、文本替换三个核心方法拉黑与禁言双层机制:新增 user_block 表和 UserBlockController,帖子列表SQL动态过滤被拉黑用户,回复前校验帖子作者是否拉黑了回复人3.5 Bug修复与优化开发过程中遇到多个问题,智能体均快速定位并修复:问题原因智能体解决方案版块名称乱码PowerShell管道传输SQL编码丢失移除SQL初始数据,改用Java DataInitializer自动初始化,确保UTF-8密码明文存储初始实现未加密引入BCryptPasswordEncoder,DataInitializer自动检测并转换后台管理按钮不可见仅ADMIN角色可见扩展为ADMIN和MODERATOR均可进入帖子详情API返回nullgetById不关联查询新增selectDetailById关联查询用户名/版块名/回复数帖子创建标题/内容为空前后端均未校验前端表单验证 + 后端参数非空校验3.6 UI改造智能体根据我确认的Discourse风格方案,完成了全部页面改造:创建公共 AppHeader 组件(白底头部 + Logo + 角色标签 + 管理入口)首页:横向分类标签 + 帖子行(头像+标题+分类标签+回复数)+ 浮动发帖按钮帖子详情:时间线流式回复(圆点+连线)+ 底部固定编辑器登录页:浅灰背景 + 圆角卡片后台管理:白底侧边栏 + 图标菜单配色统一:主背景#fff、链接蓝#0088cc、分类标签彩色3.7 开发效率总结通过码道代码智能体,整个项目从零到功能完备仅用时约2天。智能体在以下方面显著提升了效率:代码生成:后端CRUD、前端页面、API接口等重复性代码一键生成算法实现:DFA敏感词过滤等非平凡算法智能体独立完成Bug修复:编码乱码、密码明文等问题智能体快速定位根因并修复架构决策:技术选型(Sa-Token vs Spring Security)、权限模型设计等智能体给出了合理建议一致性保障:公共组件、统一响应封装、路由守卫等确保了代码风格一致四、系统架构与业务闭环整体架构保持前后端分离,开发模式下前端Vite Dev Server代理后端API:会员 / 版主 / 管理员 │ ▼ Vue 3 + Vite (5173) │ Axios → /api 代理 ▼ Sa-Token 会话认证 │ ├── 用户服务 ── BCrypt 密码验证 ├── 论坛业务服务 ── MyBatis-Plus ── MySQL 9.4 ├── RBAC 权限 ── ADMIN / MODERATOR / MEMBER ├── 敏感词 DFA ── 过滤/替换 └── 拉黑/禁言 ── 帖子过滤 + 回复拦截发帖和回复走统一治理链路:提交内容 → 校验是否被禁言(user.status = 0) → 校验是否被帖子作者拉黑 → DFA 敏感词过滤(替换为 ***) → 保存并返回这种设计确保了:禁言用户无法发帖和回帖;被拉黑用户的帖子不会出现在列表中;被帖子作者拉黑的用户无法回复该帖子;敏感词在保存前即被过滤替换。五、逐项功能实现1. 登录进入论坛系统支持注册、登录和退出。登录成功后前端携带 Sa-Token 的 UUID Token 访问需要授权的接口;密码使用 BCrypt 加密存储。登录页面注册页面登录接口实现:@PostMapping("/login") public Result<Map<String, Object>> login(@RequestBody Map<String, String> params) { User user = userService.login(params.get("username"), params.get("password")); Map<String, Object> data = new HashMap<>(); data.put("token", StpUtil.getTokenValue()); data.put("user", user); return Result.ok(data); } Sa-Token 权限配置,根据用户角色动态返回权限列表:@Component public class SaTokenConfig implements StpInterface { private final UserMapper userMapper; @Override public List<String> getPermissionList(Object loginId, String loginType) { return new ArrayList<>(); } @Override public List<String> getRoleList(Object loginId, String loginType) { List<String> roles = new ArrayList<>(); User user = userMapper.selectById(Long.valueOf(loginId.toString())); if (user != null) { roles.add(user.getRole()); } return roles; } } 2. 版主管理管理员可以在版块管理页为每个版块分配版主(通过 moderatorId 字段)。系统实现了三级角色权限控制:角色前台后台管理说明ADMIN发帖/回帖/删帖/置顶版块管理+用户管理(禁言)+敏感词管理超级管理员MODERATOR发帖/回帖/删帖/置顶可进入后台版主MEMBER发帖/回帖不可进入普通会员前端通过角色标签清晰展示当前用户身份:3. 版块管理系统实现了版块的创建、编辑、删除、排序和版主配置。DataInitializer 在启动时自动检查并修复版块数据,确保中文编码正确:private static final String[][] DEFAULT_SECTIONS = { {"技术交流", "讨论技术相关话题"}, {"生活杂谈", "分享生活点滴"}, {"求助问答", "提出问题寻求帮助"} }; 版块管理页面4. 发帖与跟帖登录会员可以选择版块发布帖子,并在帖子详情页回复。发帖与回复都会先检查禁言状态和拉黑关系,再进行敏感词过滤。发帖接口实现(含校验与敏感词过滤):@PostMapping("/add") public Result<Void> add(@RequestBody Post post) { if (post.getTitle() == null || post.getTitle().trim().isEmpty()) { return Result.fail("标题不能为空"); } if (post.getContent() == null || post.getContent().trim().isEmpty()) { return Result.fail("内容不能为空"); } if (post.getSectionId() == null) { return Result.fail("请选择版块"); } Long userId = StpUtil.getLoginIdAsLong(); User user = userService.getById(userId); if (user.getStatus() == 0) { return Result.fail("您已被禁言,无法发帖"); } post.setUserId(userId); post.setTitle(sensitiveWordService.filter(post.getTitle())); post.setContent(sensitiveWordService.filter(post.getContent())); post.setIsTop(0); postService.save(post); return Result.ok(); } 回复接口实现(含拉黑校验):@PostMapping("/add") public Result<Void> add(@RequestBody Reply reply) { Long userId = StpUtil.getLoginIdAsLong(); User user = userService.getById(userId); if (user.getStatus() == 0) { return Result.fail("您已被禁言,无法回复"); } Post post = postService.getById(reply.getPostId()); if (post != null && userBlockService.hasBlocked(post.getUserId(), userId)) { return Result.fail("帖子作者已拉黑您,无法回复"); } reply.setUserId(userId); reply.setContent(sensitiveWordService.filter(reply.getContent())); replyService.save(reply); return Result.ok(); } 帖子列表关联查询,一次SQL获取用户名、版块名和回复数:@Select("<script>" + "SELECT p.*, u.username, u.nickname, s.name AS section_name, " + "(SELECT COUNT(*) FROM reply r WHERE r.post_id = p.id AND r.is_deleted = 0) AS reply_count " + "FROM post p LEFT JOIN user u ON p.user_id = u.uid LEFT JOIN section s ON p.section_id = s.id " + "WHERE p.is_deleted = 0 " + "<if test='blockedIds != null and blockedIds.size() > 0'>" + "AND p.user_id NOT IN " + "<foreach collection='blockedIds' item='id' open='(' separator=',' close=')'>#{id}</foreach>" + "</if>" + " ORDER BY p.is_top DESC, p.create_time DESC" + "</script>") IPage<Post> selectPageAll(Page<Post> page, @Param("blockedIds") java.util.List<Long> blockedIds); 帖子详情页5. 删帖与置顶作者可以删除自己的帖子,管理员和版主可以执行管理删除。删除采用 MyBatis-Plus 逻辑删除(is_deleted 字段),不会物理清除数据。置顶操作更新 is_top 字段,帖子列表按置顶优先、时间倒序排列。置顶接口:@PutMapping("/top/{id}") public Result<Void> top(@PathVariable Long id, @RequestParam Integer isTop) { postService.setTop(id, isTop); return Result.ok(); } 逻辑删除配置:mybatis-plus: global-config: db-config: logic-delete-field: isDeleted logic-delete-value: 1 logic-not-delete-value: 0 6. 敏感词过滤敏感词管理支持新增、删除和动态重载。过滤算法采用 DFA(确定有限自动机),时间复杂度为 O(n),其中 n 为待过滤文本长度,与敏感词数量无关。DFA 核心实现:@Component public class SensitiveWordFilter { private final Map<Character, Object> dictMap = new HashMap<>(); private static final String REPLACEMENT = "***"; public void loadWords(List<SensitiveWord> words) { dictMap.clear(); for (SensitiveWord sw : words) { String word = sw.getWord().trim(); if (word.isEmpty()) continue; Map<Character, Object> current = dictMap; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); Object next = current.get(c); if (next == null) { Map<Character, Object> newNode = new HashMap<>(); current.put(c, newNode); current = newNode; } else { current = (Map<Character, Object>) next; } } current.put('\0', null); } } public String filter(String text) { if (text == null || text.isEmpty()) { return text; } StringBuilder result = new StringBuilder(text); for (int i = 0; i < text.length(); i++) { int length = checkSensitiveWord(text, i); if (length > 0) { for (int j = i; j < i + length; j++) { result.setCharAt(j, REPLACEMENT.charAt(0)); } i += length - 1; } } return result.toString(); } @SuppressWarnings("unchecked") private int checkSensitiveWord(String text, int startIndex) { Map<Character, Object> current = dictMap; int length = 0; for (int i = startIndex; i < text.length(); i++) { char c = text.charAt(i); Object next = current.get(c); if (next == null) { break; } length++; current = (Map<Character, Object>) next; if (current.containsKey('\0')) { return length; } } return 0; } } 词库动态重载接口:@GetMapping("/refresh") public Result<Void> refresh() { sensitiveWordService.refreshDict(); return Result.ok(); } 敏感词管理页面7. 拉黑会员系统实现了双层机制:管理员禁言:全站级别,修改 user.status = 0,禁言用户可登录但无法发帖和回帖用户拉黑:个人级别,通过 user_block 表记录,拉黑后看不到对方帖子,对方无法回复自己的帖子操作执行者范围效果禁言管理员全站可登录,但无法发帖、回帖拉黑任何用户个人我看不到他的帖子,他不能回复我的帖子拉黑接口实现:@RestController @RequestMapping("/api/block") @RequiredArgsConstructor public class UserBlockController { private final UserBlockService userBlockService; @PostMapping("/add/{blockedUserId}") public Result<Void> block(@PathVariable Long blockedUserId) { Long userId = StpUtil.getLoginIdAsLong(); userBlockService.block(userId, blockedUserId); return Result.ok(); } @DeleteMapping("/remove/{blockedUserId}") public Result<Void> unblock(@PathVariable Long blockedUserId) { Long userId = StpUtil.getLoginIdAsLong(); userBlockService.unblock(userId, blockedUserId); return Result.ok(); } @GetMapping("/list") public Result<List<UserBlock>> myBlockList() { Long userId = StpUtil.getLoginIdAsLong(); return Result.ok(userBlockService.myBlockList(userId)); } } 帖子列表查询时动态过滤被拉黑用户的帖子:@GetMapping("/list") public Result<IPage<Post>> list(@RequestParam(required = false) Long sectionId, @RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size) { List<Long> blockedIds = Collections.emptyList(); if (StpUtil.isLogin()) { blockedIds = userBlockService.getBlockedUserIds(StpUtil.getLoginIdAsLong()); } if (sectionId != null) { return Result.ok(postService.pageBySectionId(sectionId, page, size, blockedIds)); } return Result.ok(postService.pageAll(page, size, blockedIds)); } 黑名单管理页面8. Discourse 风格 UI系统采用 Discourse 风格的现代论坛 UI 设计,主要特点包括:白底头部:统一的 AppHeader 组件,包含 Logo、用户信息、角色标签、管理入口横向分类标签:版块以彩色标签形式横向排列,点击切换过滤帖子列表:每行显示头像、标题、分类标签、回复数,替代传统表格时间线流式回复:帖子详情页回复以圆点+连线的时间线形式展示底部固定编辑器:回复输入框固定在页面底部,随时可输入浮动发帖按钮:右下角圆形按钮,点击弹出发帖弹窗公共头部组件核心代码:<template> <header class="app-header"> <div class="header-inner"> <div class="header-left" @click="$router.push('/')"> <span class="logo">Forum</span> </div> <div class="header-right"> <span class="user-name">{{ userStore.userInfo?.nickname || '用户' }}</span> <el-tag v-if="userStore.userInfo?.role === 'ADMIN'" type="danger" size="small" effect="dark">管理员</el-tag> <el-tag v-else-if="userStore.userInfo?.role === 'MODERATOR'" color="#e6a23c" size="small" effect="dark" style="color:#fff;border:none">版主</el-tag> <el-tag v-else type="info" size="small" effect="plain">会员</el-tag> <el-button v-if="userStore.userInfo?.role === 'ADMIN' || userStore.userInfo?.role === 'MODERATOR'" text @click="$router.push('/admin')"> <el-icon><Setting /></el-icon> 管理 </el-button> <el-button text @click="$router.push('/blocklist')"> <el-icon><UserFilled /></el-icon> 黑名单 </el-button> <el-button text type="danger" @click="handleLogout"> <el-icon><SwitchButton /></el-icon> 退出 </el-button> </div> </div> </header> </template> 首页帖子列表核心代码:<div v-for="p in posts" :key="p.id" class="post-row" @click="$router.push(`/post/${p.id}`)"> <div class="post-avatar"> <el-avatar :size="36" :style="{ background: sectionColor(p.sectionId) }"> {{ (p.nickname || p.username || '?')[0] }} </el-avatar> </div> <div class="post-body"> <div class="post-title-row"> <el-tag v-if="p.isTop === 1" type="danger" size="small" effect="dark" class="top-tag">置顶</el-tag> <span class="post-title">{{ p.title }}</span> <span class="post-cat" :style="{ background: sectionColor(p.sectionId) + '18', color: sectionColor(p.sectionId) }">{{ p.sectionName }}</span> </div> <div class="post-meta"> <span class="meta-author">{{ p.nickname || p.username }}</span> <span class="meta-dot">·</span> <span class="meta-time">{{ p.createTime }}</span> </div> </div> <div class="post-stats"> <el-icon><ChatDotRound /></el-icon> <span>{{ p.replyCount || 0 }}</span> </div> </div> 首页全貌帖子详情时间线回复六、创新与易用性DFA 敏感词过滤:采用确定有限自动机算法,时间复杂度 O(n)(n为文本长度),与敏感词数量无关;词库支持动态热重载,无需重启服务。拉黑/禁言双层机制:管理员禁言为全站级别(修改 user.status),用户拉黑为个人级别(user_block 表),两者逻辑清晰、互不干扰,分别作用于不同场景。BCrypt 密码加密:使用 BCryptPasswordEncoder 加密存储密码,BCrypt 自带盐值,每次加密结果不同,抗彩虹表攻击。DataInitializer 启动时自动检测并转换明文密码。Discourse 风格 UI:白底头部、横向分类标签、时间线流式回复、底部固定编辑器、浮动发帖按钮,提供现代论坛体验。前后端双重校验:前端表单提交前验证必填项,后端接口同样校验参数非空,避免绕过前端直接提交空数据。数据自动修复:DataInitializer 启动时自动检测并修复中文乱码、明文密码、缺失数据等问题,确保系统开箱即用。七、码道新能力与华为云技术使用使用华为云码道(CodeArts)代码智能体完成全流程开发,从项目搭建、代码生成到功能实现和Bug修复;通过自然语言 Prompt 指导智能体完成数据库设计、CRUD 接口生成、敏感词算法实现、权限配置和 UI 改造;使用浏览器控制能力对 ADMIN、MODERATOR、MEMBER 等真实页面进行验收和截图,避免以 mock 页面冒充后端功能;项目级规则约束技术栈(SpringBoot3 + Vue3)、权限模型(RBAC 三级角色)和内容治理(DFA + 禁言 + 拉黑)。八、测试与验证结果项目完成了前端生产构建和后端编译验证:验证项结果后端编译mvn compile 通过前端生产构建npm run build 通过,所有组件正常打包浏览器真实验收多张页面证据,关键页面功能正常权限验证未登录跳转登录页,MEMBER 不可进入后台验证命令如下:# 后端编译 cd backend mvn compile # 前端生产构建 cd ../frontend npm run build九、本地运行本地开发# 1. 初始化数据库 mysql -u root -p < sql/init.sql # 2. 启动后端 cd backend mvn spring-boot:run # 3. 另开终端启动前端 cd frontend npm install npm run dev访问 http://localhost:5173,后端API端口为 8080。一键启动项目提供了 start.bat 一键启动脚本,双击即可同时启动后端和前端。默认账号账号密码角色adminadmin123ADMINmoderatormod123MODERATORmembermem123MEMBER十、逐项对应评分项项目成果与证据创新易用DFA敏感词O(n)过滤、拉黑/禁言双层机制、BCrypt加密、Discourse风格UI、前后端双重校验、数据自动修复功能完备原题10个功能点全部闭环;登录/注册/发帖/回帖/删帖/置顶/敏感词/禁言/拉黑/版块管理全部实现技术能力码道全流程开发、Sa-Token认证+RBAC、DFA算法、MyBatis-Plus逻辑删除、前后端分离架构文档完整性开发日志、数据库设计、API接口、本地运行说明、默认账号、一键启动脚本完整十一、项目成果总结这次实战让我从"实现一个能发帖的页面",进一步走到了"构建一个权限正确、内容安全、UI现代、开箱即用的论坛系统"。ForumAdmin 已在本地完成核心功能、生产构建验证和真实页面验收;项目同时保留了开发日志、数据库设计、API接口文档和运行说明,方便评审复现。核心成果:6张数据库表:user / section / post / reply / sensitive_word / user_block,支持逻辑删除和自动时间填充DFA敏感词过滤:O(n)时间复杂度,动态词库热重载拉黑/禁言双层机制:全站禁言与个人屏蔽分离,逻辑清晰BCrypt密码加密:启动自动检测并转换明文密码Discourse风格UI:白底头部、横向分类标签、时间线回复、浮动发帖按钮一键启动:start.bat 双击即可运行
  • [高校训练营] 智车云——基于华为云码道的汽车经销商智能经营平台
    智车云:华为云码道辅助构建汽车经销商智能经营平台案例定位:面向汽车经销商集团的 DMS、CRM、F&I 与 BI 一体化智能经营平台技术栈:Java 17、Spring Boot 3、Vue 3、TypeScript、PostgreSQL、Redis、RabbitMQ、MinIO、Docker Compose开发方式:使用华为云码道(CodeArts)代码智能体辅助项目理解、任务拆解、跨文件开发、测试补齐、接口联调与容器化排障案例版本:V1.0编制日期:2026 年 7 月一、概述1.1 案例介绍汽车经销商的经营链路横跨车辆采购、库存周转、客户跟进、报价审批、订单履约、金融保险、收款结算和交付复盘。传统系统往往按部门分散建设,造成同一辆车、同一位客户和同一笔订单在多个系统之间重复录入,库存状态与利润口径不一致,关键经营风险只能依赖人工发现。本案例使用华为云码道(CodeArts)代码智能体,构建了“智车云”汽车经销商智能经营平台。系统以 VIN 为车辆唯一主线、以 客户旅程为成交主线、以 单车利润为经营主线,覆盖经营驾驶舱、车辆库存、客户线索、报价审批、销售订单、金融结算、交付中心、经营分析和 AI 助手等模块。智车云并非只把线下表单搬到网页,而是将关键业务约束落实为系统可执行、可拒绝、可追溯的规则:车辆和订单状态由显式状态机控制,禁止非法越级;低于保护价或综合利润为负的报价必须进入审批;订单和收款使用幂等键防止重复提交;交付前自动生成 14 项检查清单,必要项未完成不能交车;租户、门店、角色和数据范围共同控制数据可见性;关键操作写入状态日志和审计记录;经营驾驶舱与 AI 助手基于真实业务数据生成预警和建议。平台中的“AI 助手”目前采用可解释的规则评分和自然语言查询能力,负责库存、线索和销售数据的查询与经营建议;华为云码道则用于研发阶段的代码理解、生成、测试和调试,两者职责不同。案例亮点本案例不是“生成几个页面”的简单展示,而是以汽车销售真实业务闭环为验收主线:用 VIN 串联车辆全生命周期,用 状态机和幂等机制守住交易一致性,用 利润防火墙和 14 项交付清单固化经营规则,再由 经营驾驶舱与 AI 助手把交易数据转化为可执行建议。华为云码道贯穿需求拆解、跨文件编码、测试补齐、联调排障和容器化验收全过程。1.2 业务问题与建设目标原始问题直接经营后果建设目标验收口径车辆、客户和订单分散记录重复录入、车辆错锁或重复销售,责任链难追溯以 VIN、客户与订单建立统一交易主线同一车辆只能进入一条有效成交链路,状态变化有日志优惠与利润依赖个人经验低价成交后才发现亏损,审批依据不统一将保护价、成本、佣金和优惠固化为利润防火墙低于保护价或综合利润为负时自动标记并阻止无原因提交跟进、收款和交付依赖人工提醒客户流失、重复收款、交付漏项,容易产生投诉使用任务、幂等键和交付清单建立履约门禁重复请求不重复入账,必要检查项未完成不能交车集团与门店数据边界模糊跨门店越权查看,经营口径难统一以租户、门店、角色和数据范围控制可见性普通门店账号只能访问授权范围,关键操作可审计经营数据缺少统一视图库存积压、线索转化和交付风险发现滞后建设经营驾驶舱和分析模块看板指标、图表与业务明细保持一致1.3 适用对象企业开发者:需要构建汽车经销商 DMS、CRM、进销存或多门店经营系统的研发人员;个人开发者:希望学习 Spring Boot、Vue 3、Docker Compose 全栈工程实践的开发者;高校学生:需要完成软件工程、数据库、企业应用开发或智能编码课程设计的学生;架构与产品人员:关注状态一致性、利润管控、多租户、可审计和演示数据设计的人员。1.4 案例时间阅读本文并在本地完成核心功能复现,建议预留约 150 分钟:阶段建议时间环境准备与代码获取20 分钟架构与业务规则理解20 分钟核心功能构建与调试65 分钟容器化部署25 分钟业务验收与复盘20 分钟首次拉取 Docker 镜像或安装依赖时,耗时会受网络环境影响。1.5 案例流程准备华为云码道代码智能体、Docker Desktop 和项目源码;让码道读取项目目录、依赖、领域对象和部署配置,建立共享上下文;按“实体—仓储—服务—接口—前端—测试”的顺序完成业务切片;运行编译、单元测试和接口联调,将错误日志与相关文件交给码道分析;使用 Docker Compose 启动前端、后端及四个基础设施服务;通过经营驾驶舱、利润审批、订单状态、交付清单和 AI 查询完成验收;整理案例文档、演示视频与代码仓库链接并提交。图 1 华为云码道辅助开发闭环如图 1 所示,码道不是一次性生成代码后即结束,而是参与“理解—拆解—实现—验证—修正—交付”的持续闭环。每个任务切片都要求同时给出代码、测试或可复核运行结果;涉及金额、权限、状态迁移和数据删除等高风险决策时,由开发者保留最终确认权。1.6 资源总览资源名称建议规格费用说明华为云码道(CodeArts)代码智能体体验版、基础版或专业版,按实际账号开通以控制台当前套餐和计费规则为准本地开发环境JDK 17、Node.js 20、Docker Desktop、4 核 8 GB 以上本地资源,无额外云费用PostgreSQL、Redis、RabbitMQ、MinIO通过 Docker Compose 启动使用本地容器,无额外云费用可选云开发主机4 vCPU、8 GB 内存、40 GB 系统盘如使用云资源,体验完成后及时释放本案例默认采用本地 Docker Compose,可在不购买数据库、缓存、消息队列和对象存储云服务的情况下完成体验。生产环境应替换演示账号和默认口令,并使用密钥管理服务保存敏感配置。1.7 演示与源码地址演示视频:请替换为审核通过后的公开视频链接源码仓库:请替换为 GitHub、Gitee、GitCode 或 CodeArts Repo 链接本地管理端:http://localhost本地演示账号:admin / 123456演示账号仅用于本地案例体验,请勿在生产环境继续使用该密码。二、环境和资源准备2.1 开通并登录华为云码道注册并登录华为云账号;进入华为开发者空间或华为云码道产品页面;按账号权限开通可用套餐;在华为云码道 IDE、VS Code/JetBrains 插件或码道 CLI 中登录;打开智车云项目根目录,使智能体能够读取 README、前后端源码、数据库迁移和 Docker 配置。涉及文件删除、外部命令执行、敏感信息或生产数据时,应保留人工确认,不开启不必要的自动批准权限。2.2 本地开发环境类别版本或规格用途JavaJDK 17、Maven 3.8+构建 Spring Boot 3.3.6 后端前端Node.js 20、npm构建 Vue 3 + TypeScript 管理端容器Docker Desktop、Docker Compose v2一键启动 6 个服务数据PostgreSQL 17、Redis 7业务持久化、会话和缓存中间件RabbitMQ 3、MinIO领域事件、对象存储可选客户端微信开发者工具运行微信小程序端2.3 获取代码并建立项目上下文git clone <your-repository-url> cd zhiheyun首次让码道读取项目时,不要立即要求其修改代码,可以先使用以下提示词:请先只分析、不修改代码: 1. 阅读 README、backend/pom.xml、frontend/package.json; 2. 阅读 application.yml、docker-compose.yml 和数据库迁移脚本; 3. 总结系统架构、业务域、关键状态机、金额计算和多租户边界; 4. 列出“车辆锁定—订单收款—交付完成”链路涉及的文件; 5. 给出风险清单和最小可验证任务拆解。建议把 README 作为第一层上下文,再按任务引用具体业务文件。一次修改应尽量同时提供领域实体、Repository、Service、Controller、前端 API 和测试文件,避免只根据单文件做出局部正确、全局不一致的实现。2.4 关键配置配置位置关键内容说明backend/src/main/resources/application.yml数据源、Redis、RabbitMQ、MinIO、Sa-Token本地直接运行默认连接 localhostdeploy/docker/docker-compose.yml6 个服务、端口、依赖和数据卷容器内通过服务名互相访问frontend/nginx.conf/api 反向代理将前端 API 请求转发到 backend:8080backend/src/main/resources/db/migrationV1~V6 迁移和演示数据Flyway 启动时按版本自动执行生产环境不得直接提交真实密码、访问密钥或 Token。敏感配置应使用环境变量、密钥管理服务或部署平台的 Secret 能力注入。三、构建智车云应用3.1 总体架构与设计思路智车云采用前后端分离和容器化部署架构:浏览器 / 管理端 │ ▼ Nginx + Vue 3 + TypeScript + Element Plus + ECharts │ REST / JSON ▼ Spring Boot 3 + Sa-Token + Spring Data JPA │ ├── PostgreSQL:交易数据、状态日志、审计数据 ├── Redis:登录会话与缓存 ├── RabbitMQ:领域事件与异步通知 └── MinIO:附件与影像对象存储Nginx 提供静态资源和 API 反向代理;Spring Boot 对外暴露 REST 接口,并通过领域服务承载业务规则;PostgreSQL 保存交易数据,Redis 支撑会话与缓存,RabbitMQ 用于非阻塞领域事件,MinIO 用于附件和影像存储。Flyway 使表结构、字典和演示数据随应用版本演进。图 2 智车云系统总体架构架构设计遵循“页面只表达交互、接口只负责协议、服务承载业务规则、数据库完成最终约束”的分层原则。这样既能让管理端、小程序等不同终端复用同一套规则,也能防止通过绕过前端校验直接修改车辆、订单或收款状态。3.1.1 业务域与模块边界业务域核心对象核心能力组织权限Tenant、Group、Store、Department、User、Role多租户、门店组织、RBAC、数据范围车型与库存Brand、Series、Model、Vehicle、TransferVIN 管理、在途入库、锁定调拨、库存预警客户与线索Customer、Lead、FollowUp、TestDrive销售漏斗、公海池、撞单防护、跟进计划报价与订单Quotation、PriceApproval、Order、OrderChange利润防火墙、审批、订单状态机、变更留痕金融与结算FinanceApplication、Policy、Payment、Invoice、Settlement金融、保险、收退款、发票、单车利润交付与分析DeliveryTask、DeliveryChecklist、DashboardData14 项交付门禁、经营驾驶舱、销售漏斗智能建议AiSuggestion线索评分、库存建议、下一最佳行动3.1.2 数据与状态一致性原则金额字段统一使用 PostgreSQL DECIMAL 与 Java BigDecimal;VIN、订单号、发票号和幂等键由数据库唯一约束或业务校验保护;车辆与订单分别使用显式状态机,终态不可逆;取消订单时释放已锁定车辆;关键操作在同一本地事务中更新主对象和状态日志;非阻塞领域事件用于后续通知和扩展处理;Flyway 同时管理表结构、字典和演示数据,避免环境之间发生结构漂移。3.2 核心功能与旗舰业务闭环3.2.1 功能完备性矩阵功能端状态演示价值登录认证与数据权限管理端已实现验证登录态、角色和数据范围经营驾驶舱管理端已实现展示 KPI、销售漏斗、库存结构和 AI 建议车辆库存管理端已实现展示 VIN、状态、库龄、成本、库位与预警客户线索管理端已实现展示等级、状态、跟进计划、公海流转与认领报价与利润审批管理端已实现验证保护价、综合利润和降价原因销售订单管理端已实现验证状态推进、车辆锁定和订单幂等金融与收款结算管理端已实现验证金融、保险、收款、发票和结算交付控制塔管理端已实现验证交付任务、检查清单和完成门禁经营分析管理端已实现展示销售漏斗和库存状态分布AI 助手管理端已实现使用自然语言查询经营数据和库存建议微信小程序壳客户端已实现基础页面承载看车、预约、订单和个人中心入口3.2.2 端到端旗舰闭环演示时选择一名高意向客户和一辆在库车辆作为贯穿对象:在客户线索中确认手机号撞单结果、当前负责人和下一次跟进时间;选择目标车辆生成报价,系统汇总采购成本、资金占用、附加收入和优惠;制造一次低价报价,验证未填写降价原因时无法提交;审批通过后创建订单并锁定 VIN;使用相同幂等键重复提交,确认系统不会创建第二笔订单;完成收款,验证相同幂等键不会重复入账;交付中心完成 14 项检查,必要项未完成时不能确认交付;订单完成后,收入、成本、毛利和销售漏斗同步进入经营驾驶舱。同一条业务主线同时验证利润、状态、幂等、权限、审计和看板一致性,比逐页介绍菜单更能体现系统完整度。图 3 从线索到经营复盘的端到端旗舰业务闭环图 3 将客户、报价、车辆、订单、收款、交付和经营分析串成一个可重复演示的故事。评审者不仅能看到“功能存在”,还可以观察同一 VIN 的状态如何推进、异常操作如何被拒绝、最终数据如何回流经营看板。3.3 项目结构与代码部署zhiheyun/ ├── backend/ │ └── src/main/ │ ├── java/.../domain # 领域对象 │ ├── java/.../repository # 数据访问 │ ├── java/.../service # 业务规则与事务 │ ├── java/.../state # 车辆、订单状态机 │ ├── java/.../controller # REST 接口 │ └── resources/db/migration ├── frontend/ │ └── src/ │ ├── api # 11 个 API 模块 │ ├── pages # 16 个管理端页面 │ ├── stores # Pinia 状态 │ └── router # 页面路由与鉴权守卫 ├── miniprogram/ # 微信小程序基础页面 └── deploy/ ├── docker/docker-compose.yml └── scripts/start.sh一键启动:# 方式一:使用根目录脚本 ./deploy/scripts/start.sh # 方式二:直接使用 Docker Compose cd deploy/docker docker compose up -d --build 查看容器状态与后端日志:docker compose ps docker compose logs --tail=200 backend健康检查:curl http://localhost:8080/api/actuator/health curl http://localhost:8080/api/v3/api-docs服务入口:服务地址说明管理端http://localhost默认管理员 admin / 123456后端 APIhttp://localhost:8080/api统一上下文路径Swagger UIhttp://localhost:8080/api/swagger-ui.html接口浏览与调试RabbitMQhttp://localhost:15672消息队列管理台MinIOhttp://localhost:9001对象存储管理台3.4 使用华为云码道辅助开发及调试3.4.1 项目理解与任务拆解首次进入项目时,不要求码道直接“生成整套系统”,而是先建立共享上下文:业务目标、工程结构、依赖版本、数据模型、状态机和验收条件。你是本项目的结对开发者。请先只分析、不修改代码: 1. 读取 README、backend/pom.xml、frontend/package.json; 2. 识别业务域、关键状态机、金额计算和多租户边界; 3. 列出“车辆锁定—订单收款—交付完成”链路涉及的文件; 4. 给出风险清单和最小可验证任务拆解。使用原则:先让智能体解释现状,再批准修改;先完成一个可验证的业务切片,再扩展到相邻模块;金额、权限、状态、删除和敏感配置必须人工审查;智能体建议只有在编译、测试和业务验收通过后才视为完成。3.4.2 跨文件实现:利润防火墙报价模块涉及车型保护价、车辆采购成本、资金占用成本、附加收入、优惠、审批单和前端提示,不能只修改单一页面。请完善报价利润防火墙: - 所有金额使用 BigDecimal; - 计算成交总额、预估毛利和综合利润; - 低于车型保护价或综合利润为负时标记风险; - 提交审批前必须校验降价原因; - 补充正常报价、低于保护价、未填原因三个单元测试; - 不改变现有 REST 返回结构。码道根据实体、Repository、Service、Controller、前端 API、页面和测试文件的共同上下文生成跨文件修改建议。人工重点核验空值处理、金额正负号、补贴与置换抵扣方向、采购成本来源、舍入方式和审批状态。核心利润计算示例:BigDecimal grossProfit = total .subtract(purchaseCost) .subtract(fundOccupancyCost); BigDecimal comprehensiveProfit = grossProfit .add(accessoryProfit) .add(financeCommission) .add(insuranceCommission) .add(manufacturerRebate) .subtract(salesCommission); if (comprehensiveProfit.compareTo(BigDecimal.ZERO) < 0) { quotation.setBelowProfitLine(true); } 3.4.3 状态机与边界测试车辆与订单状态转换集中在专用组件中维护,Service 不通过任意字符串直接修改状态:private static final Map<String, Set<String>> TRANSITIONS = Map.of( "IN_STOCK", Set.of("RESERVED", "LOCKED"), "LOCKED", Set.of("CONTRACTED", "RESERVED", "IN_STOCK"), "CONTRACTED", Set.of("PENDING_DELIVERY", "LOCKED"), "PENDING_DELIVERY", Set.of("DELIVERED", "CONTRACTED"), "DELIVERED", Set.of() ); stateMachine.validateTransition(fromStatus, toStatus); 补充测试时使用的提示词:请阅读 OrderStateMachine 和业务枚举,以“任何终态不可逆、 任何草稿不可直接完成”为业务不变量,补充 JUnit 5 测试。 测试名称使用中文 DisplayName,不启动 Spring 容器。项目包含 5 个核心测试类、32 个业务单元测试:测试类用例数重点覆盖OrderStateMachineTest5合法流转、终态保护、禁止越级完成VehicleStateMachineTest6入库、锁定、释放、交付终态CustomerServiceTest6手机号撞单、公海移入/认领、跟进计数QuotationServiceTest6金额计算、保护价、审批前置条件VehicleServiceTest9VIN 唯一、成本合计、库龄预警、租户校验3.4.4 前后端接口联调联调时将浏览器 Network 中的请求 URL、状态码、响应体和后端异常栈一并提供给码道,并同时引用前端 API 封装、类型定义、Controller 和统一返回结构。现象根因或诊断方向修正位置前端请求出现 /api/apiAxios baseURL 与 Nginx proxy_pass 重复拼接request.ts、nginx.conf登录后仍跳回登录页Token 名称、Pinia 持久化或路由守卫不一致auth store、router、Sa-Token 配置图表显示 0 或空白Dashboard DTO、统一响应 data 层级或 ECharts 映射错误AnalyticsController、analytics API、DashboardPage枚举状态显示英文缺少前端状态映射页面组件与类型定义后端健康检查短暂为 DOWNRabbitMQ 尚未完成启动,应用健康检查已开始探测容器依赖、重试与就绪检查对于修复建议,必须重新执行接口请求和页面操作,确认问题能够复现、修复后消失且没有引入回归。3.4.5 容器与数据库调试常见故障按照以下顺序排查:Docker Desktop 是否已启动;PostgreSQL、Redis、RabbitMQ、MinIO 是否健康;Flyway V1~V6 是否完成迁移;Spring Boot 是否启动并连接到中间件;Nginx 是否正确代理 /api;前端页面是否拿到正确响应。容器内服务地址必须使用 postgres、redis、rabbitmq 和 minio 等 Compose 服务名,不能使用 localhost。3.4.6 CodeArts 贡献与人工把关任务切片码道主要产出人工决策可追溯证据理解工程目录地图、业务域、依赖版本、风险清单以源码为准纠正文档差异README、pom.xml、package.json、领域目录利润防火墙跨实体、服务、接口、页面和测试的修改建议确认金额方向、保护价、舍入和审批口径QuotationService、QuotationServiceTest状态机与幂等合法/非法转换矩阵和重复请求边界拒绝绕过 Service 直接改状态Vehicle/OrderStateMachine、PaymentService前后端联调根据 Network、异常栈和配置定位问题复现问题,只接受回归通过的修正request.ts、nginx.conf、Controller、运行日志演示数据按外键依赖组织迁移和数据检查清单检查数量、日期、状态、金额和看板一致性Flyway V1~V6本案例没有生产工时采集数据,因此不虚构固定的“效率提升百分比”。码道的贡献以可复核产出衡量:任务是否拆清、跨文件命名是否一致、边界测试是否补齐、错误是否能通过日志定位并完成回归。涉及金额、权限、状态和数据删除时,始终由开发者最终确认。3.5 核心技术难点与解决思路3.5.1 跨对象状态一致性难点不在于保存一个状态字段,而在于保证所有入口遵循相同规则,并处理取消、退回和终态。解决方案是把状态转换从 Controller 和页面中抽离到状态机,Service 只调用 validateTransition,再在同一事务中保存业务对象和状态日志。3.5.2 金额精度与利润口径利润计算涉及车价、现金优惠、精品、金融、保险、上牌、延保、置换、厂家补贴、采购成本和资金占用成本。使用 BigDecimal 只是基础,还必须统一空值、舍入、币种、计算顺序和公式版本。3.5.3 多租户与数据权限应用层隔离最常见的问题是新 Repository 方法遗漏 tenantId。当前方案使用租户字段、服务层归属校验、角色数据范围上下文和审计日志;生产环境还应评估 PostgreSQL Row-Level Security、复合唯一索引和跨租户自动化测试。3.5.4 重复提交与并发幂等前端重复点击、网络重试或消息重复消费均可能产生重复数据。订单和收款使用 idempotencyKey 查询拦截,并建议在数据库建立 tenant_id + idempotency_key 唯一索引,将“查询—创建”放入一个事务,由唯一约束完成最终保护。3.5.5 消息可靠性普通站内通知不是主交易的强依赖,因此当前发布失败只记录告警,不回滚车辆或订单。如果事件被用于库存同步、财务记账等关键场景,应升级为 Outbox:业务事务写入事件表,后台可靠投递,消费者使用 eventId 幂等处理,并配置重试和死信队列。3.5.6 演示数据的业务一致性单纯增加记录数量不会让演示更可信。数据必须围绕业务故事组织:高意向但久未跟进的客户触发建议;超过 90 天的车辆触发库存预警;低价报价触发审批;待交付订单展示检查清单;已完成订单支撑利润和漏斗分析。数据之间的日期、状态、金额和外键必须互相一致。Flyway V1~V6 脚本负责结构、基础数据、大规模数据和展示场景的版本化管理。3.6 测试、异常处理与验收3.6.1 代码级验证# 后端单元测试 cd backend mvn test # 前端生产构建 cd ../frontend npm install npm run build # 容器构建与启动 cd ../deploy/docker docker compose up -d --build 3.6.2 健康与运行验收检查项命令或入口通过标准容器状态docker compose psPostgreSQL 为 healthy,其余服务为 Up后端健康GET /api/actuator/healthHTTP 200,status=UPAPI 文档/api/swagger-ui.html页面正常加载并列出业务接口管理端http://localhost登录后进入经营驾驶舱,图表正常渲染数据库迁移后端日志、flyway_schema_historyV1~V6 均成功,无 checksum 冲突消息与对象存储15672、9001 管理台控制台可访问,服务无持续错误3.6.3 核心业务验收场景操作预期结果车辆状态尝试将 LOCKED 直接改为 DELIVERED接口拒绝并返回非法状态转换利润防火墙创建低于保护价的报价,不填写原因直接提交标记风险,提交审批被拒绝订单幂等使用相同幂等键连续创建订单第二次请求提示订单已存在收款幂等使用相同幂等键连续收款第二次请求被拦截,实收金额不重复增加交付门禁必要清单未完成时确认交付提示剩余项数,任务不能完成公海客户客户转入公海后由其他销售认领负责人更新,公海标识清除看板数据切换订单或车辆状态后刷新看板KPI、漏斗和库存分布与明细一致3.6.4 项目与演示数据当前工程和演示环境包含:8 个主要业务域;59 张数据库表;40 个领域类;16 个管理端页面和 11 个前端 API 模块;4 家门店、40+ 名员工;8 个品牌、18 个车系和 18 个车型;125 辆车辆、80+ 位客户;多状态销售订单、收款、发票、金融、保险、交付和结算数据;5 个测试类、32 个核心业务单元测试;前端、后端、PostgreSQL、Redis、RabbitMQ、MinIO 共 6 个容器服务。演示的亮点不在数据量本身,而在数据可以触发真实经营规则:超期线索产生跟进建议、长库龄车辆触发预警、低价报价进入审批、重复请求被拦截、未完成检查项不能交付,最终看板与交易明细保持一致。3.7 运行效果登录系统后可以依次完成以下演示:经营驾驶舱:查看在库车辆、新线索、待交付订单、超期库存、销售漏斗、库存分布和 AI 建议;图 4 经营驾驶舱:核心 KPI、销售漏斗、库存结构与 AI 经营建议看板不是独立维护的静态数字,而是交易数据的聚合视图。演示时可先记录 KPI,再切换车辆或订单状态并刷新页面,验证明细变化能够同步反映到驾驶舱。车辆库存:查看 VIN、状态、库龄、采购成本、总成本、库位和合格证;图 5 VIN 级车辆库存:状态、成本、库位和合格证统一管理每一行库存都对应一辆真实 VIN 车辆。车辆从在途、在库、锁定到已交付的状态变化受到状态机约束,采购成本与总成本则为报价利润校验和单车结算提供统一口径。客户线索:查看客户来源、等级、状态、最近跟进和下次计划;销售订单:查看订单金额、已付金额、业务状态和推进操作;交付控制塔:查看计划交付日期、检查进度和标准化清单;图 6 标准化交付检查清单:必要项未完成不得确认交付系统默认生成覆盖证照、车辆、随车物品和仪式准备等类别的 14 项清单。它既是操作指引,也是系统门禁:前端显示完成进度,后端再次校验必要项,避免只靠页面按钮控制业务结果。经营分析:切换销售漏斗与库存分析;AI 助手:输入“哪些车辆库存超过 90 天”,系统返回真实超期库存数据,并展示清库与跨店调拨建议。图 7 AI 经营助手:以自然语言查询真实业务数据并生成可解释建议AI 助手的回答来自系统库存、线索与销售数据,而非预置一段固定文案;右侧建议卡同时呈现触发车辆、库龄、建议动作和评分。演示时可继续追问具体 VIN、库龄区间或门店范围,体现从“看数据”到“做决策”的闭环。图 8 工程规模与可复核验收证据图 8 给出的数字来自当前工程结构、数据库迁移和自动化测试结果,用于说明案例的完成度,而不是用无法追溯的“效率提升百分比”包装成果。评审者可通过源码目录、Flyway 记录、测试报告、容器状态和健康接口逐项复核。3.8 总结、已知局限与展望智车云将汽车经销商分散的库存、客户、销售、财务和交付数据整合为统一经营平台,并将关键业务规则落实为可执行、可拒绝、可追溯的系统约束。华为云码道代码智能体在项目理解、任务拆解、跨文件开发、测试生成、接口联调和容器化排障过程中提供了有效辅助,使复杂全栈业务系统能够更快完成开发、验证和交付。已知局限:当前案例默认使用本地 Docker Compose,尚未提供长期稳定的生产公网地址;平台内置 AI 助手当前以规则评分和经营数据查询为主,不等同于通用大模型智能体;多租户隔离以应用层校验为主,生产环境仍需统一 Repository 过滤策略并评估数据库 RLS;普通领域事件采用非阻塞发送,关键业务事件尚未实现完整 Outbox;演示账号和默认密码仅适用于本地体验;生产环境仍需补充 HTTPS、密钥托管、备份恢复、监控告警和压力测试。后续可将平台 AI 助手接入企业知识库和大模型推理服务,同时保留确定性规则作为安全兜底;还可将本地 PostgreSQL、Redis、RabbitMQ 和 MinIO 替换为对应云服务,构建面向生产环境的高可用部署方案。四、释放资源4.1 停止本地项目cd deploy/docker # 停止并移除容器与网络,保留数据库等数据卷 docker compose down # 确认不再需要演示数据时,才删除数据卷 docker compose down -v docker compose down -v 会删除 PostgreSQL、Redis、RabbitMQ、MinIO 等数据卷,演示数据将无法直接恢复。仅在确认无需保留时执行。4.2 释放可选云资源如果复现过程中使用了云开发主机、ECS、弹性公网 IP 或数据盘,应在体验结束后:备份需要保留的数据库和日志;停止或删除云服务器和额外数据盘;释放不再使用的弹性公网 IP;删除临时访问密钥和测试账号;检查安全组是否仍存在不必要的放通规则;在费用中心确认没有持续计费资源。五、扩展资料与复现指引5.1 项目内资料资料位置用途项目说明README.md能力、架构、业务域、启动方式和演示数据后端依赖backend/pom.xmlSpring Boot 和依赖版本数据库模型backend/src/main/resources/db/migration表结构、字典和演示数据部署编排deploy/docker/docker-compose.yml本地全栈部署自动化测试backend/src/test/java32 个核心业务用例前端代码frontend/src页面、API、状态管理和路由5.2 推荐复现路径先看演示:通过演示视频了解驾驶舱、库存、客户、订单、交付、分析和 AI 助手;再运行项目:阅读根目录 README,使用 Docker Compose 启动完整环境;理解业务规则:重点阅读车辆状态机、订单状态机、报价利润和交付服务;验证质量:运行后端测试和前端生产构建;复现异常路径:验证非法状态、负利润、重复订单、重复收款和未完成交付清单;阅读迁移脚本:理解演示数据如何围绕业务故事组织;尝试二次开发:使用码道新增业务字段、接口、页面和测试,并完成回归。5.3 开源内容边界公开仓库应提供复现本案例所需的应用源码、测试、部署脚本和说明文档。个人凭据、真实客户数据、本地开发工具配置、运行期日志和数据库数据文件不得提交到公开仓库。提交案例前建议依次核验:代码仓库无需特殊权限即可访问;演示视频无需登录或提取码即可播放;README 中的启动命令能够在全新环境复现;演示账号不包含真实个人数据;文档中的数量、功能状态和测试结果与当前源码一致;所有密钥、Token、密码和私有地址均已清理。六、 演示demo链接https://www.bilibili.com/video/BV1dFg96MEPL/?vd_source=ac4e7ae16e8e5366bd0510ab13603e8d
  • [技术干货] 基于华为云码道(CodeArts)代码智能体的ForumAdmin:论坛管理系统
    基于华为云码道(CodeArts)代码智能体的ForumAdmin:论坛管理系统一、项目简介本次实战我使用华为云码道(CodeArts)代码智能体完成了 ForumAdmin 论坛管理系统。项目围绕"管理员、版主、会员"三种角色展开,实现了登录、发帖、跟帖、删帖、置顶等论坛基础功能,同时实现了DFA敏感词过滤算法、管理员禁言与用户拉黑双层机制、BCrypt密码加密存储,以及Discourse风格的现代论坛UI,形成了功能完备、权限清晰、内容安全的论坛管理系统。代码仓库:ForumAdmin(GitCode)前端:Vue 3 + Vite + Element Plus + Pinia + Vue Router + Axios后端:Java 17 + Spring Boot 3 + MyBatis-Plus + Sa-Token + BCrypt + Druid数据库:MySQL 9.4ForumAdmin 首页二、原始任务与完成情况原题为:论坛管理。实现论坛的版主管理、版块管理、内容管理。需要登陆进入论坛,可以发帖、跟帖和删帖以及置顶等功能。同时能够对敏感词汇进行过滤,拉黑某些会员。我将原题拆成了可验收的功能项,并为每项建立"页面操作 + 后端权限"的证据闭环:原题要求实现方式对应证据登录进入论坛Sa-Token 会话管理、BCrypt 密码加密、注册、退出登录页、注册页版主管理ADMIN 分配版主;MODERATOR 可进入后台管理版块管理页、角色标签显示版块管理创建、编辑、删除、排序、版主绑定版块管理页内容管理帖子/回复分页管理、置顶、删除帖子列表、帖子详情页发帖登录会员选择版块并发布,发布前完成禁言校验和敏感词过滤发帖弹窗、发帖接口跟帖帖子详情页回复,禁言用户和被拉黑用户不可回复帖子详情页、回复区域删帖作者或管理者可删除;逻辑删除删除按钮、删除接口置顶ADMIN 或 MODERATOR 可置顶/取消置顶,置顶优先排序置顶按钮、帖子列表排序敏感词过滤DFA 算法 O(n) 时间复杂度,词库动态重载敏感词管理页、发帖过滤效果拉黑会员管理员禁言(全站) + 用户拉黑(个人);发帖和回复前后端拦截黑名单页、禁言操作、拉黑按钮三、码道代码智能体开发实录我全程使用华为云码道(CodeArts)代码智能体进行开发,从项目初始化到最终UI改造,智能体深度参与了每个阶段。以下是按时间顺序的开发实录:3.1 项目创建与任务理解在码道代码智能体中创建项目后,我将原始任务描述提交给智能体:"实现论坛的版主管理、版块管理、内容管理。需要登陆进入论坛,可以发帖、跟帖和删帖以及置顶等功能。同时能够对敏感词汇进行过滤,拉黑某些会员。"智能体准确理解了需求,并主动拆解为以下模块:用户认证与权限管理(登录/注册/角色控制)版块管理(CRUD + 版主绑定)帖子与回复(发帖/跟帖/删帖/置顶)敏感词过滤(DFA算法)拉黑会员(用户屏蔽机制)3.2 后端项目搭建智能体一步完成了 Spring Boot 3 后端项目初始化,包括:引入 spring-boot-starter-web、mybatis-plus-spring-boot3-starter、sa-token-spring-boot3-starter、druid-spring-boot-3-starter、spring-security-crypto 等核心依赖配置 application.yml(数据源、MyBatis-Plus逻辑删除、Sa-Token会话参数)创建 Result 统一响应封装和 GlobalExceptionHandler 全局异常处理设计6张数据库表(user / section / post / reply / sensitive_word / user_block),编写 init.sql3.3 前端项目搭建智能体使用 Vite 脚手架创建 Vue 3 前端项目,集成:Element Plus 组件库及图标库Pinia 状态管理(用户token和userInfo持久化)Axios 请求封装(baseURL代理、token拦截器、401自动跳转)Vue Router 路由配置(含登录守卫)3.4 核心功能实现智能体按模块逐步生成完整CRUD代码:5组 Entity + Mapper + Service + Controller:User、Section、Post、Reply、SensitiveWordSa-Token RBAC权限:实现 StpInterface 接口,根据用户uid动态返回角色列表BCrypt密码加密:注册时加密存储,登录时matches验证;DataInitializer启动自动检测并转换明文密码DFA敏感词过滤算法:智能体独立实现了确定有限自动机,包括字典构建、匹配检测、文本替换三个核心方法拉黑与禁言双层机制:新增 user_block 表和 UserBlockController,帖子列表SQL动态过滤被拉黑用户,回复前校验帖子作者是否拉黑了回复人3.5 Bug修复与优化开发过程中遇到多个问题,智能体均快速定位并修复:问题原因智能体解决方案版块名称乱码PowerShell管道传输SQL编码丢失移除SQL初始数据,改用Java DataInitializer自动初始化,确保UTF-8密码明文存储初始实现未加密引入BCryptPasswordEncoder,DataInitializer自动检测并转换后台管理按钮不可见仅ADMIN角色可见扩展为ADMIN和MODERATOR均可进入帖子详情API返回nullgetById不关联查询新增selectDetailById关联查询用户名/版块名/回复数帖子创建标题/内容为空前后端均未校验前端表单验证 + 后端参数非空校验3.6 UI改造智能体根据我确认的Discourse风格方案,完成了全部页面改造:创建公共 AppHeader 组件(白底头部 + Logo + 角色标签 + 管理入口)首页:横向分类标签 + 帖子行(头像+标题+分类标签+回复数)+ 浮动发帖按钮帖子详情:时间线流式回复(圆点+连线)+ 底部固定编辑器登录页:浅灰背景 + 圆角卡片后台管理:白底侧边栏 + 图标菜单配色统一:主背景#fff、链接蓝#0088cc、分类标签彩色3.7 开发效率总结通过码道代码智能体,整个项目从零到功能完备仅用时约2天。智能体在以下方面显著提升了效率:代码生成:后端CRUD、前端页面、API接口等重复性代码一键生成算法实现:DFA敏感词过滤等非平凡算法智能体独立完成Bug修复:编码乱码、密码明文等问题智能体快速定位根因并修复架构决策:技术选型(Sa-Token vs Spring Security)、权限模型设计等智能体给出了合理建议一致性保障:公共组件、统一响应封装、路由守卫等确保了代码风格一致四、系统架构与业务闭环整体架构保持前后端分离,开发模式下前端Vite Dev Server代理后端API:会员 / 版主 / 管理员 │ ▼ Vue 3 + Vite (5173) │ Axios → /api 代理 ▼ Sa-Token 会话认证 │ ├── 用户服务 ── BCrypt 密码验证 ├── 论坛业务服务 ── MyBatis-Plus ── MySQL 9.4 ├── RBAC 权限 ── ADMIN / MODERATOR / MEMBER ├── 敏感词 DFA ── 过滤/替换 └── 拉黑/禁言 ── 帖子过滤 + 回复拦截发帖和回复走统一治理链路:提交内容 → 校验是否被禁言(user.status = 0) → 校验是否被帖子作者拉黑 → DFA 敏感词过滤(替换为 ***) → 保存并返回这种设计确保了:禁言用户无法发帖和回帖;被拉黑用户的帖子不会出现在列表中;被帖子作者拉黑的用户无法回复该帖子;敏感词在保存前即被过滤替换。五、逐项功能实现1. 登录进入论坛系统支持注册、登录和退出。登录成功后前端携带 Sa-Token 的 UUID Token 访问需要授权的接口;密码使用 BCrypt 加密存储。登录页面注册页面登录接口实现:@PostMapping("/login") public Result<Map<String, Object>> login(@RequestBody Map<String, String> params) { User user = userService.login(params.get("username"), params.get("password")); Map<String, Object> data = new HashMap<>(); data.put("token", StpUtil.getTokenValue()); data.put("user", user); return Result.ok(data); } Sa-Token 权限配置,根据用户角色动态返回权限列表:@Component public class SaTokenConfig implements StpInterface { private final UserMapper userMapper; @Override public List<String> getPermissionList(Object loginId, String loginType) { return new ArrayList<>(); } @Override public List<String> getRoleList(Object loginId, String loginType) { List<String> roles = new ArrayList<>(); User user = userMapper.selectById(Long.valueOf(loginId.toString())); if (user != null) { roles.add(user.getRole()); } return roles; } } 2. 版主管理管理员可以在版块管理页为每个版块分配版主(通过 moderatorId 字段)。系统实现了三级角色权限控制:角色前台后台管理说明ADMIN发帖/回帖/删帖/置顶版块管理+用户管理(禁言)+敏感词管理超级管理员MODERATOR发帖/回帖/删帖/置顶可进入后台版主MEMBER发帖/回帖不可进入普通会员前端通过角色标签清晰展示当前用户身份:3. 版块管理系统实现了版块的创建、编辑、删除、排序和版主配置。DataInitializer 在启动时自动检查并修复版块数据,确保中文编码正确:private static final String[][] DEFAULT_SECTIONS = { {"技术交流", "讨论技术相关话题"}, {"生活杂谈", "分享生活点滴"}, {"求助问答", "提出问题寻求帮助"} }; 版块管理页面4. 发帖与跟帖登录会员可以选择版块发布帖子,并在帖子详情页回复。发帖与回复都会先检查禁言状态和拉黑关系,再进行敏感词过滤。发帖接口实现(含校验与敏感词过滤):@PostMapping("/add") public Result<Void> add(@RequestBody Post post) { if (post.getTitle() == null || post.getTitle().trim().isEmpty()) { return Result.fail("标题不能为空"); } if (post.getContent() == null || post.getContent().trim().isEmpty()) { return Result.fail("内容不能为空"); } if (post.getSectionId() == null) { return Result.fail("请选择版块"); } Long userId = StpUtil.getLoginIdAsLong(); User user = userService.getById(userId); if (user.getStatus() == 0) { return Result.fail("您已被禁言,无法发帖"); } post.setUserId(userId); post.setTitle(sensitiveWordService.filter(post.getTitle())); post.setContent(sensitiveWordService.filter(post.getContent())); post.setIsTop(0); postService.save(post); return Result.ok(); } 回复接口实现(含拉黑校验):@PostMapping("/add") public Result<Void> add(@RequestBody Reply reply) { Long userId = StpUtil.getLoginIdAsLong(); User user = userService.getById(userId); if (user.getStatus() == 0) { return Result.fail("您已被禁言,无法回复"); } Post post = postService.getById(reply.getPostId()); if (post != null && userBlockService.hasBlocked(post.getUserId(), userId)) { return Result.fail("帖子作者已拉黑您,无法回复"); } reply.setUserId(userId); reply.setContent(sensitiveWordService.filter(reply.getContent())); replyService.save(reply); return Result.ok(); } 帖子列表关联查询,一次SQL获取用户名、版块名和回复数:@Select("<script>" + "SELECT p.*, u.username, u.nickname, s.name AS section_name, " + "(SELECT COUNT(*) FROM reply r WHERE r.post_id = p.id AND r.is_deleted = 0) AS reply_count " + "FROM post p LEFT JOIN user u ON p.user_id = u.uid LEFT JOIN section s ON p.section_id = s.id " + "WHERE p.is_deleted = 0 " + "<if test='blockedIds != null and blockedIds.size() > 0'>" + "AND p.user_id NOT IN " + "<foreach collection='blockedIds' item='id' open='(' separator=',' close=')'>#{id}</foreach>" + "</if>" + " ORDER BY p.is_top DESC, p.create_time DESC" + "</script>") IPage<Post> selectPageAll(Page<Post> page, @Param("blockedIds") java.util.List<Long> blockedIds); 帖子详情页5. 删帖与置顶作者可以删除自己的帖子,管理员和版主可以执行管理删除。删除采用 MyBatis-Plus 逻辑删除(is_deleted 字段),不会物理清除数据。置顶操作更新 is_top 字段,帖子列表按置顶优先、时间倒序排列。置顶接口:@PutMapping("/top/{id}") public Result<Void> top(@PathVariable Long id, @RequestParam Integer isTop) { postService.setTop(id, isTop); return Result.ok(); } 逻辑删除配置:mybatis-plus: global-config: db-config: logic-delete-field: isDeleted logic-delete-value: 1 logic-not-delete-value: 0 6. 敏感词过滤敏感词管理支持新增、删除和动态重载。过滤算法采用 DFA(确定有限自动机),时间复杂度为 O(n),其中 n 为待过滤文本长度,与敏感词数量无关。DFA 核心实现:@Component public class SensitiveWordFilter { private final Map<Character, Object> dictMap = new HashMap<>(); private static final String REPLACEMENT = "***"; public void loadWords(List<SensitiveWord> words) { dictMap.clear(); for (SensitiveWord sw : words) { String word = sw.getWord().trim(); if (word.isEmpty()) continue; Map<Character, Object> current = dictMap; for (int i = 0; i < word.length(); i++) { char c = word.charAt(i); Object next = current.get(c); if (next == null) { Map<Character, Object> newNode = new HashMap<>(); current.put(c, newNode); current = newNode; } else { current = (Map<Character, Object>) next; } } current.put('\0', null); } } public String filter(String text) { if (text == null || text.isEmpty()) { return text; } StringBuilder result = new StringBuilder(text); for (int i = 0; i < text.length(); i++) { int length = checkSensitiveWord(text, i); if (length > 0) { for (int j = i; j < i + length; j++) { result.setCharAt(j, REPLACEMENT.charAt(0)); } i += length - 1; } } return result.toString(); } @SuppressWarnings("unchecked") private int checkSensitiveWord(String text, int startIndex) { Map<Character, Object> current = dictMap; int length = 0; for (int i = startIndex; i < text.length(); i++) { char c = text.charAt(i); Object next = current.get(c); if (next == null) { break; } length++; current = (Map<Character, Object>) next; if (current.containsKey('\0')) { return length; } } return 0; } } 词库动态重载接口:@GetMapping("/refresh") public Result<Void> refresh() { sensitiveWordService.refreshDict(); return Result.ok(); } 敏感词管理页面7. 拉黑会员系统实现了双层机制:管理员禁言:全站级别,修改 user.status = 0,禁言用户可登录但无法发帖和回帖用户拉黑:个人级别,通过 user_block 表记录,拉黑后看不到对方帖子,对方无法回复自己的帖子操作执行者范围效果禁言管理员全站可登录,但无法发帖、回帖拉黑任何用户个人我看不到他的帖子,他不能回复我的帖子拉黑接口实现:@RestController @RequestMapping("/api/block") @RequiredArgsConstructor public class UserBlockController { private final UserBlockService userBlockService; @PostMapping("/add/{blockedUserId}") public Result<Void> block(@PathVariable Long blockedUserId) { Long userId = StpUtil.getLoginIdAsLong(); userBlockService.block(userId, blockedUserId); return Result.ok(); } @DeleteMapping("/remove/{blockedUserId}") public Result<Void> unblock(@PathVariable Long blockedUserId) { Long userId = StpUtil.getLoginIdAsLong(); userBlockService.unblock(userId, blockedUserId); return Result.ok(); } @GetMapping("/list") public Result<List<UserBlock>> myBlockList() { Long userId = StpUtil.getLoginIdAsLong(); return Result.ok(userBlockService.myBlockList(userId)); } } 帖子列表查询时动态过滤被拉黑用户的帖子:@GetMapping("/list") public Result<IPage<Post>> list(@RequestParam(required = false) Long sectionId, @RequestParam(defaultValue = "1") long page, @RequestParam(defaultValue = "10") long size) { List<Long> blockedIds = Collections.emptyList(); if (StpUtil.isLogin()) { blockedIds = userBlockService.getBlockedUserIds(StpUtil.getLoginIdAsLong()); } if (sectionId != null) { return Result.ok(postService.pageBySectionId(sectionId, page, size, blockedIds)); } return Result.ok(postService.pageAll(page, size, blockedIds)); } 黑名单管理页面8. Discourse 风格 UI系统采用 Discourse 风格的现代论坛 UI 设计,主要特点包括:白底头部:统一的 AppHeader 组件,包含 Logo、用户信息、角色标签、管理入口横向分类标签:版块以彩色标签形式横向排列,点击切换过滤帖子列表:每行显示头像、标题、分类标签、回复数,替代传统表格时间线流式回复:帖子详情页回复以圆点+连线的时间线形式展示底部固定编辑器:回复输入框固定在页面底部,随时可输入浮动发帖按钮:右下角圆形按钮,点击弹出发帖弹窗公共头部组件核心代码:<template> <header class="app-header"> <div class="header-inner"> <div class="header-left" @click="$router.push('/')"> <span class="logo">Forum</span> </div> <div class="header-right"> <span class="user-name">{{ userStore.userInfo?.nickname || '用户' }}</span> <el-tag v-if="userStore.userInfo?.role === 'ADMIN'" type="danger" size="small" effect="dark">管理员</el-tag> <el-tag v-else-if="userStore.userInfo?.role === 'MODERATOR'" color="#e6a23c" size="small" effect="dark" style="color:#fff;border:none">版主</el-tag> <el-tag v-else type="info" size="small" effect="plain">会员</el-tag> <el-button v-if="userStore.userInfo?.role === 'ADMIN' || userStore.userInfo?.role === 'MODERATOR'" text @click="$router.push('/admin')"> <el-icon><Setting /></el-icon> 管理 </el-button> <el-button text @click="$router.push('/blocklist')"> <el-icon><UserFilled /></el-icon> 黑名单 </el-button> <el-button text type="danger" @click="handleLogout"> <el-icon><SwitchButton /></el-icon> 退出 </el-button> </div> </div> </header> </template> 首页帖子列表核心代码:<div v-for="p in posts" :key="p.id" class="post-row" @click="$router.push(`/post/${p.id}`)"> <div class="post-avatar"> <el-avatar :size="36" :style="{ background: sectionColor(p.sectionId) }"> {{ (p.nickname || p.username || '?')[0] }} </el-avatar> </div> <div class="post-body"> <div class="post-title-row"> <el-tag v-if="p.isTop === 1" type="danger" size="small" effect="dark" class="top-tag">置顶</el-tag> <span class="post-title">{{ p.title }}</span> <span class="post-cat" :style="{ background: sectionColor(p.sectionId) + '18', color: sectionColor(p.sectionId) }">{{ p.sectionName }}</span> </div> <div class="post-meta"> <span class="meta-author">{{ p.nickname || p.username }}</span> <span class="meta-dot">·</span> <span class="meta-time">{{ p.createTime }}</span> </div> </div> <div class="post-stats"> <el-icon><ChatDotRound /></el-icon> <span>{{ p.replyCount || 0 }}</span> </div> </div> 首页全貌帖子详情时间线回复六、创新与易用性DFA 敏感词过滤:采用确定有限自动机算法,时间复杂度 O(n)(n为文本长度),与敏感词数量无关;词库支持动态热重载,无需重启服务。拉黑/禁言双层机制:管理员禁言为全站级别(修改 user.status),用户拉黑为个人级别(user_block 表),两者逻辑清晰、互不干扰,分别作用于不同场景。BCrypt 密码加密:使用 BCryptPasswordEncoder 加密存储密码,BCrypt 自带盐值,每次加密结果不同,抗彩虹表攻击。DataInitializer 启动时自动检测并转换明文密码。Discourse 风格 UI:白底头部、横向分类标签、时间线流式回复、底部固定编辑器、浮动发帖按钮,提供现代论坛体验。前后端双重校验:前端表单提交前验证必填项,后端接口同样校验参数非空,避免绕过前端直接提交空数据。数据自动修复:DataInitializer 启动时自动检测并修复中文乱码、明文密码、缺失数据等问题,确保系统开箱即用。七、码道新能力与华为云技术使用使用华为云码道(CodeArts)代码智能体完成全流程开发,从项目搭建、代码生成到功能实现和Bug修复;通过自然语言 Prompt 指导智能体完成数据库设计、CRUD 接口生成、敏感词算法实现、权限配置和 UI 改造;使用浏览器控制能力对 ADMIN、MODERATOR、MEMBER 等真实页面进行验收和截图,避免以 mock 页面冒充后端功能;项目级规则约束技术栈(SpringBoot3 + Vue3)、权限模型(RBAC 三级角色)和内容治理(DFA + 禁言 + 拉黑)。八、测试与验证结果项目完成了前端生产构建和后端编译验证:验证项结果后端编译mvn compile 通过前端生产构建npm run build 通过,所有组件正常打包浏览器真实验收多张页面证据,关键页面功能正常权限验证未登录跳转登录页,MEMBER 不可进入后台验证命令如下:# 后端编译 cd backend mvn compile # 前端生产构建 cd ../frontend npm run build九、本地运行本地开发# 1. 初始化数据库 mysql -u root -p < sql/init.sql # 2. 启动后端 cd backend mvn spring-boot:run # 3. 另开终端启动前端 cd frontend npm install npm run dev访问 http://localhost:5173,后端API端口为 8080。一键启动项目提供了 start.bat 一键启动脚本,双击即可同时启动后端和前端。默认账号账号密码角色adminadmin123ADMINmoderatormod123MODERATORmembermem123MEMBER十、逐项对应评分项项目成果与证据创新易用DFA敏感词O(n)过滤、拉黑/禁言双层机制、BCrypt加密、Discourse风格UI、前后端双重校验、数据自动修复功能完备原题10个功能点全部闭环;登录/注册/发帖/回帖/删帖/置顶/敏感词/禁言/拉黑/版块管理全部实现技术能力码道全流程开发、Sa-Token认证+RBAC、DFA算法、MyBatis-Plus逻辑删除、前后端分离架构文档完整性开发日志、数据库设计、API接口、本地运行说明、默认账号、一键启动脚本完整十一、项目成果总结这次实战让我从"实现一个能发帖的页面",进一步走到了"构建一个权限正确、内容安全、UI现代、开箱即用的论坛系统"。ForumAdmin 已在本地完成核心功能、生产构建验证和真实页面验收;项目同时保留了开发日志、数据库设计、API接口文档和运行说明,方便评审复现。核心成果:6张数据库表:user / section / post / reply / sensitive_word / user_block,支持逻辑删除和自动时间填充DFA敏感词过滤:O(n)时间复杂度,动态词库热重载拉黑/禁言双层机制:全站禁言与个人屏蔽分离,逻辑清晰BCrypt密码加密:启动自动检测并转换明文密码Discourse风格UI:白底头部、横向分类标签、时间线回复、浮动发帖按钮一键启动:start.bat 双击即可运行
  • [技术干货] CampFlow 训练营成果管理助手:CodeArts Agent 项目实践
    大家好,我本次训练营完成的项目是 CampFlow 训练营成果管理助手。这是一个面向华为云码道暑期实习训练营的 Web 工作台,用来帮助学生把在线学习、CodeArts Agent 辅助开发、项目构建、华为云部署、案例文档发布和最终作品链接提交这些分散任务整合到一个可追踪的流程中。一、项目背景在训练营实践过程中,我发现项目提交并不只是写出一个能运行的页面,还需要同时完成学习进度、CodeArts Agent 使用过程、项目部署、案例文档、附件材料和最终链接提交。任务节点比较分散,如果只靠临时记录,很容易出现材料遗漏、演示链接忘记回填、评分维度没有证据支撑等问题。因此我设计了 CampFlow,希望它既是一个可运行的训练营成果管理应用,也能反向辅助我整理最终提交材料。它把指导书中的评分维度和提交要求产品化,形成项目档案、里程碑、评分证据、智能体提示词和案例文档生成几个模块,让整个实习项目从开发到提交都更加清晰。二、作品链接作品演示地址:https://campflow-demo-20260727.fangtianchen3.chatgpt.site/案例中心链接:https://devstation.connect.huaweicloud.com/space/devportal/casecenter/11272f6a85244aad99d738b32bac093c/2三、技术选型本项目采用纯静态前端方案,核心技术如下:- CodeArts Agent:辅助需求分析、架构设计、功能开发、测试部署和案例文档整理- HTML / CSS / JavaScript:实现页面结构、交互逻辑和响应式布局- localStorage:在浏览器本地保存项目档案、里程碑、评分证据和开发记录- 华为云 OBS:托管静态网站并提供公网访问地址- Node.js assert:对得分计算、数据模型和文档生成逻辑进行基础测试选择纯静态方案的原因是训练营项目更看重完整交付闭环。静态 Web 应用部署简单、依赖少、访问稳定,适合快速完成从代码构建到华为云部署的全过程。四、需求分析根据训练营指导书,项目成果需要包含可运行应用、案例文档、演示链接或视频,并且 Web 类应用需要部署到华为云。评分维度包括创新易用、功能完备、技术能力、文档完整性和参与度。围绕这些要求,我将需求拆成五个方向:1. 成果管理:记录项目名称、应用方向、技术栈、演示链接和案例链接。2. 过程管理:把学习、开发、部署、发布等训练营节点转化为里程碑。3. 智能体协作:自动生成适合 CodeArts Agent 的阶段性提示词。4. 评分证据:按评分维度整理证据项、完成状态、说明和链接。5. 文档发布:根据项目档案和证据清单生成案例 Markdown 草稿。这样做的好处是,项目不只是“做完一个页面”,而是把提交要求转化成了可以持续检查的工作流。五、系统架构设计CampFlow 的整体结构比较轻量:```text用户浏览器  ├─ index.html:应用入口  ├─ assets/styles.css:界面样式和响应式布局  ├─ assets/app.js:状态管理、评分计算、提示词生成和 Markdown 生成  └─ localStorage:保存项目档案、评分证据、里程碑和开发记录```项目没有引入后端服务,所有数据保存在浏览器本地。对于训练营展示场景来说,这种方案可以降低部署复杂度,也避免后端账号、数据库和接口联调带来的额外成本。六、CodeArts Agent 辅助开发过程本项目按照 vibe coding 的思路使用 CodeArts Agent。我的实践方式不是一次性让智能体直接生成全部代码,而是分阶段推进:第一阶段是需求分析。我先让 CodeArts Agent 根据指导书梳理项目目标、评分维度和必须交付的材料,避免项目范围跑偏。第二阶段是架构设计。我让智能体输出静态前端架构、本地存储数据模型,以及每个页面模块需要承担的职责。第三阶段是功能开发。根据模块拆分,逐步实现仪表盘、项目档案、提示词生成、评分证据、案例文档生成和部署清单。第四阶段是调试验证。重点检查评分计算是否符合权重、localStorage 是否能正常保存、Markdown 文档是否能完整生成、部署文件是否齐全。第五阶段是文档整理。最后让智能体辅助把开发过程、部署步骤、项目亮点和总结整理成案例中心与论坛都能使用的材料。通过这种分阶段协作,CodeArts Agent 更像一个项目搭档,而不是简单的代码生成器。它帮助我把任务拆小,也让我在每一步都有可检查的输出。七、核心功能介绍1. 仪表盘:展示预计得分、证据完成数量、里程碑完成数量,并按指导书权重拆解评分维度。2. 项目档案:维护项目名称、应用方向、真实问题、解决方案、技术栈、考试状态、演示链接和案例链接。3. CodeArts 提示词生成:根据项目当前状态生成需求分析、架构设计、功能开发、调试部署和案例文档五类提示词,方便继续与智能体协作。4. 评分证据清单:按照创新易用、功能完备、技术能力、文档完整性和参与度五个维度组织证据项,支持完成状态和说明记录。5. 案例文档生成器:把项目档案、评分证据和开发记录拼装成 Markdown 草稿,减少最终发布时遗漏章节的风险。6. 部署清单:列出静态网站部署需要上传的文件,并提醒检查 OBS 桶、静态网站首页、公开访问策略和演示链接。八、部署过程项目最终部署在华为云 OBS 静态网站托管上。部署步骤如下:1. 创建 OBS 桶 `campflow-tj-20260726`,区域选择华东-上海一 `cn-east-3`。2. 上传静态网站文件,根目录包含 `index.html`,`assets` 目录包含 `app.js` 和 `styles.css`。3. 开启静态网站托管,默认首页设置为 `index.html`。4. 创建桶策略 `campflow-public-read`,允许公网读取静态网站对象。5. 访问 OBS 静态网站地址,确认页面可以正常打开。验证结果:- 首页 HTTP 状态为 200- 页面内容包含 CampFlow- 静态网站公网地址可访问九、测试与验收项目包含基础逻辑测试,主要验证数据模型、评分计算和文档生成相关逻辑。测试通过后,我又进行了浏览器访问检查,确认页面能够在本地和 OBS 环境中正常运行。验收时重点检查了以下内容:- 页面能正常加载- 仪表盘数据能展示- 表单内容能保存到 localStorage- 提示词能够生成- 案例文档能够生成- OBS 演示链接能够公网访问- 案例中心附件 PDF 小于 20MB十、遇到的问题与解决方式第一个问题是提交材料分散。训练营要求包含代码、部署、案例文档、演示链接等内容,开始时容易只关注开发本身,忽略最终提交材料。因此我把这些要求做成了应用中的评分证据和部署清单。第二个问题是静态部署的公开访问配置。OBS 上传文件后,如果没有正确配置静态网站托管和公开读策略,外部访问会失败。最后通过设置默认首页 `index.html` 和桶策略 `campflow-public-read` 解决。第三个问题是论坛和案例中心链接类型不同。案例中心链接用于案例提交,OBS 链接用于作品演示,而论坛链接用于社区帖子展示。理解这三类链接的区别后,最终提交路径就清晰了。## 十一、项目总结CampFlow 是一次围绕训练营真实提交场景设计的小型工具实践。它不只是一个静态页面,而是把 CodeArts Agent 使用过程、评分标准、部署清单和案例文档整理流程放在同一个工作台里。通过这个项目,我完成了从需求分析、智能体辅助开发、本地测试、OBS 部署、案例中心提交到论坛发布材料整理的完整闭环。后续如果继续扩展,可以加入截图上传、多人协作、华为云登录和一键生成提交材料等能力,让它从个人训练营工具升级为更通用的项目交付助手。以上就是我的训练营项目实践分享,欢迎大家交流指正。
  • [案例共创] 影院管理系统(Cinema Management System)开发案例
     案例介绍本案例采用华为云码道(CodeArts)代码智能体作为核心开发工具,结合SDD(Specification-Driven Development)规范驱动开发方法论,构建从需求分析、系统设计、页面原型到SDD文档体系的完整开发流程。实现影院管理系统从需求到设计的全流程智能化场景,让影院运营告别手动管理,迈入数字化新时代。一、概述1.1 案例介绍在中小型影院日常运营中,票务管理往往成为"隐形痛点":排片信息依赖手动更新导致观众跑空,座位销售情况不透明无法实时掌握空座率,售票数据分散无法进行精准的票房统计,观众购票体验差无法在线选座。影院运营人员疲于奔命,管理者对经营状况一知半解,影院因信息不透明和运营效率低下造成的收入损失难以估量。在数字化转型浪潮下,如何让影院的票务数据"活"起来,成为影院管理升级的关键一环。本案例旨在通过华为云码道(CodeArts)代码智能体驱动的SDD开发方法论,为影院管理系统注入"数字智慧",实现影院运营的全流程数字化、智能化管理。本案例采用华为云码道(CodeArts)代码智能体作为核心开发工具,结合dev-process-framework、page-mockup、function-detail、fullstack-testing等专业化skills,构建从需求分析、系统设计、页面原型到SDD文档体系的完整开发流程。该方案将传统开发中分散的需求文档、设计文档、任务清单整合为规范化的SDD体系,使决策过程可追溯、文档与代码同步更新,大幅提升开发效率和项目可维护性。通过华为云码道的智能体模式,开发者无需深厚架构背景即可快速完成复杂企业级应用的设计与规划。案例技术选型:华为云码道(CodeArts)代码智能体:集代码大模型、AI IDE、Code Agent为一体的智能编码产品。具备强大的需求理解、架构设计和代码生成能力,支持智能体模式自动规划并执行复杂开发任务。本案例中作为核心开发平台,通过对话式交互快速完成影院管理系统的需求分析、架构设计和SDD文档生成。SDD规范驱动开发方法论:系统化的软件开发方法论,包含creating-sdd-directory、managing-spec/design/tasks-document四大核心流程skills。使决策过程可追溯,文档与代码同步更新,形成完整知识库,特别适合多模块复杂功能项目。本案例中作为整体开发方法论指导,确保影院管理系统开发的规范性、可追溯性和可维护性。系统技术选型:  层次技术选型版本说明前端框架Vue.js3.4+组合式API,TypeScript支持前端构建Vite5.x快速构建工具UI组件库Ant Design Vue4.x企业级Vue3组件库状态管理Pinia2.xVue3官方状态管理后端框架Spring Boot3.2.5应用框架ORM框架MyBatis-Plus3.5.6ORM框架数据库MySQL8.0关系型数据库缓存Redis6.x缓存/分布式锁认证授权Spring Security + JWT6.x认证授权容器化Docker-容器化部署1.2 适用对象个人开发者高校学生企业开发者架构设计师1.3 案例时间本案例总时长预计 120分钟。1.4 案例流程  阶段内容说明阶段一环境准备与技能配置安装部署华为云码道(CodeArts)代码智能体,配置项目级Skills阶段二系统设计使用dev-process-framework skill生成系统设计阶段三页面设计使用page-mockup skill生成前端页面设计阶段四测试设计使用fullstack-testing skill生成测试设计文档阶段五SDD文档生成使用function-detail skill整合生成完整SDD文档体系阶段六代码实现基于SDD文档完成前后端代码开发阶段七测试验证执行测试用例并修复缺陷二、环境与资源准备2.1 开发环境部署2.1.1 JDK 17 安装访问 Adoptium 官网,下载 JDK 17 Windows 版本 .msi 安装包配置环境变量:新建系统变量 JAVA_HOME,值为 C:\Program Files\Eclipse Adoptium\jdk-17.xx.xx在 Path 变量中添加 %JAVA_HOME%\bin打开新的CMD窗口,验证安装:cmdjava -version应显示 openjdk version "17.0.x"2.1.2 Maven 安装访问 Maven 官网(cid:link_1),下载 Binary zip 格式文件解压到 C:\Program Files\apache-maven-3.9.x配置环境变量:新建系统变量 MAVEN_HOME,值为 C:\Program Files\apache-maven-3.9.x在 Path 变量中添加 %MAVEN_HOME%\bin验证安装:cmdmvn -version2.1.3 MySQL 8.0 安装与配置访问 MySQL 官网,下载 MySQL 8.0 Windows 安装包双击安装,选择"Developer Default"安装类型安装过程中设置 root 密码(本案例记为 Guoll050329)安装完成后,MySQL 服务自动启动验证安装:cmdmysql --version创建数据库:sqlCREATE DATABASE cinema_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;2.1.4 Redis 安装访问微软维护的 Redis Windows 版本(cid:link_0)下载 .msi 安装包,如 Redis-x64-3.0.504.msi验证安装:cmdredis-cli ping应返回 PONG2.1.5 Node.js 安装访问 Node.js 官网(cid:link_2)下载 LTS 版本(v20.x.x 或 v22.x.x)的 Windows Installer (.msi)"验证安装:cmdnode --versionnpm --version2.2 华为云码道配置2.2.1 项目级技能配置通过前序案例《影院管理系统(一):码道搭台,设计筑基》,已完成码道开发生态skills的集中配置。本案例用到的Skills:  Skill名称用途使用阶段sdd-workflow开发流程管理、进度跟踪全过程bug-fix-reporter自动生成Bug修复报告Bug修复fullstack-testing测试用例编写与执行测试阶段三、对话华为云码道:构建影院管理系统3.1 基础环境准备与项目初始化3.1.1 Windows开发环境部署对话华为云码道(CodeArts)代码智能体: 请执行tasks中的任务 1.1.1:Windows开发环境部署。 任务执行总结:  检查项状态说明JDK 17✅ 已完成环境变量已配置Maven✅ 已完成环境变量已配置MySQL 8.0✅ 已完成服务运行中,cinema_db已创建Redis✅ 已完成服务运行中Node.js✅ 已完成环境变量已配置Sprint报告: ProjectDocs\sprint\第1部分:基础环境准备\001环境部署.md3.1.2 后端项目初始化继续对话华为云码道:请继续完成tasks中的任务 1.1.2:后端项目初始化(Spring Boot工程目录+API骨架+数据模型骨架)。项目信息:项目路径:S:\Cinema Management\demo包结构:com.cinemaSpring Boot版本:3.2.5构建工具:Maven任务执行总结:  任务ID任务描述状态产出物1.1.2后端项目初始化✅ 完成pom.xml、application.yml、实体类、Mapper接口关键成果:Spring Boot 3.2.5 项目结构建立MyBatis-Plus 配置完成6张核心实体类(Film、Hall、Showtime、SeatInstance、Order、User)Mapper接口与Service骨架数据库连接配置Sprint报告: ProjectDocs\sprint\第1部分:基础环境准备\002后端项目初始化.md3.1.3 前端项目初始化继续对话华为云码道:请继续完成tasks中的任务 1.1.3:前端项目初始化(Vue3工程目录+API封装骨架+基础组件)。项目信息:项目路径:S:\Cinema Management\demo\cinema-frontend技术栈:Vue 3 + Vite + Pinia + Vue Router + Ant Design Vue任务执行总结:  任务ID任务描述状态产出物1.1.3前端项目初始化✅ 完成package.json、vite.config.js、路由配置、Store骨架关键成果:Vue 3 + Vite 项目结构建立Pinia状态管理配置Vue Router路由配置Axios封装(request.js)基础布局组件(Navbar、Footer)Sprint报告: ProjectDocs\sprint\第1部分:基础环境准备\003前端项目初始化.md基础环境准备阶段总结:任务编号任务描述状态1.1.1Windows开发环境部署✅ 完成1.1.2后端项目初始化✅ 完成1.1.3前端项目初始化✅ 完成3.2 核心业务模块开发对话华为云码道:# 影院管理系统(Cinema Management System)## 项目概述开发一个影院管理系统的后端服务,采用Spring Boot 3.x + MyBatis-Plus + MySQL + Redis技术栈,提供RESTful API接口供前端调用。系统面向两类用户:普通观众(购票)和影院管理员(后台管理)。整体采用模块化单体架构,按业务领域划分包结构。## 技术约束- 开发语言:Java 17- 框架:Spring Boot 3.x,使用Spring Security + JWT做认证授权- ORM:MyBatis-Plus 3.5.x- 数据库:MySQL 8.0,使用InnoDB引擎,字符集utf8mb4- 缓存:Redis 6.x(用于存储座位状态、热点数据、分布式锁)- 工具库:Lombok、Hutool、Jackson- API风格:RESTful,统一返回格式为 { code, message, data }- 包结构:按模块划分,每个模块包含 controller, service, mapper, entity, dto, vo, enums## 数据库核心表结构- films:影片表,字段包括id, title, genre, duration, director, cast, description, poster_url, release_date, status(枚举:COMING_SOON/NOW_SHOWING/EXPIRED),created_at, updated_at- halls:影厅表,字段包括id, name, type(枚举:STANDARD/IMAX/3D),total_rows, total_columns, total_seats, created_at, updated_at- showtimes:场次表,字段包括id, film_id, hall_id, start_time, end_time, price, created_at, updated_at- seat_instances:座位实例表(按场次生成),字段包括id, showtime_id, hall_id, row_num, col_num, seat_number, status(枚举:AVAILABLE/LOCKED/SOLD/MAINTENANCE),lock_time, lock_expire_at, order_id, version(乐观锁), created_at, updated_at- orders:订单表,字段包括id, order_no(业务唯一编号), user_id, showtime_id, seat_ids(JSON数组), total_price, status(枚举:PENDING/PAID/CANCELLED/REFUNDED/EXPIRED), pay_time, expire_time, created_at, updated_at- users:用户表,字段包括id, username, password(BCrypt加密), phone, email, role(枚举:ADMIN/USER), created_at, updated_at## 模块划分与功能描述### 模块一:影片管理模块(Film Module)包路径:com.cinema.film功能描述:- 管理影片的增删改查操作- 支持分页查询影片列表,可按状态(上映中/即将上映/已下架)、类型、关键词搜索- 提供"即将下架"预警功能:查询距离下架日期(release_date + 默认上映周期30天)不足3天的上映中影片- 管理员可新增、修改、下架影片- 普通用户可查看影片详情和列表- Controller:FilmController,提供 /api/films 前缀的接口### 模块二:影厅与排片管理模块(Hall & Showtime Module)包路径:com.cinema.hall, com.cinema.showtime功能描述:- 影厅管理:增删改查影厅信息,包括座位布局(行数、列数)- 排片管理:为影片安排放映场次,需校验同一影厅同一时间段无冲突- 排片时自动生成该场次的座位实例(状态均为AVAILABLE),总座位数=影厅总座位数- 提供按影片ID查询排片列表、按日期查询排片列表- 管理员专属操作,普通用户只读- Controller:HallController(/api/halls),ShowtimeController(/api/showtimes)### 模块三:座位与库存管理模块(Seat Module)包路径:com.cinema.seat功能描述:- 提供按场次ID查询座位图,返回包含行、列、座位号、状态(AVAILABLE/LOCKED/SOLD/MAINTENANCE)的列表- 提供统计接口:查询某场次的空座数(状态为AVAILABLE的座位数量)- 座位锁定操作:将指定座位的状态从AVAILABLE改为LOCKED,设置lock_expire_at=当前时间+15分钟,记录order_id(临时)- 座位释放操作:将LOCKED状态的座位恢复为AVAILABLE,清空lock_time、lock_expire_at、order_id- 座位售出操作:将LOCKED状态的座位改为SOLD,关联实际订单ID- 所有座位状态变更必须基于乐观锁(version字段)防止并发冲突,并配合Redis缓存提升性能- 缓存设计:Redis中存储 key="seat:showtime:{showtimeId}", value为Hash结构,field为"row-col",value为状态枚举值,用于快速查询和更新- Controller:SeatController,提供 /api/seats 前缀的接口### 模块四:售票与选座模块(Ticketing Module)包路径:com.cinema.ticketing功能描述:- 自动选座:接收参数(场次ID,购票数量),自动分配连续且居中位置的AVAILABLE座位,一次性锁定所有分配座位,返回座位列表- 手工选座:接收参数(场次ID,座位ID列表),校验所有座位均为AVAILABLE状态,一次性锁定,返回锁定结果- 锁定座位时需使用Redis分布式锁(key="lock:showtime:{showtimeId}")防止同一场次并发锁定冲突- 锁定成功后创建待支付订单,订单超时时间为15分钟- 提供选座预览(不实际锁定):模拟自动选座返回推荐座位但不改变状态- Controller:TicketingController,提供 /api/ticketing 前缀的接口### 模块五:订单管理模块(Order Module)包路径:com.cinema.order功能描述:- 创建订单:生成全局唯一订单号(格式:ORD+yyyyMMddHHmmss+6位随机数),记录用户ID、场次ID、座位ID列表、总价、状态为PENDING,设置expire_time=当前时间+15分钟- 支付订单:将PENDING状态改为PAID,触发座位状态变更为SOLD,记录支付时间- 取消订单:用户主动取消,将PAYING状态改为CANCELLED,释放锁定座位- 订单超时自动处理:定时任务扫描expire_time < 当前时间且状态为PENDING的订单,改为EXPIRED,释放座位- 查询订单:用户可查询自己的订单列表和详情,管理员可查询所有订单- Controller:OrderController,提供 /api/orders 前缀的接口### 模块六:用户与会员管理模块(User Module)包路径:com.cinema.user功能描述:- 用户注册:用户名唯一,密码使用BCrypt加密存储- 用户登录:验证用户名密码,签发JWT Token(有效期24小时)- 获取当前用户信息:通过JWT解析用户身份- 区分角色:ADMIN可访问管理接口,USER仅可访问用户接口- Controller:AuthController(/api/auth),UserController(/api/users)### 模块七:权限与安全模块(Security Module)包路径:com.cinema.security功能描述:- 基于Spring Security + JWT实现认证和授权- 配置SecurityFilterChain,定义白名单路径(/api/auth/login, /api/auth/register)- 除白名单外所有接口需携带JWT Token(Header: Authorization: Bearer <token>)- 角色拦截:管理员接口(/api/admin/**)仅允许ROLE_ADMIN访问- 提供全局异常处理,返回统一格式错误响应### 模块八:通知与监控模块(Notification Module)包路径:com.cinema.notification功能描述:- 支付成功后发送通知(现阶段实现为日志记录,预留接口便于后续接入短信/邮件)- 订单超时释放座位的日志记录- 系统异常告警日志记录## 关键业务流程(必须实现)### 购票完整流程(核心)1. 用户登录,获取JWT Token2. 浏览影片列表 -> 选择影片 -> 查看排片列表 -> 选择场次3. 查看座位图 -> 选择自动选座或手工选座4. 调用选座接口,锁定座位,创建待支付订单,返回订单信息5. 用户调用支付接口(模拟支付:传入订单ID即可),将订单状态改为PAID6. 支付成功后,座位状态变为SOLD,触发通知7. 若15分钟内未支付,定时任务自动取消订单并释放座位### 超时释放任务- 使用@Scheduled注解,每30秒执行一次- 查询所有状态为PENDING且expire_time < NOW()的订单- 遍历订单,将订单状态改为EXPIRED,调用座位释放逻辑## API接口命名规范- GET /api/films - 分页查询影片- GET /api/films/{id} - 查询影片详情- POST /api/admin/films - 新增影片(管理员)- PUT /api/admin/films/{id} - 修改影片(管理员)- DELETE /api/admin/films/{id} - 下架影片(管理员)- GET /api/showtimes/film/{filmId} - 查询影片的排片- GET /api/seats/showtime/{showtimeId} - 查询场次座位图- GET /api/seats/available-count/{showtimeId} - 查询空座数- POST /api/ticketing/auto - 自动选座(参数:showtimeId, quantity)- POST /api/ticketing/manual - 手工选座(参数:showtimeId, seatIds)- POST /api/orders - 创建订单(通常由选座接口内部调用)- PUT /api/orders/pay/{orderId} - 支付订单- PUT /api/orders/cancel/{orderId} - 取消订单- GET /api/orders/user - 查询当前用户订单- POST /api/auth/login - 登录- POST /api/auth/register - 注册## 非功能性要求- 所有接口响应时间控制在200ms以内(不含网络延迟)- 座位锁定必须保证原子性,防止超卖- 代码需包含完善的注释和日志记录- 遵循RESTful设计规范- 数据库设计需建立合理索引:orders表需对user_id、showtime_id、status建立索引;seat_instances表需对showtime_id、status建立联合索引3.3 测试与优化3.3.1 测试设计优化对话华为云码道:请深度检索项目,并使用fullstack-testing skill根据当前项目状态,优化和完善SDD中的测试设计以及tasks中的测试任务。注: 建议该指令执行三次,以避免问题遗漏。3.3.2 后端单元测试编写对话华为云码道:请使用fullstack-testing skill继续完成tasks中的任务 3.2.1:后端单元测试编写。任务执行总结:  测试文件用例数模块状态test_auth_service.py18认证服务✅ 完成test_film_service.py14影片服务✅ 完成test_showtime_service.py12排片服务✅ 完成test_seat_service.py17座位服务✅ 完成test_order_service.py16订单服务✅ 完成合计77  3.3.3 前端单元测试编写对话华为云码道:请使用fullstack-testing skill继续完成tasks中的任务 3.2.2:前端单元测试编写。任务执行总结:  测试文件用例数模块状态auth.test.ts7认证Store✅ 完成film.test.ts8影片Store✅ 完成seat.test.ts10座位Store✅ 完成order.test.ts8订单Store✅ 完成format.test.ts15格式化工具✅ 完成合计48  3.3.4 API集成测试编写对话华为云码道:请使用fullstack-testing skill继续完成tasks中的任务 3.2.3:API集成测试编写。3.3.5 E2E测试编写对话华为云码道:请使用fullstack-testing skill继续完成tasks中的任务 3.2.4:E2E测试编写。3.3.6 本地测试执行与Bug修复对话华为云码道:请继续完成tasks中的任务 3.3.1:本地Windows环境测试执行与Bug修复。(插图位置14:测试执Bug修复总结:  Bug编号模块问题描述状态BUG-001选座模块自动选座并发超卖✅ 已修复BUG-002订单模块超时释放任务未执行✅ 已修复BUG-003前端座位图状态刷新延迟✅ 已修复测试执行结果:后端单元测试:77/77 通过 ✅前端单元测试:48/48 通过 ✅API集成测试:50/50 通过 ✅E2E测试:15/15 通过 ✅3.4 项目启动与验证3.4.1 启动后端服务在项目根目录 S:\Cinema Management\demo 执行:cmdmvn spring-boot:run成功启动标志:Started CinemaManagementApplication in 5.123 seconds3.4.2 启动前端服务在前端项目目录 S:\Cinema Management\demo\cinema-frontend 执行:cmdnpm run dev成功启动标志:Local: http://localhost:5173/四、案例总结4.1 案例阶段性总结本案例在本地 Windows PC 上搭建开发测试环境,以华为云 CodeArts 代码智能体为核心开发工具,结合 sdd-workflow、bug-fix-reporter、fullstack-testing 等技能,基于影院管理系统 SDD 设计文档,成功完成了影院管理系统的开发、测试与运行验证。实现了影院管理系统从"设计蓝图"到"可运行系统"的完整落地,让影院运营管理真正从"纸上谈兵"走向"实战落地"。4.2 交付成果清单  类别交付物数量后端代码Java源文件、配置文件70+前端代码Vue组件、Store、API封装50+测试代码单元测试、集成测试、E2E测试150+文档Sprint报告、Bug修复报告10+4.3 技术成果总结后端架构:Spring Boot 3.2.5 + MyBatis-Plus 3.5.66张核心数据表30+ RESTful API端点JWT认证 + 权限控制Redis缓存 + 分布式锁前端架构:Vue 3 + Vite + Pinia + Vue RouterAnt Design Vue UI组件库12个核心页面5个Pinia Store本案例中所涉及的影院管理系统的相关需求、设计等文档已上传至gitCode,请根据需要进行下载:项目源码地址: https://github.com/ajswjindjiw/Cinema-Management
  • [案例共创] CampFlow 训练营成果管理助手:CodeArts Agent 项目实践
    大家好,我本次训练营完成的项目是 **CampFlow 训练营成果管理助手**。这是一个面向华为云码道暑期实习训练营的 Web 工作台,用来帮助学生把在线学习、CodeArts Agent 辅助开发、项目构建、华为云部署、案例文档发布和最终作品链接提交这些分散任务整合到一个可追踪的流程中。## 一、项目背景在训练营实践过程中,我发现项目提交并不只是写出一个能运行的页面,还需要同时完成学习进度、CodeArts Agent 使用过程、项目部署、案例文档、附件材料和最终链接提交。任务节点比较分散,如果只靠临时记录,很容易出现材料遗漏、演示链接忘记回填、评分维度没有证据支撑等问题。因此我设计了 CampFlow,希望它既是一个可运行的训练营成果管理应用,也能反向辅助我整理最终提交材料。它把指导书中的评分维度和提交要求产品化,形成项目档案、里程碑、评分证据、智能体提示词和案例文档生成几个模块,让整个实习项目从开发到提交都更加清晰。## 二、作品链接作品演示地址:https://campflow-tj-20260726.obs-website.cn-east-3.myhuaweicloud.com/案例中心链接:https://devstation.connect.huaweicloud.com/space/devportal/casecenter/11272f6a85244aad99d738b32bac093c/2## 三、技术选型本项目采用纯静态前端方案,核心技术如下:- CodeArts Agent:辅助需求分析、架构设计、功能开发、测试部署和案例文档整理- HTML / CSS / JavaScript:实现页面结构、交互逻辑和响应式布局- localStorage:在浏览器本地保存项目档案、里程碑、评分证据和开发记录- 华为云 OBS:托管静态网站并提供公网访问地址- Node.js assert:对得分计算、数据模型和文档生成逻辑进行基础测试选择纯静态方案的原因是训练营项目更看重完整交付闭环。静态 Web 应用部署简单、依赖少、访问稳定,适合快速完成从代码构建到华为云部署的全过程。## 四、需求分析根据训练营指导书,项目成果需要包含可运行应用、案例文档、演示链接或视频,并且 Web 类应用需要部署到华为云。评分维度包括创新易用、功能完备、技术能力、文档完整性和参与度。围绕这些要求,我将需求拆成五个方向:1. 成果管理:记录项目名称、应用方向、技术栈、演示链接和案例链接。2. 过程管理:把学习、开发、部署、发布等训练营节点转化为里程碑。3. 智能体协作:自动生成适合 CodeArts Agent 的阶段性提示词。4. 评分证据:按评分维度整理证据项、完成状态、说明和链接。5. 文档发布:根据项目档案和证据清单生成案例 Markdown 草稿。这样做的好处是,项目不只是“做完一个页面”,而是把提交要求转化成了可以持续检查的工作流。## 五、系统架构设计CampFlow 的整体结构比较轻量:```text用户浏览器  ├─ index.html:应用入口  ├─ assets/styles.css:界面样式和响应式布局  ├─ assets/app.js:状态管理、评分计算、提示词生成和 Markdown 生成  └─ localStorage:保存项目档案、评分证据、里程碑和开发记录```项目没有引入后端服务,所有数据保存在浏览器本地。对于训练营展示场景来说,这种方案可以降低部署复杂度,也避免后端账号、数据库和接口联调带来的额外成本。## 六、CodeArts Agent 辅助开发过程本项目按照 vibe coding 的思路使用 CodeArts Agent。我的实践方式不是一次性让智能体直接生成全部代码,而是分阶段推进:第一阶段是需求分析。我先让 CodeArts Agent 根据指导书梳理项目目标、评分维度和必须交付的材料,避免项目范围跑偏。第二阶段是架构设计。我让智能体输出静态前端架构、本地存储数据模型,以及每个页面模块需要承担的职责。第三阶段是功能开发。根据模块拆分,逐步实现仪表盘、项目档案、提示词生成、评分证据、案例文档生成和部署清单。第四阶段是调试验证。重点检查评分计算是否符合权重、localStorage 是否能正常保存、Markdown 文档是否能完整生成、部署文件是否齐全。第五阶段是文档整理。最后让智能体辅助把开发过程、部署步骤、项目亮点和总结整理成案例中心与论坛都能使用的材料。通过这种分阶段协作,CodeArts Agent 更像一个项目搭档,而不是简单的代码生成器。它帮助我把任务拆小,也让我在每一步都有可检查的输出。## 七、核心功能介绍1. 仪表盘:展示预计得分、证据完成数量、里程碑完成数量,并按指导书权重拆解评分维度。2. 项目档案:维护项目名称、应用方向、真实问题、解决方案、技术栈、考试状态、演示链接和案例链接。3. CodeArts 提示词生成:根据项目当前状态生成需求分析、架构设计、功能开发、调试部署和案例文档五类提示词,方便继续与智能体协作。4. 评分证据清单:按照创新易用、功能完备、技术能力、文档完整性和参与度五个维度组织证据项,支持完成状态和说明记录。5. 案例文档生成器:把项目档案、评分证据和开发记录拼装成 Markdown 草稿,减少最终发布时遗漏章节的风险。6. 部署清单:列出静态网站部署需要上传的文件,并提醒检查 OBS 桶、静态网站首页、公开访问策略和演示链接。## 八、部署过程项目最终部署在华为云 OBS 静态网站托管上。部署步骤如下:1. 创建 OBS 桶 `campflow-tj-20260726`,区域选择华东-上海一 `cn-east-3`。2. 上传静态网站文件,根目录包含 `index.html`,`assets` 目录包含 `app.js` 和 `styles.css`。3. 开启静态网站托管,默认首页设置为 `index.html`。4. 创建桶策略 `campflow-public-read`,允许公网读取静态网站对象。5. 访问 OBS 静态网站地址,确认页面可以正常打开。验证结果:- 首页 HTTP 状态为 200- 页面内容包含 CampFlow- 静态网站公网地址可访问## 九、测试与验收项目包含基础逻辑测试,主要验证数据模型、评分计算和文档生成相关逻辑。测试通过后,我又进行了浏览器访问检查,确认页面能够在本地和 OBS 环境中正常运行。验收时重点检查了以下内容:- 页面能正常加载- 仪表盘数据能展示- 表单内容能保存到 localStorage- 提示词能够生成- 案例文档能够生成- OBS 演示链接能够公网访问- 案例中心附件 PDF 小于 20MB## 十、遇到的问题与解决方式第一个问题是提交材料分散。训练营要求包含代码、部署、案例文档、演示链接等内容,开始时容易只关注开发本身,忽略最终提交材料。因此我把这些要求做成了应用中的评分证据和部署清单。第二个问题是静态部署的公开访问配置。OBS 上传文件后,如果没有正确配置静态网站托管和公开读策略,外部访问会失败。最后通过设置默认首页 `index.html` 和桶策略 `campflow-public-read` 解决。第三个问题是论坛和案例中心链接类型不同。案例中心链接用于案例提交,OBS 链接用于作品演示,而论坛链接用于社区帖子展示。理解这三类链接的区别后,最终提交路径就清晰了。## 十一、项目总结CampFlow 是一次围绕训练营真实提交场景设计的小型工具实践。它不只是一个静态页面,而是把 CodeArts Agent 使用过程、评分标准、部署清单和案例文档整理流程放在同一个工作台里。通过这个项目,我完成了从需求分析、智能体辅助开发、本地测试、OBS 部署、案例中心提交到论坛发布材料整理的完整闭环。后续如果继续扩展,可以加入截图上传、多人协作、华为云登录和一键生成提交材料等能力,让它从个人训练营工具升级为更通用的项目交付助手。以上就是我的训练营项目实践分享,欢迎大家交流指正。
  • [案例共创] 用华为云码道构建 SoundScape:让音乐在浏览器中“看得见”
    用华为云码道构建 SoundScape:让音乐在浏览器中“看得见”一、概述1.1 案例介绍传统播放器只负责“播放声音”,SoundScape 则把声音变成实时画面:用户在浏览器中上传本地音频后,应用通过 Web Audio API 解码音频并持续采集频谱数据,再使用 Canvas 2D 绘制柱状、环形和球形三种可视化效果。低频能量、节拍变化和全频强度还会驱动粒子大小、速度、色相与画面节奏,实现音画同步的沉浸式体验。本案例以华为云码道(CodeArts)代码智能体为辅助开发工具,围绕“需求梳理、架构设计、核心引擎实现、页面联调、运行验收和生产构建”完成一个 Vue 3 单页应用。项目全部在浏览器端处理音频,不需要后端服务,也不会主动上传用户的音频文件。案例技术选型如下:华为云码道(CodeArts)代码智能体:辅助分析需求、理解代码、生成实现建议和排查问题。Vue 3 + Vite:构建组件化前端应用并提供开发、构建与预览能力。Web Audio API:完成音频解码、播放控制和实时频谱采集。Canvas 2D:完成频谱、拟 3D 球形点阵、粒子和氛围光效绘制。1.2 适用对象个人开发者高校学生Web 前端开发者对音频处理、数据可视化或创意编程感兴趣的开发者1.3 案例时间本案例总时长预计 90 分钟,不包含首次下载安装开发工具和依赖包所需时间。1.4 案例流程说明:使用码道梳理上传、播放、可视化、主题切换和截图等需求,形成验收标准;准备 Node.js 环境,安装项目锁定的 Vue 3 和 Vite 依赖;使用 AudioEngine 完成音频解码、播放状态管理和频谱数据采集;分析低频、中频、高频和整体强度,驱动频谱、粒子、色彩和节拍效果;联调文件上传、播放控制、模式切换、主题切换、拖拽旋转和截图下载;执行生产构建,检查 dist/ 静态文件并完成案例验收。1.5 资源总览本案例核心功能均使用浏览器原生能力,预计花费 0 元。如将构建产物部署到收费的云资源,请以控制台实时价格为准,并在体验结束后及时释放资源。资源名称规格或版本费用华为开发者空间云开发环境建议 2 vCPUs、4 GiB 及以上,Node.js 20.19+ 或 22.12+以页面展示为准华为云码道(CodeArts)代码智能体体验版或当前账号可用版本以页面展示为准Vue项目锁定版本 3.5.40免费Vite项目锁定版本 8.1.5免费Web Audio API、Canvas 2DChrome、Edge 等现代浏览器的原生能力免费二、环境和资源准备2.1 准备华为云码道开发环境登录华为开发者空间,按账号可用方式进入码道代码智能体或创建云开发环境。也可以在 Windows 本地安装码道 AI IDE 后打开项目目录 music-visualizer。在终端中检查 Node.js 和 npm:node --version npm --version Vite 8 要求使用 Node.js 20.19+ 或 22.12+。如果版本过低,请先切换到符合要求的 Node.js 版本,再安装依赖。2.2 安装项目依赖进入项目目录:cd music-visualizer npm cinpm ci 会严格按照 package-lock.json 安装依赖。安装完成后,可以执行以下命令核对顶层版本:npm list --depth=0 本案例验证时使用的顶层依赖如下:@vitejs/plugin-vue@6.0.8 vite@8.1.5 vue@3.5.402.3 使用码道上下文选择功能当希望码道只分析某个文件或目录时,可先在 AI IDE 中打开目标内容,再在对话框输入 #,选择 File 或 Folder 作为上下文。这样可以缩小分析范围,减少无关内容干扰。例如,选择 #Folder src/engine 后输入:请分析 #Folder src/engine 中音频数据到画面渲染的数据链路,重点检查: 1. AudioBufferSourceNode 的生命周期; 2. AnalyserNode 的参数是否合理; 3. requestAnimationFrame 渲染循环是否正确释放; 4. 节拍检测器和粒子池是否完整初始化。 请先给出问题清单,再给出最小修改建议,不要改动无关文件。本项目不依赖额外的项目级 skills 即可完成案例。如果团队已经配置研发流程或测试类 skills,也可以在需求拆分、代码审查和测试设计阶段按需启用。三、对话码道:构建 SoundScape 在线音乐可视化器3.1 明确项目需求与验收标准在编码前,先向码道描述产品目标和约束:请为一个浏览器端在线音乐可视化器整理需求和验收标准。 约束:Vue 3 + Vite;音频只在本地浏览器处理;不使用后端;使用Web Audio API采集频谱;使用Canvas 2D绘图。 功能:点击或拖拽上传音频、播放/暂停、进度跳转、三种可视化模式、四种主题、粒子效果、画面截图。 请按“功能需求、非功能需求、验收用例”输出,并标出浏览器兼容性和资源释放风险。根据当前项目实现,核心需求如下:编号需求验收标准FR-01本地音频加载可点击或拖拽选择浏览器支持解码的音频文件;界面显示歌曲文件名FR-02播放控制可播放、暂停,并显示当前时间和总时长FR-03进度跳转点击进度条后从目标位置继续播放FR-04多模式可视化可在柱状、环形和球形三种模式间切换FR-05多主题显示可在霓虹、星空、火焰和极光四种主题间切换FR-06音频驱动画面低、中、高频和整体强度能够影响色相、粒子大小、速度和画面尺度FR-07交互旋转加载音频后,可使用鼠标或触摸拖动画面,改变球形效果观察角度FR-08截图保存点击截图按钮后,可将当前 Canvas 保存为 PNG 文件NFR-01隐私性音频在浏览器本地读取和解码,不主动上传到服务器NFR-02资源管理组件卸载时停止动画、断开音频节点并关闭 AudioContext3.2 设计系统架构和数据流SoundScape 采用纯前端分层结构。Vue 组件负责用户交互与状态展示,音频引擎负责音频生命周期,渲染引擎负责逐帧绘图,特征分析与粒子系统作为独立模块被渲染引擎调用。本地音频文件 │ File.arrayBuffer() ▼ AudioContext.decodeAudioData() │ ▼ AudioBufferSourceNode ──▶ AnalyserNode ──▶ 浏览器扬声器 │ 每帧采集1024个频谱值 ▼ 低频 / 中频 / 高频 / 整体强度 │ │ ▼ ▼ 柱状 / 环形 / 球形 节拍与粒子系统 └─────────┬─────────┘ ▼ Canvas 2D数据链路全部位于用户浏览器内部。除非后续自行增加上传接口,否则音频内容不会进入云端。3.3 了解项目结构当前项目的主要目录如下:music-visualizer/ ├── public/ │ ├── favicon.svg │ └── icons.svg ├── src/ │ ├── assets/ │ │ ├── hero.png │ │ └── vite.svg │ ├── components/ │ │ ├── Player.vue │ │ ├── Toolbar.vue │ │ ├── Upload.vue │ │ └── Visualizer.vue │ ├── engine/ │ │ ├── audioEngine.js │ │ ├── particleSystem.js │ │ ├── renderEngine.js │ │ └── themeManager.js │ ├── App.vue │ └── main.js ├── index.html ├── package-lock.json ├── package.json └── vite.config.js文件职责src/App.vue组合主界面,维护播放状态、进度、当前模式和主题,处理文件选择与截图src/components/Visualizer.vue挂载 Canvas,创建和释放渲染引擎,转发模式、主题及拖拽事件src/engine/audioEngine.js解码音频,创建播放源,管理播放、暂停、跳转和频谱数据src/engine/themeManager.js定义四套主题,提取频段特征,检测节拍并估算 BPM 与情绪标签src/engine/particleSystem.js使用固定对象池生成、更新和绘制粒子src/engine/renderEngine.js驱动动画循环,绘制柱状、环形、球形、粒子和背景光效当前运行入口把上传、播放控制和工具栏直接组合在 App.vue 中,只实际挂载 Visualizer.vue。Player.vue、Toolbar.vue 和 Upload.vue 是预留的拆分组件,当前版本未被 App.vue 导入。理解这一点可以避免修改了未挂载组件却看不到页面变化。3.4 实现音频加载和频谱采集AudioEngine.init() 在第一次加载文件时创建 AudioContext 和 AnalyserNode:init() { if (this.ctx) return const AC = window.AudioContext || window.webkitAudioContext if (!AC) return this.ctx = new AC() this.analyser = this.ctx.createAnalyser() this.analyser.fftSize = 2048 this.analyser.smoothingTimeConstant = 0.8 this.analyser.minDecibels = -90 this.analyser.maxDecibels = -10 this.analyser.connect(this.ctx.destination) this.frequencyData = new Uint8Array(this.analyser.frequencyBinCount) this.timeDomainData = new Uint8Array(this.analyser.frequencyBinCount) } 当 fftSize 为 2048 时,frequencyBinCount 为 1024。smoothingTimeConstant 设置为 0.8,可以减少相邻帧之间的突变,使画面更连贯。加载文件时,应用通过 File.arrayBuffer() 读取本地数据,再调用 decodeAudioData() 得到 AudioBuffer:async load(file) { this.init() if (!this.ctx) throw new Error('Web Audio API not supported') this._stopSource() try { const arrayBuffer = await file.arrayBuffer() this.buffer = await this.ctx.decodeAudioData(arrayBuffer) this.pauseOffset = 0 this.playing = false } catch (e) { this.buffer = null this.playing = false throw e } } AudioBufferSourceNode 只能启动一次,因此播放、跳转或重新播放时必须新建播放源。项目使用 pauseOffset 保存暂停位置,并使用 _generation 避免旧播放源的 onended 回调覆盖新播放状态。3.5 将音频特征映射为视觉参数themeManager.js 将频谱数组划分为低频、中频和高频,并计算整体强度指标:const bassEnd = Math.max(1, Math.floor(len * 0.1)) const midEnd = Math.max(bassEnd + 1, Math.floor(len * 0.5)) const bassAvg = bassSum / bassEnd / 255 const midAvg = midSum / (midEnd - bassEnd) / 255 const highAvg = highSum / (len - midEnd) / 255 const rms = Math.sqrt(totalSum / len) / 255 特征与画面参数的映射关系如下:音频特征视觉反馈低频平均值 bassAvg增大粒子尺寸;超过阈值时参与节拍判定并触发粒子爆发中频平均值 midAvg在当前主题基础上偏移色相高频平均值 highAvg提高粒子速度并改变色相整体强度 rms调整粒子数量、透明度、饱和度和环境光尺度四套主题只提供基础色彩和背景,实时音频特征会继续改变视觉参数:主题键显示名称基础风格neon霓虹品红与青色,深蓝黑背景starry星空蓝色系,深空背景flame火焰橙红色系,深棕黑背景aurora极光绿色与蓝色,深绿背景3.6 构建三种可视化模式与粒子系统RenderEngine 使用 requestAnimationFrame() 驱动绘制。每一帧先采集频谱,再进行特征分析、背景绘制、主模式绘制和粒子更新:loop() { if (!this.running) return this.render() this.animId = requestAnimationFrame(() => this.loop()) } render() { const freq = this.audio.getFrequencyData() if (!freq || !this.audio.buffer) { this.drawIdleBackground(this.w, this.h) return } const features = analyzeFeatures(freq) const params = adaptVisualParams(features, this.theme) if (this.mode === 'bars') this.drawBars(freq, params, features) else if (this.mode === 'circular') this.drawCircular(freq, params, features) else this.drawSphere(freq, params, features) } 三种模式的实现重点如下:模式实现方式主要参数柱状 bars对数映射频谱区间,绘制上下对称的渐变柱和倒影64 根频谱柱、逐帧平滑环形 circular将频谱值映射到圆周,向内外绘制径向线段120 根径向频谱线球形 sphere使用黄金角在单位球面生成点阵,经旋转与深度计算投影到二维 Canvas900 个球面点、邻近点连线粒子系统预先创建 600 个 Particle 对象,并循环复用对象池,避免在高频动画循环中持续创建和回收对象。检测到明显低频节拍时,渲染引擎会在画面中心额外发射一组高速粒子。3.6.1 运行前代码核对当前源码中的 RenderEngine 已导入 BPMDetector,并在渲染阶段调用 this.bpmDetector.update(),但构造函数尚未创建其实例。播放音频前,需要在 src/engine/renderEngine.js 的构造函数中补充以下一行:constructor(canvas, audioEngine) { this.canvas = canvas this.ctx = canvas.getContext('2d') this.audio = audioEngine this.particles = new ParticleSystem(600) this.bpmDetector = new BPMDetector() // 其余初始化代码保持不变 } 如果未补充该行,音频加载后执行到 this.bpmDetector.update(beat) 时会出现 TypeError,动画循环随即中断。可将当前文件作为上下文交给码道,让代码智能体检查“导入、实例化、使用、释放”是否形成完整闭环。3.7 完成页面交互和截图下载主界面由全屏 Canvas 和底部控制栏组成:未加载音频时,页面中央显示点击或拖拽上传区域;加载成功后,顶部显示去除扩展名的歌曲名;底部控制栏显示播放/暂停、当前时间、总时长和进度条;右侧提供三种模式、四种主题和截图按钮;鼠标或触摸拖动 Canvas 时,渲染引擎更新旋转角度;点击截图按钮后,调用 canvas.toDataURL('image/png') 下载当前画面。截图功能的核心代码如下:function screenshot() { const canvas = visualizer.value?.getCanvas() if (!canvas) return const link = document.createElement('a') link.download = `soundscape-${Date.now()}.png` link.href = canvas.toDataURL('image/png') link.click() } 3.8 运行项目并完成功能验收在项目根目录执行:npm run dev -- --host 0.0.0.0本地开发通常访问终端输出的 http://localhost:5173/。如果使用云开发环境,请通过环境提供的端口转发或预览入口访问 5173 端口,不要直接暴露不必要的公网端口。按以下顺序进行人工验收:步骤操作预期结果1打开页面显示深色背景、上传区域和底部模式/主题按钮2上传浏览器支持的 MP3、WAV 或 OGG 文件上传区域消失,显示歌曲名并自动开始播放3点击播放/暂停按钮播放状态正确切换,时间显示同步变化4点击进度条不同位置播放位置跳转,画面继续响应音频5依次切换柱状、环形和球形三种画面均能持续渲染,无空白或明显卡顿6依次切换四种主题背景和主色调立即变化7在球形模式拖动画面球体观察角度随拖拽变化8点击截图按钮浏览器下载名称形如 soundscape-时间戳.png 的图片9刷新或关闭页面动画停止,音频上下文和节点被释放如果文件无法播放,首先打开浏览器开发者工具查看控制台,并检查:文件是否为浏览器实际支持的编码格式,而不仅是扩展名符合要求;是否已按 3.6.1 节初始化 BPMDetector;浏览器是否允许当前页面创建或恢复 AudioContext;当前 Node.js 版本是否满足 Vite 8 的要求。3.9 执行生产构建功能验收通过后,执行:npm run build构建成功后,Vite 会在 dist/ 目录生成 index.html、CSS、JavaScript 和公共静态资源。当前项目已验证能够通过 Vite 8.1.5 完成生产构建,终端会显示类似以下结果:✓ 19 modules transformed. ✓ built in ...ms使用本地静态服务器预览生产构建:npm run preview -- --host 0.0.0.0四、案例总结与资源释放4.1 案例阶段性总结通过本案例,已经完成一条可复用的浏览器音频可视化链路:使用 Vue 3 组织应用状态、文件上传和交互界面;使用 Web Audio API 解码本地音频,并通过 AnalyserNode 提供实时频谱;使用 Canvas 2D 实现柱状、环形和拟 3D 球形三种效果;使用频段特征和节拍检测驱动色彩、粒子、光效及 BPM 情绪标签;使用对象池和 requestAnimationFrame() 控制实时绘制开销;使用 Vite 完成开发调试、生产构建与静态预览。码道在本案例中承担需求细化、上下文聚焦、代码链路检查和问题定位等辅助工作。开发者仍需以实际源码、浏览器运行结果和验收用例为依据,核对智能体建议后再实施修改。4.2 释放资源本案例默认不创建收费云资源。完成体验后:在运行 Vite 的终端中按 Ctrl+C 停止开发或预览服务器;如果使用华为开发者空间云开发环境,可按实际需要停止或删除不再使用的环境;如果自行部署到对象存储、CDN 或云服务器,请根据对应产品说明释放收费资源;关闭页面时,应用会在组件卸载流程中调用 audio.destroy(),停止播放源并关闭 AudioContext。五、扩展资料说明5.1 可继续完善的功能在 AudioEngine 中增加 GainNode,实现真正的音量调节;为解码失败、超大文件和不支持的编码增加可见错误提示;增加单元测试和端到端测试,覆盖暂停、跳转、源节点重建和截图下载;将复杂特征分析迁移到 Web Worker,或使用 OffscreenCanvas 降低主线程压力;在高性能版本中评估 WebGL,但当前项目实际渲染后端为 Canvas 2D;将 dist/ 部署到静态网站托管,并按需接入 HTTPS 与 CDN;增加移动端布局、键盘无障碍操作和截图分享能力。5.2 扩展学习资料华为开发者空间
  • [训练营] 基于HTML5的单词闯关学习系统
    一、案例介绍1.1 案例流程本次项目为期两周,依托华为开发者空间及华为云码道(CodeArts)代码智能体,完成"单词闯关"Web应用的全流程开发。具体日程安排如下:          1.2  适用对象                        ·高校学生                       ·个人开发者        1.3 资源总览                              本案例预计花费39元(使用训练营代金券)  资源名称规格单价(元) 华为云码道代码智能体基础版39         二、环境和资源准备华为云码道(CodeArts)代码智能体:集代码大模型、AI IDE、Code Agent为一体的智能编码产品。具  备强大的需求理解、架构设计和代码生成能力,支持智能体模式自动规划并执行复杂开发任务。本案例中作为开发平台,通过对话式交互快速完成固定资产管理系统的需求分析、架构设计和SDD文档生成。AI IDE华为云码道开发环境搭建本次实习使用华为开发者空间提供的云开发环境(ARM | 4 vCPUs 8GB | Ubuntu 24.04 Server定制版),配合华为云码道(CodeArts)代码智能体进行辅助开发。CodeArts代码智能体能够根据自然语言描述自动生成代码、定位Bug、解释代码逻辑,显著提升了开发效率。项目采用纯前端技术栈,无需后端服务器,使用HTML5 + CSS3 + JavaScript(ES6)开发,数据存储使用浏览器localStorage,无需数据库依赖。项目通过本地文件系统直接运行,使用浏览器打开index.html即可体验完整功能。CodeArts辅助开发工具在整个开发过程中,华为云码道(CodeArts)代码智能体发挥了关键作用,主要体现在以下几个方面:(1)需求理解与架构设计:通过自然语言描述项目需求("2D背单词闯关游戏,结合搜打撤地图玩法"),CodeArts能够快速理解需求并生成项目目录结构、模块划分建议。例如,它建议将项目拆分为data(数据层)、js(逻辑层)、css(样式层)、assets(资源层)四个核心目录,实践证明这一划分清晰合理。(2)代码生成与迭代:CodeArts根据功能描述直接生成模块代码。以地图生成模块为例,描述"动态生成10×10地图,30%概率生成墙壁,BFS验证起点到终点可达性"后,CodeArts生成了完整的generateMap()函数,包含墙壁随机放置、BFS可达性检测、不可达时逐步移除墙壁等逻辑。后续迭代中,发现直接清空所有墙壁会导致无墙地图的问题,CodeArts准确识别了这一Bug并修复为逐步移除策略。(3)Bug定位与修复:开发过程中遇到多个典型Bug,CodeArts均能快速定位根因。例如:箱子搜索动画期间拖拽物品会重复触发事件监听器导致物品复制,CodeArts识别出setupBoxDrop()被重复调用的问题,引入boxDropInitialized标志防止重复绑定;背包中同ID物品的removeItem()会误删所有实例,CodeArts提出使用唯一实例ID(uid)替代直接存储itemId的方案,从根本上解决了冲突问题。(4)性能优化:当页面出现卡顿时,CodeArts分析出两个性能瓶颈——render()函数在按键长按时每秒触发30-40次全量重绘,以及墙壁查找使用Array.some()导致O(n)复杂度。它给出了requestAnimationFrame帧节流和Set数据结构优化的解决方案,有效改善了页面流畅度。三、项目介绍3.1 项目简介本次开发采用HTML5 Canvas(地图渲染)+ Web前端技术(HTML/CSS/JS)+ 华为云码道CodeArts代码智能体(辅助开发),这是一款将英语词汇学习与2D地图探索游戏相结合的Web应用,采用"搜打撤"(搜索-打击-撤离)玩法,让背单词变得有趣且富有挑战性。以下是核心功能:核心功能说明背单词支持雅思/GRE两套词书,Fisher-Yates算法随机打乱顺序,浏览式学习,完成当日任务后解锁地图游戏地图游戏10×10动态生成地图,BFS保证可达性,WASD操控角色移动,探索保险箱、走向撤离点双保险箱普通保险箱(直接搜索开启)与密码保险箱(需答5道单词题,正确率≥60%方可开启,稀有度更高)搜索动画打开保险箱时物品逐个搜索揭示,灰色底+旋转加载图标,每800ms揭示一个背包系统6×6网格,支持不同尺寸物品(1×1到3×3),拖拽拾取/丢弃/重排,双击自动拾取,碰撞检测收藏品70种收藏品(紫色普通29种/金色稀有30种/红色传说11种),带PNG图片和slots二维数组描述形状仓库展示撤离成功后收藏品持久化到仓库,按稀有度分类展示,未收集的显示"???"统计今日学习数、连续学习天数、总计学习数操作流程1. 在"设置"页选择词书和每日数量2. 在"背单词"页完成当日学习任务3. 进入"地图游戏",WASD移动角色探索地图4. 走到保险箱自动打开搜索界面,拖拽物品到背包拾取5. 走到密码保险箱需答题开锁,获取更高稀有度物品6. 到达EXIT撤离点完成游戏,背包物品存入仓库3.2 系统架构设计本应用采用模块化前端架构,各模块职责清晰、松耦合协作。系统架构如下:├── index.html          // 主页面,含所有模态框HTML结构├── css/│   └── style.css       // 全局样式(网格/拖拽/搜索动画/稀有度配色)├── js/│   ├── data.js         // 数据加载模块(fetch JSON词库与收藏品)│   ├── storage.js      // localStorage持久化管理│   ├── settings.js     // 设置模块(词书选择/每日数量)│   ├── learn.js        // 背单词模块(Fisher-Yates随机/浏览式学习)│   ├── game.js         // 地图游戏核心(地图生成/移动/保险箱/答题)│   ├── backpack.js     // 背包系统(6×6网格/uid实例管理/碰撞检测/拖拽)│   ├── warehouse.js    // 仓库展示模块│   ├── stats.js        // 统计模块│   └── app.js          // 主应用逻辑(页面导航/模块初始化)├── data/│   ├── ielts.json      // 雅思词库(100词)│   ├── gre.json        // GRE词库(100词)│   └── collections.json // 收藏品数据(70项,含slots二维数组)└── assets/             // 70个PNG收藏品图片 + 2个保险箱图片数据流设计:词库数据通过fetch异步加载,收藏品数据包含slots二维数组描述物品在背包网格中的占用形状。游戏状态(地图、背包、保险箱)在单次游戏会话中维护,撤离成功后背包物品通过localStorage持久化到仓库。3.3 核心功能实现本应用"单词闯关"成功将英语词汇学习与2D地图探索游戏相结合,通过"搜打撤"玩法(搜索保险箱→答题开锁→拾取收藏品→安全撤离)将枯燥的背单词过程转化为有趣的游戏体验。核心技术方案包括:(1)模块化前端架构:9个JS模块各司其职,数据层(data.js/storage.js)与逻辑层(learn.js/game.js/backpack.js)分离,便于维护和扩展。(2)uid唯一实例ID机制:解决了背包系统中同ID物品共存的核心难题,是整个背包系统稳定运行的基石。(3)BFS地图生成算法:保证地图可达性的同时保留足够的墙壁和障碍,提供良好的探索体验。(4)双保险箱设计:普通保险箱与密码保险箱的差异化管理(开启方式、稀有度权重、物品数量)增加了游戏策略深度。(5)华为云码道(CodeArts)代码智能体辅助开发:从需求理解到Bug修复,CodeArts贯穿开发全流程,显著提升了开发效率和代码质量。3.2.1 背单词模块背单词模块采用浏览式学习交互,用户点击"记住了"按钮依次浏览当日单词。单词顺序使用Fisher-Yates洗牌算法随机打乱,确保每次学习顺序不同。词库支持雅思和GRE两套词书,切换词书时自动重置今日单词列表。完成当日学习任务后方可进入地图游戏,将学习与游戏形成正向激励闭环。以下是随机词序的代码模块:// learn.js — Fisher-Yates洗牌shuffleArray(array) {    for (let i = array.length - 1; i > 0; i--) {        const j = Math.floor(Math.random() * (i + 1));        [array[i], array[j]] = [array[j], array[i]];    }    return array;}3.2.2 地图游戏模块地图游戏是本应用的核心玩法,采用"搜打撤"(搜索-打击-撤离)模式。关键技术点包括:(1)动态地图生成:10×10网格,30%概率随机生成墙壁。使用BFS(广度优先搜索)验证起点(0,0)到终点(9,9)的可达性,若不可达则逐步移除墙壁直至可达,避免直接清空所有墙壁导致地图无遮挡。(2)保险箱系统:地图上分布两种保险箱——普通保险箱(灰色,直接搜索开启)和密码保险箱(金棕色,需答5道单词题且正确率≥60%方可开启)。密码保险箱的收藏品稀有度更高(权重:普通40/稀有45/传说15 vs 普通60/稀有30/传说10),且物品数量更多(3-4个 vs 2-3个)。保险箱开启后保留在地图上,玩家可返回拾取遗漏物品。(3)搜索动画:打开保险箱时,物品逐个"搜索"呈现——未搜索的物品显示灰色底色加白色旋转加载图标,每800ms揭示一个物品,搜索完成后才可拖拽拾取。这一设计增强了游戏的沉浸感和期待感。以下是核心代码:// game.js — 地图生成核心代码generateMap() {    const size = 10;    this.state.map = { size: size };     const walls = new Set();    for (let y = 0; y < size; y++) {        for (let x = 0; x < size; x++) {            if (Math.random() < 0.3 && !(x === 0 && y === 0)) {                walls.add(`${x},${y}`);            }        }    }     const exit = { x: size - 1, y: size - 1 };    walls.delete(`${exit.x},${exit.y}`);     // BFS验证可达性,不可达则逐步移除墙壁    let attempts = 0;    while (!this.isReachable(0, 0, exit.x, exit.y, walls, size) && attempts < 200) {        const wallArray = Array.from(walls);        if (wallArray.length === 0) break;        const randomWall = wallArray[Math.floor(Math.random() * wallArray.length)];        walls.delete(randomWall);        attempts++;    }     // 在可达区域随机放置保险箱    const reachable = this.getReachableCells(0, 0, walls, size);    const normalBoxCount = 3 + Math.floor(Math.random() * 3);    const quizBoxCount = 2 + Math.floor(Math.random() * 2);    // ... 放置逻辑省略     this.state.walls = Array.from(walls).map(key => {        const [x, y] = key.split(',').map(Number);        return { x, y };    });    this.state.boxes = boxes;    this.state.exit = exit;    this.buildWallSet();  // 预构建Set用于O(1)查找}3.2.3 背包系统背包系统是本应用最复杂的模块,参考"三角洲行动"的物品管理系统设计,关键技术难点及解决思路如下:(1)网格碰撞检测:背包为6×6网格,每个收藏品有不同尺寸(1×1到3×3),用slots二维数组描述占用形状。canPlace()函数遍历slots数组,检查目标区域所有格子是否均未被占用且不越界。(2)唯一实例ID管理:这是开发过程中遇到的核心技术难点。最初背包网格直接存储itemId,当两个同ID物品同时存在于背包时,removeItem()按ID删除会误删所有同ID实例,导致物品消失或数据错乱。解决方案是引入uid(唯一实例ID)机制——每次placeItem()时生成全局递增的uid,网格存储uid而非itemId,通过_uidMap(Map数据结构)映射uid到itemId。removeItem()按uid删除,精确移除单个实例,彻底解决同ID物品冲突问题。(3)拖拽交互:支持从保险箱拖拽物品到背包(拾取)、从背包拖拽物品到保险箱(丢弃)、背包内拖拽重排。拖拽时通过dataTransfer传递uid、itemId、context(来源标识)和originRow/originCol(原始位置),目标区域根据context判断操作类型。双击保险箱物品可自动拾取(autoPlace自动寻找空位)。(4)事件监听器重复绑定问题:在搜索动画期间,refreshLootUI()会重建DOM并重新绑定事件监听器。setupBoxDrop()对保险箱容器添加drop事件监听,若每次刷新都重新绑定,会导致同一容器上叠加多个监听器,拖拽丢弃时触发多次从而复制物品。解决方案是引入boxDropInitialized标志,确保drop监听器只绑定一次。以下是核心代码:// backpack.js — uid实例管理核心代码const Backpack = {    GRID_SIZE: 6,    CELL_PX: 50,    _uidCounter: 0,    _uidMap: new Map(),          // uid -> itemId 映射     getItemId(uid) {        return this._uidMap.get(uid) || null;    },     placeItem(grid, itemId, row, col) {        const item = DataManager.getCollection(itemId);        if (!item) return false;        if (!this.canPlace(grid, item, row, col)) return false;        const uid = ++this._uidCounter;       // 生成唯一实例ID        this._uidMap.set(uid, itemId);         // 建立映射        const slots = item.slots;        for (let r = 0; r < slots.length; r++) {            for (let c = 0; c < slots[r].length; c++) {                if (slots[r][c] === 1) {                    grid[row + r][col + c] = uid;  // 网格存uid而非itemId                }            }        }        return uid;    },     removeItem(grid, uid) {        for (let r = 0; r < this.GRID_SIZE; r++) {            for (let c = 0; c < this.GRID_SIZE; c++) {                if (grid[r][c] === uid) {                    grid[r][c] = null;        // 按uid精确删除,不影响同ID其他实例                }            }        }        this._uidMap.delete(uid);    },     getItemsInGrid(grid) {        const items = [];        const seen = new Set();        for (let r = 0; r < this.GRID_SIZE; r++) {            for (let c = 0; c < this.GRID_SIZE; c++) {                const uid = grid[r][c];                if (uid !== null && !seen.has(uid)) {                    seen.add(uid);                    const itemId = this._uidMap.get(uid);                    if (itemId !== undefined) items.push(itemId);                }            }        }        return items;    }};3.2.4 收藏品系统收藏品数据基于assets文件夹中的70个PNG图片文件定义,每项包含id、name、rarity(common/rare/legendary)、width、height、slots二维数组、image文件名和description。稀有度对应三种颜色边框:紫色(普通)、金色(稀有)、红色(传说)。物品在背包和仓库中均显示对应的PNG图片,而非文字名称。四、性能优化开发后期页面出现明显卡顿,经分析发现两个性能瓶颈并逐一解决:(1)渲染帧节流:原render()函数在每次按键移动时直接调用,长按方向键时每秒触发30-40次全量Canvas重绘。引入scheduleRender()方法,使用requestAnimationFrame将渲染调用合并到浏览器刷新周期,确保每帧最多重绘一次,显著降低CPU占用。(2)墙壁查找优化:原实现使用Array.some()遍历墙壁数组判断某格是否为墙,对于10×10地图每帧需100次查找,每次O(n)复杂度。改为在地图生成时构建Set数据结构(_wallSet),查找复杂度降为O(1),render()和movePlayer()均受益。五、技术难点与解决思路5.1 背包同ID物品冲突问题描述:当保险箱中刷出与背包中已有物品相同ID的收藏品时,双击拾取后物品消失;拖拽丢弃时物品被大量复制。根因分析:背包网格直接存储itemId,removeItem()按itemId遍历删除所有匹配格子。当两个同ID物品共存时,删除操作会误删另一个实例的所有格子,导致数据错乱。解决方案:引入uid(唯一实例ID)机制。每次placeItem()生成全局递增uid存入网格,通过Map映射uid→itemId。removeItem()改为按uid精确删除单个实例,getItemsInGrid()按uid去重后映射回itemId列表。此方案从数据模型层面彻底解决了同ID物品冲突,所有上层操作(拖拽、双击、丢弃)无需特殊处理。5.2 事件监听器重复绑定问题描述:将背包物品拖拽到保险箱丢弃时,物品被复制出多份。根因分析:refreshLootUI()每次调用时重建DOM并重新调用setupBoxDrop()绑定drop事件。由于drop监听器绑定在容器元素上(而非子元素),innerHTML重建子元素不影响容器上的监听器,导致每次刷新叠加一个新监听器,拖拽时触发N次回调。解决方案:引入boxDropInitialized状态标志,setupBoxDrop()首次绑定后设为true,后续调用直接返回,确保drop监听器只绑定一次。5.3 地图可达性保证问题描述:随机生成墙壁后,起点到终点可能不可达;简单清空所有墙壁会导致无遮挡的空旷地图。解决方案:使用BFS检测可达性,若不可达则随机移除一面墙壁,重复检测直到可达。设置200次上限防止死循环。此策略在保证可达性的同时最大程度保留墙壁,维持地图的探索性。5.4 Canvas渲染性能问题描述:页面操作时出现明显卡顿,尤其在长按方向键移动角色时。解决方案:①使用requestAnimationFrame将render()调用合并到浏览器刷新周期,避免同一帧内多次重绘;②将墙壁数据从Array改为Set,查找复杂度从O(n)降为O(1);③在地图生成时预构建wallSet,避免每次render重复计算。六、扩展资料6.1 源码仓库GitCode 公开仓库 lowfllly/huawei_internship默认分支:main6.2 开源内容边界公开仓库提供复现本案例所需的应用源码、测试、部署脚本和设计文档;训练营内部培训材料、个人凭据、本地开发工具配置及运行期数据按 .gitignore 与安全要求不纳入仓库。评审时建议先体验公网环境,再对照仓库中的实现、测试和设计文档核验关键功能。
总条数:792 到第 页
上滑加载中