• 基于华为云码道(CodeArts)代码智能体的CloudForum:支持版块级权限与双层内容审核的校园论坛管理系统
    一、项目简介本次实战我使用华为云码道代码智能体完成了 CloudForum 校园论坛管理系统。项目围绕“会员交流、版主自治、平台治理”三个角色展开,不仅实现了登录、发帖、跟帖、删帖、置顶等论坛基础功能,还补充了版块级权限隔离、本地敏感词 DFA、华为云文本内容审核、人工复核、黑名单、软删除恢复和审计日志,形成了可运行、可管理、可追溯的内容治理闭环。代码仓库:CampusCloudForum(GitCode)前端:Vue 3 + TypeScript + Vite + Element Plus + Pinia + Vue Router + Axios后端:Java 17 + Spring Boot 3 + Spring Security + JWT + MyBatis-Plus数据库与运行:MySQL 8 + Docker Compose + NginxCloudForum 首页二、原始任务与完成情况原题为:论坛管理。实现论坛的版主管理、版块管理、内容管理。需要登陆进入论坛,可以发帖、跟帖和删帖以及置顶等功能。同时能够对敏感词汇进行过滤,拉黑某些会员。我将原题拆成了可验收的功能项,并为每项建立“页面操作 + 后端权限 + 自动化测试”的证据闭环:原题要求实现方式对应证据登录进入论坛JWT 无状态认证、BCrypt 密码、注册、退出、修改密码、禁用账号拦截登录页、认证测试版主管理ADMIN 分配或移除版主;MODERATOR 只能管理被分配版块版块管理页、版主范围页、跨版块 403 测试版块管理创建、编辑、启用、停用、排序、版主列表版块管理页、管理接口测试内容管理帖子/回复分页管理、审核、锁定、删除、恢复审核页、帖子管理页、回复管理页发帖登录会员选择版块并发布,发布前完成黑名单和敏感词审核发帖接口与集成测试跟帖帖子详情页回复,锁帖后禁止回复帖子详情页、回复测试删帖作者或对应管理者可删除;默认软删除,可恢复删除/恢复测试、审计日志置顶ADMIN 或对应版主可置顶/取消置顶,置顶内容优先排序帖子管理页、排序测试敏感词过滤DFA 支持 REJECT、REVIEW、REPLACE,词库动态重载敏感词页、审核队列、四类审核测试拉黑会员全局/版块、永久/限时、解除拉黑;发帖和回复前后端拦截黑名单页、拉黑权限与拦截测试三、码道代码智能体开发实录码道项目与原始任务任务规划与阶段拆分Skill / MCP 使用记录自动化验证我还在仓库中沉淀了项目级规则、阶段 Prompt 和专项 Skill,使智能体后续修改都遵循“读代码 → 实现最小闭环 → 测试 → 文档”的流程,减少前后端契约漂移与权限遗漏。四、系统架构与业务闭环整体架构保持前后端分离,本地容器化运行时由 Nginx 提供统一入口:会员 / 版主 / 管理员 │ ▼ Nginx + Vue 3 Web │ RESTful JSON ▼ Spring Security + JWT │ ├── 论坛业务服务 ── MyBatis-Plus ── MySQL 8 ├── 版块级 RBAC ── 403 越权拦截 ├── 本地敏感词 DFA ── PASS / REVIEW / BLOCK ├── 华为云 Moderation SDK ── 异常时安全降级 └── 审计日志 ── 操作者 / 原因 / 前后状态发帖和回复走统一治理链路:提交内容 → 校验是否被全局或当前版块拉黑 → 本地 DFA 过滤(REJECT / REVIEW / REPLACE) → 按配置调用华为云文本内容审核 → 统一得到 PASS / REVIEW / BLOCK → PASS 公开、REVIEW 进入人工队列、BLOCK 拦截 → 云审核异常时降级到本地结果并记录日志这种设计解决了两个真实问题:一是减轻版主逐条审查的压力;二是避免外部审核服务短暂不可用时整个论坛无法发帖。五、逐项功能实现1. 登录进入论坛系统支持注册、登录、退出和修改密码。登录成功后前端携带 JWT 访问需要授权的接口;密码使用 BCrypt 存储。公开浏览与登录后操作边界由 Spring Security 后端统一控制,匿名发帖返回 401,角色越权返回 403。登录页面注册页面关键安全配置使用精确的数字详情路径,避免把 /api/topics/mine 一类私有接口误判成公开接口:.authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/actuator/health").permitAll() .requestMatchers("/api/boards/all").permitAll() .requestMatchers(new RegexRequestMatcher("^/api/boards/\\d+$", "GET")).permitAll() .requestMatchers(HttpMethod.GET, "/api/topics").permitAll() .requestMatchers(new RegexRequestMatcher("^/api/topics/\\d+$", "GET")).permitAll() .requestMatchers(HttpMethod.GET, "/api/comments").permitAll() .anyRequest().authenticated()) 2. 版主管理管理员可以在版块管理页为每个版块分配或移除版主。后端不只判断用户是不是 MODERATOR,还会继续查询“用户—版块”的关联关系;因此版主即使手工构造请求,也不能管理其他版块。核心权限逻辑如下:public boolean canManageBoard(Long userId, Long boardId) { User user = requireUser(userId); if (user.getRole() == UserRole.ADMIN) return true; if (user.getRole() != UserRole.MODERATOR || boardId == null) return false; return boardModeratorMapper.selectCount( new LambdaQueryWrapper<BoardModerator>() .eq(BoardModerator::getUserId, userId) .eq(BoardModerator::getBoardId, boardId) ) > 0; } public void requireBoardManager(Long userId, Long boardId) { if (!canManageBoard(userId, boardId)) { throw BusinessException.forbidden("无权管理该版块"); } } ADMIN 获得全局管理范围,MODERATOR 只获得被分配的版块 ID,MEMBER 没有后台管理权限。帖子、回复、审核、黑名单和审计列表都复用这套后端判定。3. 版块管理系统实现了版块的创建、编辑、启用、停用、排序和版主配置。停用版块不能继续发帖;公开端和管理端使用不同的数据接口,管理接口通过方法级鉴权限制到 ADMIN 或 MODERATOR,并在服务层进一步做版块范围校验。@PostMapping @PreAuthorize("hasRole('ADMIN')") public ApiResponse<BoardDTO> createBoard( @Valid @RequestBody CreateBoardRequest request, @AuthenticationPrincipal UserPrincipal principal) { return ApiResponse.success(boardService.createBoard(request, principal.getId())); } @PutMapping("/{id}") @PreAuthorize("hasAnyRole('ADMIN','MODERATOR')") public ApiResponse<BoardDTO> updateBoard( @PathVariable Long id, @Valid @RequestBody UpdateBoardRequest request, @AuthenticationPrincipal UserPrincipal principal) { return ApiResponse.success(boardService.updateBoard(id, request, principal.getId())); } 4. 发帖与跟帖登录会员可以选择启用中的版块发布帖子,并在帖子详情页回复。发帖与回复都会先检查黑名单,再进入内容审核。帖子支持点赞、浏览量、回复数和最后活跃时间,回复可选填图片地址;锁帖后不允许继续回复。前端通过类型化 API 调用后端,页面不使用 mock 数据冒充功能:export function createTopic(data: { boardId: number title: string content: string }) { return api.post<any, ApiResponse<TopicInfo>>('/topics', data) } export function createComment(data: { topicId: number content: string imageUrl?: string }) { return api.post<any, ApiResponse<CommentInfo>>('/comments', data) } 公开帖子列表在后端固定过滤为 PUBLISHED + PASS,待审、被拒绝或已删除内容不会因修改前端参数而泄露:wrapper.eq(Topic::getStatus, TopicStatus.PUBLISHED); wrapper.eq(Topic::getReviewStatus, ReviewStatus.PASS); wrapper.orderByDesc(Topic::getIsTop); 5. 删帖、恢复、置顶与锁帖作者可以删除自己的帖子,对应版主和管理员可以执行管理删除。删除不是直接清除数据库记录,而是记录 DELETED、删除人、时间和原因;后续可由合法操作者恢复。置顶、取消置顶、锁定、解锁、删除和恢复都会写入审计日志。软删除和审计的关键实现:public void deleteTopic(Long id, Long operatorId, String reason) { Topic topic = topicMapper.selectById(id); if (topic == null) throw BusinessException.notFound("帖子不存在"); checkOwnerOrManager(topic, operatorId); String before = topic.getStatus().name(); topic.setStatus(TopicStatus.DELETED); topic.setDeletedAt(LocalDateTime.now()); topic.setDeletedBy(operatorId); topic.setDeleteReason(reason); topicMapper.updateById(topic); auditLogService.log(operatorId, AuditAction.TOPIC_DELETED, "TOPIC", id, topic.getBoardId(), reason, before, "DELETED", null, true, null); } 置顶操作先做版块权限校验,再更新状态并记录审计:authorizationService.requireBoardManager(operatorId, topic.getBoardId()); topic.setIsTop(true); topicMapper.updateById(topic); auditLogService.log(operatorId, AuditAction.TOPIC_TOPPED, "TOPIC", id, topic.getBoardId(), reason, "false", "true", null, true, null); 6. 内容管理与人工复核管理端提供帖子管理、回复管理和内容审核队列。REVIEW 内容默认不公开,管理员或对应版主可以查看命中信息并选择通过或拒绝;系统会检查内容当前状态,避免重复审批。审核队列同样受版块权限约束:管理员查看全部,版主查询条件被限定到自己负责的版块。审批结果会同步回帖子或回复,并写入审计日志。7. 敏感词过滤与华为云审核敏感词管理支持新增、编辑、启用、停用和动态重载。每个词可以配置不同动作:REJECT:直接判为 BLOCK,阻止公开;REVIEW:进入人工审核队列;REPLACE:将命中内容替换后继续处理;未命中:本地结果为 PASS。系统先执行本地 DFA,再按配置调用华为云官方 Moderation Java SDK,并将不同来源统一映射为 PASS / REVIEW / BLOCK。云服务超时或异常时,系统降级到本地审核结果,同时保存 isDegraded 和脱敏错误摘要,不输出 AK/SK。public ModerationDecision moderateContent( String content, String contentType, Long targetId, Long boardId) { DfaResult dfaResult = matchWithDfa(content); ReviewStatus localStatus = determineLocalStatus(dfaResult.matchedWords()); saveModerationRecord(targetId, parseTargetType(contentType), boardId, ModerationSource.LOCAL, localStatus, null, String.join(",", dfaResult.matchedWords()), null, false, null); if (localStatus == ReviewStatus.BLOCK || !huaweiCloudEnabled) { return new ModerationDecision(localStatus, dfaResult.maskedText()); } try { CloudDecision cloud = callCloudApi(content, contentType); return new ModerationDecision( strictest(localStatus, cloud.status()), dfaResult.maskedText()); } catch (Exception e) { String summary = sanitizeError(e); saveModerationRecord(targetId, parseTargetType(contentType), boardId, ModerationSource.HUAWEI_CLOUD, localStatus, null, String.join(",", dfaResult.matchedWords()), null, true, summary); return new ModerationDecision(localStatus, dfaResult.maskedText()); } } 8. 拉黑会员系统支持两类作用域和两类时效:管理员可以创建全局黑名单;管理员或对应版主可以创建版块黑名单;记录既可以永久生效,也可以设置结束时间。解除拉黑同样需要权限校验并记录原因。发帖和回复前会同时匹配“全局黑名单”与“当前版块黑名单”,并校验记录仍处于有效期内:wrapper.eq(BlacklistRecord::getUserId, userId) .eq(BlacklistRecord::getStatus, BlacklistStatus.ACTIVE) .and(w -> w.eq(BlacklistRecord::getScope, BlacklistScope.GLOBAL) .or(w2 -> w2.eq(BlacklistRecord::getScope, BlacklistScope.BOARD) .eq(BlacklistRecord::getBoardId, boardId))) .and(w -> w.eq(BlacklistRecord::getIsPermanent, true) .or(w2 -> w2.isNull(BlacklistRecord::getEndTime) .or(w3 -> w3.gt(BlacklistRecord::getEndTime, LocalDateTime.now())))); 命中黑名单时后端返回 403 和清晰原因;即使绕过前端按钮也无法发帖或跟帖。9. 审计日志与管理驾驶舱除了原题要求,我增加了审计日志和管理驾驶舱。置顶、锁帖、删除、恢复、拉黑、解除拉黑和人工审核等关键动作都会记录操作者、目标、所属版块、原因、前后状态与时间,便于复盘管理行为和处理争议。六、创新与易用性双层内容治理:本地 DFA 提供低延迟、可控的第一道防线,华为云审核扩展识别范围,人工复核处理模糊内容。故障降级:外部云审核不可用时不阻断整个论坛,改用本地结果并留痕,兼顾可用性和可追溯性。细粒度版主权限:不是简单的“后台角色”,而是把管理权精确限制到负责版块,跨版块请求明确返回 HTTP 403。可恢复内容治理:管理删除采用软删除,保留原因和责任人,并提供恢复能力,降低误删风险。角色化操作体验:会员专注浏览与互动,版主只看到负责范围,管理员获得全局驾驶舱,减少无关菜单和误操作。七、码道新能力与华为云技术使用使用项目级规则与阶段 Prompt 约束技术栈、权限模型、内容治理和质量门禁;建立 forum-sdd、forum-moderation、forum-quality-gate 三个项目 Skill,分别服务于需求设计、内容治理与发布前验证;使用浏览器控制能力对 ADMIN、MODERATOR 等真实页面进行验收和截图,避免以 mock 页面冒充后端功能;接入华为云 Moderation Java SDK,保留 requestId、风险标签、分段结果和降级状态;同时提供 Vue Web 应用、REST 后台服务、MySQL 数据库与 Docker Compose/Nginx 本地容器化运行形态。八、测试与验证结果项目不是只完成页面展示,而是执行了完整质量门禁:验证项结果后端集成测试34/34 通过,0 failure、0 error、0 skipped前端类型检查与生产构建通过Docker Compose 配置与镜像构建通过全新 MySQL 数据卷启动MySQL、backend、frontend 均 healthy浏览器真实验收13 张页面证据,关键页面控制台错误为 0权限专项验证匿名私有接口 401,会员后台接口 403,版主跨版块 403验证命令如下:# 后端测试 cd backend mvn clean test # 前端类型检查和生产构建 cd ../frontend npm run build # 生产形态验证 cd .. docker compose config --quiet docker compose build docker compose up -d docker compose ps curl --fail http://localhost/actuator/health34 项后端测试覆盖:三种角色认证、错误密码、禁用账号、匿名访问、发帖、回复、点赞幂等、置顶排序、锁帖、软删除恢复、敏感词 REJECT/REVIEW/REPLACE、词库动态重载、人工审核、全局/版块黑名单、版主跨版块越权、审计和驾驶舱等关键场景。九、本地运行与容器化验证本地开发# 后端:dev 配置使用 H2,便于本地复现 git clone cid:link_0.git cd CampusCloudForum/backend mvn spring-boot:run -Dspring-boot.run.profiles=dev # 另开终端启动前端 cd CampusCloudForum/frontend npm install npm run dev访问 http://localhost:5173,后端健康检查为 http://localhost:8080/actuator/health。Docker Compose 本地容器化运行cp .env.example .env # 填写本地容器运行所需的 MySQL 密码和 JWT_SECRET docker compose config --quiet docker compose up -d --build curl --fail http://localhost/actuator/health如需在本地自行验证华为云内容审核,可通过环境变量启用;凭证不在代码中硬编码,也不提交到仓库:HUAWEI_CLOUD_MODERATION_ENABLED=true HUAWEI_CLOUD_REGION=cn-north-4 HUAWEI_CLOUD_PROJECT_ID=<project-id> HUAWEI_CLOUD_AK=<ak> HUAWEI_CLOUD_SK=<sk> HUAWEI_CLOUD_MODERATION_TIMEOUT_MS=3000 十、逐项对应评分项项目成果与证据创新易用双层审核、云故障降级、人工复核、版块级权限、软删除与角色化页面功能完备原题 10 个功能点全部闭环;34 项测试、13 张真实页面截图技术能力码道 Prompt/Skill/MCP、华为云 Moderation SDK、Web + REST + Docker/Nginx 多形态文档完整性需求、架构、数据库、API、测试、本地运行、码道过程、验收清单、案例文档和证据目录完整十一、项目成果总结这次实战让我从“实现一个能发帖的页面”,进一步走到了“构建一个权限正确、内容安全、操作可追溯、能够容器化运行的论坛系统”。CloudForum 已在本地完成核心功能、自动化测试、真实页面验收和完整容器验证;仓库中同时保留了需求、架构、API、测试和运行文档,方便评审复现。
  • [高校训练营] 基于 MaaS 和 CodeArts 的智能运维与代码重构平台实践
    在线体验地址:http://113.44.103.96(请复制到浏览器访问)项目源码仓库:cid:link_5一、概述1.1 案例介绍在软件研发和云上运维过程中,遗留代码重构依赖人工经验,故障日志分析又常常跨越应用、容器和函数等多个层次,定位慢、重复劳动多。CodeVerse-Ops 将华为云 MaaS 大模型能力接入研发运维流程,提供智能代码重构、云原生日志诊断、代码质量评分、上下文追问、历史任务分析和代码片段管理等能力。本案例将使用华为云 MaaS 的 DeepSeek-V4-Flash 模型作为推理引擎,基于 Next.js、Prisma 和 SQLite 构建全栈应用,并通过 PM2 与 Nginx 部署到弹性云服务器 ECS。完成案例后,您将掌握:使用 OpenAI 兼容接口调用华为云 MaaS 模型;使用华为云码道的 Spec-Driven 模式,将需求依次转化为规格、设计、任务和代码;理解 Server-Sent Events(SSE)任务事件,并在 AI 追问场景中实现流式回复;将模型能力组合为代码重构、日志根因分析和质量评分工作流;使用 Prisma 与 SQLite 管理任务、对话和收藏数据,并理解质量评分的数据模型;在 Ubuntu ECS 上完成 Node.js 应用的一键部署、验证和运维。说明:模型生成内容可能存在偏差。重构代码和运维修复建议应经过人工审查,并在测试环境验证后再应用到生产环境。1.2 适用对象企业开发者及 DevOps、SRE、云原生运维人员;希望学习大模型应用开发的个人开发者;具备 JavaScript/TypeScript、Linux 命令行基础的高校学生。1.3 案例时间直接使用仓库源码完成资源准备、部署和功能验证,预计需要 60~90 分钟。如通过码道分阶段搭建 CodeVerse-Ops,建议预留 2~3 小时,具体时间取决于代码生成、人工评审、依赖下载和构建速度。1.4 案例流程图 1-1 CodeVerse-Ops 案例流程说明:开通 MaaS:登录华为开发者空间,开通 DeepSeek-V4-Flash 预置服务,创建并妥善保存 API Key;创建 ECS:购买 Ubuntu ECS,绑定弹性公网 IP,并在安全组中开放 SSH 和 HTTP 访问;配置并上传:填写 MaaS API Key、基础地址和数据库连接,将项目部署包上传至 ECS;一键部署:运行部署脚本,自动安装依赖,完成数据库迁移、项目构建、PM2 启动和 Nginx 配置;功能体验:依次验证代码重构、批量处理、日志诊断、质量评分、AI 对话、仪表盘和收藏库;验证并释放:检查应用、代理和数据库状态;体验结束后删除 ECS、EIP 及不再使用的模型凭据。流程说明:图 1-1 展示的是“使用现有源码部署体验”的主流程。如需从需求开始复现项目开发过程,请在获取源码和正式部署前完成第三章的码道 Spec-Driven 四阶段实践。1.5 方案架构图 1-2 CodeVerse-Ops 系统运行架构核心调用链如下:浏览器提交代码或日志,Next.js API 创建任务并写入 SQLite;当前版本的提交接口同步调用华为云 MaaS,解析结果并将任务更新为 COMPLETED;浏览器收到 taskId 后连接任务 SSE 接口,通常直接收到 complete 事件并展示结果;用户继续追问时,服务端通过 thinking、result_chunk、complete 或 error 事件逐段推送模型回复;任务结果、对话记录和收藏内容持久化到 SQLite;质量评分接口在收到 taskId 时可持久化评分;仪表盘聚合任务数据,展示近 30 天趋势、任务分布,并预留质量趋势展示。1.6 资源总览本案例使用按需资源。以 1 小时体验、少量公网流量和少量模型调用估算,费用通常由 ECS 实例费用、EIP 流量费用和 MaaS Token 费用组成。云服务价格会因区域、规格和活动变化,最终以购买页面及账单为准。资源名称推荐规格用途计费说明华为开发者空间已完成实名认证的账号进入开发平台和实战案例免费MaaS 模型即服务DeepSeek-V4-Flash代码重构、日志分析、质量评分和对话按实际 Token 用量计费,可优先使用已领取权益弹性云服务器 ECS2 vCPU、4 GiB、Ubuntu 22.04、40 GiB 系统盘运行 CodeVerse-Ops推荐按需计费,价格以控制台为准弹性公网 IP EIP按流量计费、5 Mbit/sSSH 登录和浏览器访问按流量计费,价格以控制台为准费用提示:体验完成后请及时释放 ECS 和 EIP。仅关闭操作系统不会停止 ECS 计费。二、环境和资源准备2.1 前置条件开始前请确认:已注册华为云账号并完成实名认证;账号余额或代金券足以支付本案例资源;本地可使用 SSH 和 SCP。Windows 10/11 可在 PowerShell 中执行 ssh -V 和 scp 检查;已获得完整的 codeverse-ops 项目目录;不要将 API Key 写入公开仓库、聊天记录或截图。2.2 开通 MaaS 模型并创建 API Key登录华为开发者空间。如尚未领取模型权益,可参考《华为云 MaaS 平台大模型 Tokens 领取使用指导》完成领取。然后按以下步骤开通模型:进入 MaaS 控制台 > 模型推理 > 在线推理 > 预置服务;找到 DeepSeek-V4-Flash,单击 开通服务;服务开通后单击 调用说明,确认模型参数为 deepseek-v4-flash;在调用说明页面创建 API Key,并立即复制到安全位置。API Key 通常只在创建时完整显示;记录 OpenAI 兼容接口地址。中国大陆站的 OpenAI 兼容接口当前仅支持 西南-贵阳一,该区域的完整地址为:https://api.modelarts-maas.com/openai/v1/chat/completions本项目会自动在基础地址后追加 /v1/chat/completions,因此项目配置中应填写:https://api.modelarts-maas.com/openai中国香港站应以控制台“调用说明”显示的地址为准,常见基础地址为:https://api-ap-southeast-1.modelarts-maas.com/openai重要:模型服务、API Key 和调用地址必须属于同一区域,并以控制台“调用说明”为准。不要填写完整的 /v1/chat/completions 地址,否则项目会重复拼接路径;不要使用 https://api.deepseek.com,该地址不是华为云 MaaS 服务地址。Linux、macOS 或 ECS 可使用以下命令验证 API Key:export MAAS_API_KEY="<你的MaaS API Key>" curl -sS "https://api.modelarts-maas.com/openai/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${MAAS_API_KEY}" \ -d '{ "model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "请回复:连接成功"}], "max_tokens": 64 }' 响应中出现 choices 和模型回复即表示调用成功。若返回 401 或 403,请检查 API Key、模型开通状态和区域是否一致。Windows PowerShell 使用以下命令:$env:MAAS_API_KEY = "<你的MaaS API Key>" $headers = @{ "Content-Type" = "application/json" "Authorization" = "Bearer $env:MAAS_API_KEY" } $body = @{ model = "deepseek-v4-flash" messages = @(@{ role = "user"; content = "请回复:连接成功" }) max_tokens = 64 } | ConvertTo-Json -Depth 4 Invoke-RestMethod ` -Uri "https://api.modelarts-maas.com/openai/v1/chat/completions" ` -Method Post ` -Headers $headers ` -Body $body2.3 创建 ECS登录华为云控制台,进入 服务列表 > 计算 > 弹性云服务器 ECS,单击 购买弹性云服务器。图 2-1 选择 ECS 规格、镜像、磁盘和公网访问配置推荐配置如下:配置项推荐值说明计费模式按需计费便于体验结束后及时释放区域与账号和网络规划一致购买后不可直接更换CPU 架构x86与常用 Node.js 依赖兼容规格2 vCPU、4 GiB低于 4 GiB 可能在 next build 时内存不足镜像Ubuntu 22.04 Server 64bit部署脚本使用 apt-get系统盘40 GiB用于系统、依赖、构建产物和 SQLiteEIP现在购买用于 SSH 和 Web 访问带宽计费按流量计费,5 Mbit/s适合短时体验登录方式密钥对或强密码密钥对安全性更高购买完成后,在 ECS 详情页记录:ECS 公网 IP:后文以 <ECS_IP> 表示;登录用户名:本案例部署脚本固定使用 /root 并以 root 用户配置 PM2,因此应选择支持 root 登录的 Ubuntu 公共镜像;密钥文件路径或登录密码。图 2-2 ECS 创建完成并处于运行中说明:截图中的实例名称、IP、价格和区域仅为操作示例,请以实际控制台页面为准。2.4 配置安全组进入 ECS 详情 > 安全组 > 配置规则 > 入方向规则,添加以下规则:协议端口来源用途TCP22本机公网 IP/32SSH 和 SCPTCP80本机公网 IP/32;公开体验时可临时使用 0.0.0.0/0浏览器访问应用图 2-3 配置 ECS 安全组入方向规则安全建议:不要将 22 端口长期对全网开放。生产环境还应配置 HTTPS、Web 应用防火墙、身份认证和访问审计。本案例应用本身未实现用户登录,不应直接承载敏感代码或生产日志。2.5 准备项目环境变量记录从 MaaS 控制台获取的 API Key 和基础地址。为避免凭据进入压缩包,本案例将在代码上传 ECS 后创建 .env.production,文件内容如下:# 华为云 MaaS API Key HUAWEI_MAAS_API_KEY=<你的MaaS API Key> # 仅填写基础地址,不包含 /v1/chat/completions HUAWEI_MAAS_BASE_URL=https://api.modelarts-maas.com/openai # Prisma 会相对 prisma/schema.prisma 解析该路径 DATABASE_URL=file:../dev.db配置要求:HUAWEI_MAAS_API_KEY 不要添加多余空格或中文引号;HUAWEI_MAAS_BASE_URL 末尾有无 / 均可,客户端会移除末尾斜杠;DATABASE_URL 保持为 file:../dev.db,使 Prisma CLI 和应用运行时使用项目根目录下同一个数据库;.env.production 含敏感信息,不得提交到公开代码仓库或打入部署包;项目已通过 .gitignore 排除 .env.production;提交前仍应使用 git status 确认该文件未被暂存;部署脚本不会输出环境变量内容,终端日志中不应出现 API Key。2.6 获取案例源码通过 Git 下载案例源码:git clone cid:link_5.git codeverse-ops cd codeverse-ops仓库地址:CodeVerse-Ops(GitCode)【本帖子开头有】。下载后确认目录中至少包含:codeverse-ops/ ├── package.json ├── package-lock.json ├── scripts/deploy-ecs.sh ├── prisma/ └── src/检查点:执行 git status 能正常显示仓库状态,且 package.json、scripts/deploy-ecs.sh、prisma/ 和 src/ 均存在。三、通过码道分阶段搭建 CodeVerse-Ops本模块参考华为开发者空间案例中心的码道实践组织方式,结合 CodeVerse-Ops 的实际开发记录,演示如何使用华为云码道(CodeArts)代码智能体,以 Spec-Driven 模式将复杂需求依次转化为需求规格、技术设计、任务清单和可运行代码。说明:码道界面、模型列表和按钮位置可能随版本更新而变化,请以实际产品页面为准。生成代码必须经过人工审查、构建测试和安全检查;不要在对话、截图或提交记录中粘贴 API Key、密码等敏感信息。3.1 开通并进入码道登录华为开发者官网,进入华为云码道(CodeArts)代码智能体体验页面;按页面提示完成体验版开通;下载并安装支持码道的开发工具,登录同一华为云账号;打开码道 Agent Space 或 IDE 右侧智能体面板,确认可以选择 氛围编程(Vibe-Coding) 和 规范开发(Spec-Driven)。图 3-1 开通华为云码道代码智能体体验版图 3-2 进入码道 Agent Space图 3-3 在 IDE 中打开码道代码智能体3.2 创建项目并选择 Spec-Driven 模式新建空工作区,在智能体面板选择 规范开发(Spec-Driven)。首次输入应描述业务目标、技术栈、模型服务、核心功能和交付要求,避免只输入“帮我做一个网站”等宽泛指令。可使用以下需求作为起始提示词:请使用 Next.js 14、TypeScript、Tailwind CSS、Prisma 和 SQLite 构建 CodeVerse-Ops。应用接入华为云 MaaS 的 DeepSeek-V4-Flash, 提供单文件/批量代码重构、CCE/FunctionGraph 日志诊断、代码质量评分、 上下文对话、任务仪表盘和代码片段收藏功能。请采用 Spec-Driven 流程, 先生成需求规格,再生成技术设计和任务清单,经确认后分阶段实现。图 3-4 选择 Spec-Driven 模式并提交项目目标Spec-Driven 流程包含四个阶段:需求规格设计:明确目标、边界、用户故事和验收标准;实现方案创建:确定架构、数据模型、接口和部署方案;编码任务规划:将设计拆分为可追踪、可验证的任务;任务执行:按依赖顺序生成代码,并持续构建验证。3.3 第一阶段:生成并评审 spec.md码道首先将自然语言需求整理为 spec.md。评审时重点检查:是否覆盖代码重构、日志诊断、任务状态、模型调用和数据持久化;是否明确“不负责自动修改生产代码、不直接执行模型生成命令”等安全边界;每个核心能力是否具有可验证的验收标准;模型名称、接口兼容方式和部署目标是否与项目实际一致。图 3-5 第一阶段完成需求规格设计若规格有遗漏,先在对话中提出修改要求,确认 spec.md 后再进入设计阶段。不要让智能体在需求边界未确定时直接批量生成代码。3.4 第二阶段:生成并评审 design.mddesign.md 应把需求落实为可实现的技术方案。本项目重点确认:Next.js App Router 同时承载页面和 API;Prisma/SQLite 数据模型覆盖任务、日志、对话、评分和收藏;MaaS 客户端统一处理鉴权、超时、重试及流式响应;首轮任务与 AI 对话的 SSE 行为描述准确;ECS、PM2、Nginx 和容器化部署路径清晰;API Key 仅通过环境变量注入,不进入源码、镜像和日志。图 3-6 第二阶段完成实现方案设计3.5 第三阶段:生成并评审 tasks.md码道根据规格和设计生成 tasks.md,把工作拆分为初始化、数据模型、MaaS 客户端、任务状态、核心 API、前端页面和部署验证等任务。评审任务清单时应确保:每项任务都能回溯到 spec.md 和 design.md;任务依赖顺序正确,可并行项和串行项明确;每项任务包含完成条件,而不只是文件名;构建、数据库迁移、接口验证和安全检查被列入任务。图 3-7 第三阶段完成编码任务规划3.6 第四阶段:按任务清单执行确认任务清单后进入执行阶段。码道会读取规格和设计,按依赖关系创建文件、安装依赖并实现功能。建议采用“小批次执行—查看变更—运行验证—继续下一批”的节奏:先完成项目初始化、环境变量声明和 Prisma Schema;再实现 MaaS 客户端、任务状态和后端 API;然后实现重构、诊断、仪表盘、收藏等页面;最后补充 Dockerfile、ECS/CCE 部署文件和操作文档;每批变更后查看差异,拒绝与规格无关的修改。图 3-8 码道开始执行初始化与配置任务图 3-9 码道继续实现后端接口和前端页面图 3-10 任务执行阶段完成3.7 本地运行与阶段验收智能体完成首轮实现后,在项目目录执行:npm install npx prisma generate npx prisma migrate deploy npm run dev浏览器访问 http://localhost:3000,先验证页面路由和基本交互,再使用脱敏的测试代码与测试日志验证 MaaS 调用。首个可运行版本可能只具备代码重构和日志诊断,应按 tasks.md 的验收条件逐项检查,而不是仅以“页面能打开”作为完成标准。图 3-11 首个本地可运行版本的代码重构页面图 3-12 本地验证日志诊断功能3.8 模型接入的原型记录与正式配置项目早期曾使用 DeepSeek 官方 API 验证 OpenAI 兼容调用链,以下两张图仅用于说明原型演进,不是本案例的最终配置步骤。图 3-13 早期原型的 API Key 创建记录图 3-14 早期原型的环境变量配置正式案例已经切换到华为云 MaaS。请严格按照 2.2 和 2.5 节配置 HUAWEI_MAAS_API_KEY 与 https://api.modelarts-maas.com/openai,不要照抄历史截图中的 https://api.deepseek.com;截图中的凭据已失效或脱敏。3.9 迭代优化与上下文管理首轮功能完成后,可继续让码道基于实际测试结果迭代,但每次指令应说明问题、预期行为、影响范围和验证方式。本项目的后续迭代包括主题系统、命令面板、仪表盘、收藏库、批量重构、上下文对话以及 ECS 部署加固。图 3-15 基于功能差距分析继续迭代图 3-16 依据新增需求升级功能版本长任务会持续占用上下文。阶段验收后可使用会话压缩保留目标、约束、关键文件和未完成任务,再继续下一轮开发。压缩前应确认摘要未包含 API Key、登录密码等敏感信息。图 3-17 使用会话压缩管理长周期开发上下文完成本模块后,项目应通过 npm run build,数据库迁移可执行,核心页面可访问,且所有环境变量和部署步骤与后续章节一致。四、构建并部署 CodeVerse-Ops 应用4.1 技术栈与项目结构主要技术栈如下:层次技术版本/作用Web 框架Next.js14.2.35,App Router 全栈应用前端React、TypeScript、Tailwind CSSReact 18、TypeScript 5、Tailwind CSS 3.4编辑器CodeMirror 6代码输入、语法高亮和只读结果展示图表Recharts仪表盘与五维质量雷达图数据访问Prisma5.22.0,模型定义、迁移和查询数据库SQLite保存任务、日志、对话、评分和收藏模型服务华为云 MaaSDeepSeek-V4-Flash、OpenAI 兼容接口运行环境Node.js、PM2、NginxNode.js 20、进程守护、反向代理项目关键结构:codeverse-ops/ ├── prisma/ │ ├── schema.prisma # 7 个数据模型 │ └── migrations/ # 数据库迁移 ├── src/ │ ├── app/ │ │ ├── page.tsx # 首页 │ │ ├── refactor/page.tsx # 单文件/批量代码重构 │ │ ├── ops/diagnose/page.tsx # CCE、FunctionGraph 日志诊断 │ │ ├── dashboard/page.tsx # 任务统计与趋势 │ │ ├── snippets/page.tsx # 代码片段收藏库 │ │ └── api/ # 重构、诊断、评分、对话等 API │ ├── components/ # 编辑器、对比、图表、命令面板等组件 │ ├── hooks/ # SSE、主题等 React Hooks │ ├── lib/ │ │ ├── huawei-maas.ts # MaaS 客户端、重试和超时控制 │ │ ├── prisma.ts # Prisma 单例 │ │ ├── sse-client.ts # SSE 消息与响应头 │ │ ├── task-state.ts # 任务状态 │ │ ├── conversation-manager.ts # 30 分钟内存上下文 │ │ └── templates.ts # 代码与日志示例模板 │ └── types/ # API、模板和 SSE 类型 ├── .env.example # 环境变量示例 ├── .env.production # 生产配置,需自行创建 ├── scripts/ │ ├── deploy-ecs.sh # ECS 一键部署脚本 │ └── build-image.sh # SWR 镜像构建脚本 ├── deploy/ │ └── cce-deployment.yaml # CCE 部署清单 ├── Dockerfile # 容器化构建文件 ├── package.json # 项目依赖与命令 └── package-lock.json # 锁定依赖版本Prisma 数据模型职责:模型作用Task保存重构或日志诊断任务及状态CloudLog保存待分析日志及分析状态Snippet保存收藏的原始代码、重构代码和说明BatchGroup管理批量重构的总数和完成进度Conversation关联任务与对话Message持久化用户和助手消息QualityScore在评分接口收到 taskId 时,保存安全性、可维护性、性能、可读性和类型安全评分4.2 关键实现解析4.2.1 MaaS 客户端src/lib/huawei-maas.ts 负责:从环境变量读取 API Key 和基础地址;拼接 /v1/chat/completions;使用 Authorization: Bearer <API_KEY> 鉴权;固定调用 deepseek-v4-flash;同步调用最多尝试 3 次,即首次失败后最多重试 2 次,退避时间依次为 1 秒、2 秒;单次调用超时时间为 120 秒;支持普通 JSON 响应和流式响应。核心请求结构如下:const response = await fetch(`${baseUrl}/v1/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ model: "deepseek-v4-flash", messages, temperature: 0.7, max_tokens: 4096, stream: true, }), }); 4.2.2 任务接口与 SSE 事件代码重构和日志诊断采用“同步任务提交 + SSE 结果回传”的两阶段请求:图 4-1 CodeVerse-Ops 首轮任务与对话请求流程图中编号说明:提交代码或日志:浏览器将用户输入发送到对应的 Next.js API;创建任务:服务端在 SQLite 中创建状态为 PENDING 的任务;进入处理状态:开始推理前,将任务状态更新为 PROCESSING;调用模型:服务端通过 OpenAI 兼容接口同步调用华为云 MaaS;返回完整结果:MaaS 返回完整的代码重构或日志分析结果;保存结果:服务端解析模型输出,将结果写入 SQLite,并将任务标记为 COMPLETED;响应提交请求:Next.js API 向浏览器返回 taskId 和完整结果;连接任务 SSE:浏览器使用 EventSource 连接任务 SSE 接口;返回完成事件:SSE 接口查询到已完成任务后,发送 complete 事件。用户继续对话时,应用则通过 SSE 逐段返回模型回复。实现边界:页面上的“正在连接 AI 服务”和 SSE 状态组件已经具备流式展示结构,但首轮重构、诊断请求的等待主要发生在同步 POST 阶段,当前版本不会逐 Token 展示首轮模型输出。对话追问采用真实流式响应。4.2.3 提示词与结构化结果应用通过系统提示词限定模型角色,并要求模型返回 JSON:代码重构:返回 refactoredCode 和 explanation;日志诊断:返回 analysis 和 patchSuggestion;质量评分:返回五个 0~100 的维度分数及 details。服务端会从模型输出中提取 JSON。若模型未严格返回 JSON,部分接口会回退为原始文本。因此,生成结果仍需人工复核。4.3 打包项目在本地打开项目父目录执行。部署包明确排除环境变量、依赖、构建产物、数据库和 Git 元数据:tar -czf codeverse-ops-deploy.tar.gz \ --exclude=codeverse-ops/node_modules \ --exclude=codeverse-ops/.next \ --exclude=codeverse-ops/dev.db \ --exclude=codeverse-ops/.env \ --exclude=codeverse-ops/.env.production \ --exclude=codeverse-ops/.git \ codeverse-ops/Windows PowerShell 使用反引号续行:tar -czf codeverse-ops-deploy.tar.gz ` --exclude=codeverse-ops/node_modules ` --exclude=codeverse-ops/.next ` --exclude=codeverse-ops/dev.db ` --exclude=codeverse-ops/.env ` --exclude=codeverse-ops/.env.production ` --exclude=codeverse-ops/.git ` codeverse-ops/ 打包后检查文件和压缩包内容:Get-Item .\codeverse-ops-deploy.tar.gz tar -tzf .\codeverse-ops-deploy.tar.gz检查点:压缩包中必须包含 package-lock.json、scripts/deploy-ecs.sh、prisma/ 和 src/,不得包含 .env、.env.production、node_modules、.next 或旧的 dev.db。4.4 上传项目并执行一键部署步骤 1:上传部署包在本地项目父目录执行:scp codeverse-ops-deploy.tar.gz root@<ECS_IP>:/root/使用密钥对时执行:scp -i <私钥文件路径> codeverse-ops-deploy.tar.gz root@<ECS_IP>:/root/步骤 2:登录 ECSssh root@<ECS_IP> 使用密钥对时执行:ssh -i <私钥文件路径> root@<ECS_IP> 步骤 3:解压并运行部署脚本cd /root tar -xzf codeverse-ops-deploy.tar.gz rm -f codeverse-ops-deploy.tar.gz cd /root/codeverse-ops vi .env.production在编辑器中填写 2.5 节准备的三个环境变量,保存后限制文件权限:chmod 600 .env.production # 确保 Node.js 主版本为 20 node -v 2>/dev/null || true 若已安装的 Node.js 不是 20.x,先升级:curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs首次部署执行:chmod +x scripts/deploy-ecs.sh bash scripts/deploy-ecs.sh重新部署时,scripts/deploy-ecs.sh 会先备份 /opt/codeverse-ops/dev.db,替换应用文件后再恢复数据库并执行增量迁移。重要数据仍建议在部署前单独备份。部署脚本自动完成:阶段操作预期结果1/6安装 Node.js 20、PM2、Nginx、SQLite输出各工具版本2/6备份数据库,替换 /opt/codeverse-ops 中的应用文件并恢复数据项目文件部署完成,历史数据保留3/6将 .env.production 复制为 .env应用可读取配置4/6执行 npm ci、Prisma 生成、迁移和 next build数据表和生产构建生成5/6使用 PM2 启动 npm startcodeverse-ops 状态为 online6/6配置 Nginx,将 80 端口代理到 3000nginx -t 成功并重载部署脚本结束时会输出访问地址。请以实际 ECS 公网 IP 为准:http://<ECS_IP>说明:脚本末尾可能显示脚本内预置的示例 IP,该值不一定是当前 ECS 地址,不应作为访问依据。图 4-2 PM2 启动成功且 Nginx 配置校验通过4.5 部署结果验证依次执行:node -v npm -v pm2 status systemctl is-active nginx curl -I http://127.0.0.1:3000 curl -I http://127.0.0.1预期结果:Node.js 主版本为 v20;PM2 中 codeverse-ops 状态为 online;Nginx 状态为 active;两次 curl 均返回 HTTP 200、301 或 307 等正常响应,而不是连接失败。检查数据库:cd /opt/codeverse-ops sqlite3 dev.db ".tables" 预期至少看到与以下模型对应的数据表:BatchGroup CloudLog Conversation Message QualityScore Snippet Task最后,在浏览器访问 http://<ECS_IP>。首页应显示“代码重构”“日志诊断”“仪表盘”和“收藏库”等入口。图 4-3 通过 ECS 公网地址访问 CodeVerse-Ops图 4-4 首页功能入口、核心特性和任务统计五、功能体验5.1 智能代码重构在首页单击 代码重构;保持 单文件 模式;选择 javascript,单击 快捷模板 > 回调地狱;也可粘贴自己的代码;单击 提交重构;提交后等待 MaaS 返回完整结果。当前版本在此阶段可能仅显示按钮处于处理中;页面连接任务 SSE 接口并显示“重构完成”后,查看 TypeScript 结果和优化点;单击 对比查看,检查原代码与重构代码差异;查看五维质量雷达图,比较原始代码和重构代码;使用复制、导出或收藏功能保存结果。图 5-1 提交代码并获得 TypeScript 重构结果图 5-2 对比重构前后代码并查看质量评分示例输入:function getUserData(userId, callback) { db.query("SELECT * FROM users WHERE id = ?", [userId], function (err, user) { if (err) return callback(err); db.query("SELECT * FROM orders WHERE userId = ?", [userId], function (err, orders) { if (err) return callback(err); callback(null, { user, orders }); }); }); } 验收标准:请求完成后页面显示任务成功状态、完整重构结果和任务 ID;结果包含带明确类型的 TypeScript 代码;优化说明能够指出异步流程、错误处理或类型安全等改进;雷达图至少展示安全性、可维护性、性能、可读性和类型安全五个维度。注意:当前重构提示词统一要求输出 TypeScript。即使输入 Python、Java、Go、PHP、Ruby、C 或 C++,输出目标仍是 TypeScript。5.2 批量代码重构进入 代码重构,切换到 批量;单击 添加文件,填写文件名、语言和代码内容;重复添加多个文件;单击批量提交按钮,查看总体和单文件处理状态;等待各文件状态更新为 COMPLETED 或 FAILED。限制条件:单次最多 20 个文件;接口以 JavaScript 字符串长度统计总量,上限约 500 万字符;该限制不等同于严格的 UTF-8 字节大小;每个文件会创建独立任务,并归属同一个批次;批量处理消耗的模型 Token 通常高于单文件处理,请控制测试代码规模。当前版本说明:批量页面仅展示文件名、语言和任务状态,暂不提供单个文件的重构结果详情入口。5.3 云原生日志故障诊断在首页单击 日志诊断;选择 CCE(云容器引擎);单击 快捷模板 > CCE OOMKilled;单击 提交诊断;等待同步分析完成,查看根因分析和 YAML 修复建议;再选择 FunctionGraph(函数工作流),使用“函数超时”模板重复体验。图 5-3 提交 FunctionGraph 故障日志并查看根因图 5-4 查看结构化修复建议并继续追问示例输入:Warning OOMKilled pod/api-server-7d9f8b6c4-x2k9j Last State: Terminated Reason: OOMKilled Exit Code: 137 Restart Count: 5 Limits: cpu: 1, memory: 512Mi Requests: cpu: 500m, memory: 256Mi验收标准:根因分析能识别容器内存超限和退出码 137;修复建议包含调整 resources.requests、resources.limits 或排查内存泄漏的可执行方向;FunctionGraph 超时案例能给出超时时间、内存、数据读取方式等方面的排查建议。安全提示:提交真实日志前应删除账号、Token、密码、内网地址、用户数据等敏感信息。模型建议不可直接应用于生产集群。5.4 代码质量评分单文件重构完成后,页面会分别调用质量评分接口评估原始代码和重构代码。评分范围为 0~100:维度评估内容常见风险安全性注入、XSS、敏感信息、危险 API拼接 SQL、明文密钥、eval可维护性模块化、重复度、耦合度超长函数、重复逻辑、全局状态性能复杂度、I/O 和资源使用不必要的嵌套循环、重复请求可读性命名、结构、注释单字母变量、深层嵌套类型安全类型覆盖与边界处理any、隐式转换、空值未处理评分由大模型生成,适合辅助比较,不等同于静态代码扫描、单元测试或安全审计结果。当前版本说明:重构页面会展示原始代码和重构代码的即时评分,但页面请求暂未携带 taskId,因此这些评分不会写入 QualityScore 表,仪表盘“质量评分趋势”可能为空。这不影响雷达图展示和其他任务统计。5.5 AI 上下文对话在重构或诊断结果页单击 继续对话;输入针对当前结果的问题,例如“请解释此处的类型设计”或“如何验证该 YAML 修复有效”;查看流式回复;收起对话面板后再次打开,确认历史消息仍可显示。对话消息会写入 SQLite,但服务端用于连续推理的内存上下文有效期为 30 分钟,每 5 分钟清理一次。重新打开“继续对话”面板时,应用会读取持久化消息并重建上下文;如果面板保持打开期间上下文过期,接口会提示重新创建。刷新页面后,当前结果和 taskId 会丢失,现有页面没有从仪表盘重新进入原任务详情的入口。5.6 历史任务仪表盘完成至少一次代码重构和一次日志诊断;进入 仪表盘;查看总任务数、重构次数、诊断次数和成功率;查看近 30 天趋势、任务类型分布、状态分布、质量评分趋势和最近任务;单击 刷新,或保持 30 秒自动刷新。图 5-5 查看任务总量、成功率和近 30 天趋势图 5-6 查看任务分布、质量趋势和最近任务若仪表盘为空,请先确认任务已成功写入数据库,再刷新页面。5.7 代码片段收藏库在代码重构结果页单击 收藏;进入 收藏库;使用关键词或编程语言筛选收藏;复制或导出收藏结果;单击 删除 并确认,可移除不再需要的收藏。图 5-7 搜索、复制、导出或删除收藏内容日志诊断结果也提供收藏入口。收藏前请确认结果中不含敏感日志。5.8 命令面板与主题按 Ctrl+K(macOS 为 Command+K)打开命令面板;输入“重构”“诊断”“仪表盘”“收藏”或“主题”等关键词;使用方向键选择命令,按 Enter 执行,按 Esc 关闭;可通过页面导航切换明暗主题。图 5-8 使用命令面板快速导航图 5-9 切换为浅色主题六、运行维护与故障排查6.1 常用运维命令# 查看进程 pm2 status # 查看最近日志 pm2 logs codeverse-ops --lines 100 # 重启应用 pm2 restart codeverse-ops # 查看 Nginx 状态与配置 systemctl status nginx --no-pager nginx -t # 查看端口监听 ss -lntp | grep -E ':80|:3000' # 查看磁盘和内存 df -h free -h # 查看数据库表和最近任务 cd /opt/codeverse-ops sqlite3 dev.db ".tables" sqlite3 dev.db \ "SELECT id, type, status, language, createdAt FROM Task ORDER BY createdAt DESC LIMIT 10;" 修改 .env 后必须重启应用:cd /opt/codeverse-ops pm2 restart codeverse-ops --update-env6.2 常见问题现象可能原因处理方法浏览器无法访问 http://<ECS_IP>安全组未开放 80、Nginx 未启动、EIP 错误检查安全组、systemctl status nginx 和 ECS 公网 IP502 Bad GatewayNext.js 进程未启动或 3000 端口未监听执行 pm2 status、pm2 logs codeverse-ops,重启 PM2返回 401 或 403API Key 无效、模型未开通、账号区域不匹配重新查看 MaaS 调用说明并创建 API Key返回 404MaaS 基础地址配置错误确保地址不包含 /v1/chat/completions,国内站填写 https://api.modelarts-maas.com/openai页面提示“系统配置异常”环境变量缺失检查 /opt/codeverse-ops/.env 中两个 HUAWEI_MAAS_* 变量AI 请求长时间无响应或连接中断单次 MaaS 调用超时为 120 秒,普通调用最多尝试 3 次缩短输入并检查 MaaS 状态;Nginx 已配置 400 秒读取超时,生产环境仍应结合调用策略统一超时对话流式输出中断Nginx、浏览器网络或模型连接中断检查 PM2/Nginx 日志,重新打开对话面板后重试首轮重构或诊断没有逐 Token 输出当前提交接口同步完成 MaaS 调用后才连接任务 SSE这是当前版本的实现行为;等待请求完成,以最终结果为准next build 被系统终止ECS 内存不足使用 4 GiB 或更高规格,停止无关进程后重试Prisma 报数据库不存在或无表DATABASE_URL 错误或迁移失败恢复 file:../dev.db,执行 npx prisma generate && npx prisma migrate deploy仪表盘有任务但无质量趋势当前重构页面的评分请求未携带 taskId这是当前版本已知限制,不影响即时雷达图和其他任务统计批量任务拒绝提交文件数或字符串总长度超限保持不超过 20 个文件、代码总量约 500 万字符以内6.3 重新构建与升级更新代码后,在 ECS 执行:cd /opt/codeverse-ops npm ci npx prisma generate npx prisma migrate deploy npm run build pm2 restart codeverse-ops --update-env执行数据库迁移前建议备份:cd /opt/codeverse-ops cp dev.db "dev.db.backup.$(date +%Y%m%d%H%M%S)" 6.4 生产化建议本案例以快速体验为目标。用于团队或生产环境前,至少应补充:使用 IAM、统一身份认证或应用登录保护所有页面和 API;使用 ELB/Nginx 配置 HTTPS 证书,禁止明文传输代码和日志;将 API Key 存储到云凭据管理服务,避免落盘和终端输出;使用云数据库替代单机 SQLite,并建立自动备份;将内存对话上下文迁移到 Redis 等共享存储,支持多实例;增加请求限流、输入大小限制、审计日志和敏感信息脱敏;对模型生成代码执行静态扫描、单元测试和人工评审;对模型生成的运维命令和 YAML 建立审批及灰度验证流程;配置 AOM、LTS 或其他可观测服务监控 CPU、内存、错误率和模型调用延迟。七、释放资源7.1 删除 ECS登录华为云控制台,进入 弹性云服务器 ECS > 实例;选择本案例创建的 ECS;单击 更多 > 删除;根据页面提示勾选释放绑定的 EIP、删除系统盘和数据盘;确认资源名称和影响范围后完成删除。删除后再次检查 ECS、云硬盘和 EIP 列表,确认没有遗留按需资源。7.2 处理 MaaS 资源进入 MaaS 控制台 > 模型推理 > 在线推理:预置模型通常按实际调用量计费,停止调用后不会继续产生推理 Token;删除不再使用的 API Key,降低泄露风险;如创建过专属部署实例或其他持续计费资源,请停止并删除;在费用中心检查账单和代金券使用情况。7.3 删除本地敏感文件不再使用项目时,可删除包含 API Key 的部署包和环境变量文件:# Linux/macOS rm -f codeverse-ops-deploy.tar.gz rm -f codeverse-ops/.env.productionWindows PowerShell 执行:Remove-Item .\codeverse-ops-deploy.tar.gz -ErrorAction SilentlyContinue Remove-Item .\codeverse-ops\.env.production -ErrorAction SilentlyContinue若 API Key 曾出现在公开仓库、日志或截图中,应立即在 MaaS 控制台删除并重新创建。八、扩展资料华为云 MaaS OpenAI 兼容接口说明华为云 MaaS 模型列表弹性云服务器 ECS 文档弹性公网 IP 文档云容器引擎 CCE 文档函数工作流 FunctionGraph 文档九、案例验收清单完成以下检查即表示案例体验成功:[ ] 已开通 DeepSeek-V4-Flash,并使用华为云 MaaS API Key 完成接口验证;[ ] 如实践第三章,已通过码道完成 spec.md、design.md、tasks.md 和分阶段任务执行;[ ] ECS、EIP 和安全组配置完成;[ ] codeverse-ops 在 PM2 中为 online,Nginx 为 active;[ ] 浏览器可通过 ECS 公网 IP 打开首页;[ ] 单文件代码重构可通过任务 SSE 接口收到 complete 结果;[ ] 批量重构可显示批次和单文件状态;[ ] CCE 或 FunctionGraph 日志可生成根因分析和修复建议;[ ] 质量雷达图可展示原始代码与重构代码对比;[ ] AI 对话可逐段显示回复,仪表盘和收藏库可正常使用;[ ] 已确认模型输出仅作辅助并经过人工复核;[ ] 体验结束后已释放不再使用的计费资源和 API Key。
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体与 ECS 的 CoursePilot:AI 个性化学习闭环开发实践
    一、概述1.1 案例介绍在课程学习中,学生常常同时面对 PDF 讲义、Markdown 笔记、教材摘录和练习题等多种资料。传统学习工具通常只能解决“保存资料”或“回答问题”中的某一个环节,难以持续回答下面几个问题:一门课程到底包含哪些知识点,它们之间有什么层级和前置关系?学生目前真正薄弱的是哪些知识点,判断依据是什么?学习计划能否根据实际作答结果自动调整?AI 给出的知识点、题目和回答是否有课程资料依据?当模型或外部服务不可用时,核心学习流程能否继续运行?基于这些问题,我利用华为云码道(CodeArts)智能体开发了 CoursePilot。它不是一个只负责聊天的通用助手,而是一个以课程资料和学习证据为基础的 AI 个性化学习教练 Agent。系统围绕以下闭环工作:注册登录 → 创建课程 → 添加资料 → 构建知识结构 → 设置学习目标 → 初始诊断 → 生成知识画像 → 制定学习计划 → 学习与练习 → 错因分析 → 更新掌握度 → 动态调整计划 项目仓库:cid:link_7项目地址:115.120.251.21(由于成本限制,该IP发布帖子几日后可能会释放!)演示视频:项目仓库根目录 demo视频.mp41.2 核心设计原则课程无关:不把业务逻辑绑定到某一门固定课程。资料驱动:知识点、题目和学习辅导尽量建立在用户资料之上。来源可追溯:知识点和 AI 生成题目保留对应资料与分块来源。证据驱动:掌握度来自真实作答、难度、耗时和提示使用情况。人机协同:AI 负责提取、生成和辅助判断,用户保留确认与修正权。可解释与可审计:重要算法采用确定性规则,Skill 与 MCP 调用保存日志。可降级:大模型不可用时,资料解析、诊断和掌握度更新等核心流程仍可运行。1.3 适用对象希望完成 AI Agent 项目实践的高校学生;学习 Vue 3、FastAPI、MCP、Skill 与 Docker 的开发者;需要搭建课程资料管理、诊断或个性化学习系统的团队;希望了解如何将本地全栈应用部署到华为云 ECS 的开发者。1.4 案例时间本案例总时长预计240分钟。1.5 案例流程本案例采用“需求规格—架构设计—任务拆解—分阶段开发—测试验证—云端部署—迭代优化”的流程完成 CoursePilot 的设计与实现。使用华为云码道(CodeArts)代码智能体辅助完成需求分析,编写产品规格、功能需求和用户流程文档,明确 CoursePilot 的产品定位、功能范围、验收条件以及“资料驱动、证据驱动、来源可追溯”等核心原则,定义系统“做什么”。完成系统架构与技术方案设计,确定 Vue 3、FastAPI、SQLAlchemy、MCP、Skill 和 Docker Compose 技术栈,并编写领域模型、总体架构、MCP 设计、Skill 设计及关键算法 ADR,定义系统“怎么做”。根据需求和架构生成开发路线及阶段任务清单,将项目拆分为课程资料、知识结构、题库诊断、知识画像、学习计划、学习 Agent、MCP/Skill、学习看板和云端部署等可独立验收的开发任务。按照任务清单逐步开发:搭建 FastAPI 后端和 Vue 3 前端,实现用户认证、课程管理、资料解析、知识结构生成、AI 辅助出题、动态诊断、掌握度计算、个性化学习计划及渐进式辅导 Agent。建立 CoursePilot MCP Server,封装课程资料、题库、作答记录、学习状态和计划管理等工具;同时实现资料结构化、学习诊断、计划生成和苏格拉底式辅导等可插拔 Skill。使用码道代码智能体辅助进行跨文件代码审查、缺陷定位和测试补充;后端及 MCP Server 使用 Pytest 和 Ruff 验证,前端使用 TypeScript 类型检查、ESLint 和 Vite 生产构建验证。使用 Docker Compose 完成前端、后端和 MCP Server 的容器化编排,并部署至华为云 ECS;结合华为云 SWR 镜像加速解决基础镜像拉取问题,使用 Alembic 完成数据库迁移,并通过健康检查和容器日志验证服务状态。根据实际使用结果持续迭代,修复文件上传 413、AI 长任务 504、生成题目知识点 ID 越界、诊断中断后无法继续等问题,进一步提升系统的数据一致性、容错能力和用户体验。1.6 资源总览资源名称本案例使用规格主要用途计费说明弹性云服务器 ECS通用计算增强型 ac9s.large.2;2 vCPU;4 GiB;Ubuntu 24.04 Server 64 位;60 GiB 通用型 SSD运行前端、FastAPI 后端和 MCP Server 容器0.3452元/小时 弹性公网 IP EIP全动态 BGP;按流量计费;5 Mbit/s提供网站公网访问及 SSH 运维入口0.8元/GB虚拟私有云 VPC 和安全组1 个 VPC、1 个子网、1 个安全组提供私有网络及端口访问控制免费容器镜像服务 SWR使用个人专属镜像加速地址加速拉取 Python、Node.js 和 Nginx 等 Docker 基础镜像免费华为云码道(CodeArts)代码智能体专业版辅助需求分析、架构设计、任务拆解、代码开发、测试及问题定位专业版,139元/6000万tokens免排队MaaS - Console个人使用deepseek-v4-flash用于知识结构优化、AI 辅助出题及学习辅导输入:1元/百万tokens  输出:2元/百万tokensECS 本地存储SQLite 数据库及课程上传目录,共用 ECS 系统盘保存业务数据、课程资料和调用记录已包含在本案例 ECS 云硬盘配置中二、系统方案设计2.1 技术栈层级技术选型前端Vue 3、TypeScript、Pinia、Vue Router、Vite、AxiosWeb 服务Nginx后端Python 3.11、FastAPI、Pydantic、异步 SQLAlchemy数据迁移AlembicAgent 协议Model Context Protocol(MCP)业务能力4 个可插拔 Skill大模型接入OpenAI 兼容 Provider,用户自行配置模型数据库SQLite(案例演示);可切换 PostgreSQL容器化Docker、Docker Compose云资源华为云弹性云服务器 ECS、弹性公网 IP、安全组代码托管GitCodeAI 辅助开发华为云码道(CodeArts)代码智能体2.2 总体架构用户浏览器 │ ▼ Nginx / Vue 3 前端(80/443) │ /api/* ▼ FastAPI 后端(容器内部 8000) ├── SQLAlchemy / Alembic ── SQLite 或 PostgreSQL ├── 课程资料与上传文件 ├── LLM Provider ───────── 用户配置的大模型服务 └── MCP Client │ Streamable HTTP ▼ MCP Server(容器内部 8001) ├── 13 个业务工具 └── 4 个 CoursePilot 运行时 Skill2.3 项目结构CoursePilot/ ├── backend/ # FastAPI、领域模型、服务、Alembic 与测试 ├── frontend/ # Vue 3 前端 ├── mcp-server/ # MCP Server 与业务工具 ├── skills/ # 4 个 CoursePilot 运行时 Skill ├── docs/ # 需求、架构、ADR、验收与阶段报告 ├── AGENTS.md # 项目技术规范与协作约束 ├── docker-compose.yml └── README.md2.4 MCP 与 Skill 设计CoursePilot 的 MCP Server 提供 13 个业务工具,分为四类:课程与资料:课程列表、课程结构、资料检索、资料来源;学习状态:学生画像、知识点掌握度、错题;题库与作答:题目搜索、题目详情、保存作答;计划与掌握度:读取计划、更新计划、更新掌握度。系统还实现了 4 个运行时 Skill:Skill作用course_material_structuring将课程资料整理为知识结构learning_diagnosis根据作答证据分析学习状态和错因study_plan_generator生成及动态调整学习计划socratic_tutor使用分级提示进行启发式辅导三、使用华为云码道进行规范驱动开发3.1 建立项目上下文CoursePilot 涉及课程资料、题库、诊断、知识画像、计划、Agent、MCP 和 Skill 等多个领域。如果只用一句话要求 AI “生成一个学习平台”,很容易得到功能堆叠但规则不一致的代码。因此,本项目先在仓库中沉淀以下上下文:AGENTS.md:技术栈、目录结构、编码规范和测试命令;docs/product-spec.md:产品定位、范围和冻结决策;docs/requirements.md:功能需求与验收条件;docs/domain-model.md:领域实体、关系与约束;docs/architecture.md:系统边界与调用链;docs/adr/:掌握度算法、学习计划算法、Agent 编排等架构决策。3.2 各阶段Prompt每次使用时,可以先附加这段通用要求:请先阅读 AGENTS.md、本阶段相关设计文档和现有代码。 开始修改前必须: 1. 说明当前实现基线; 2. 给出任务拆解、影响文件和数据迁移方案; 3. 明确本阶段边界; 4. 不修改与本阶段无关的模块; 5. 不覆盖用户已有修改; 6. 实现后运行相关自动化测试和质量检查; 7. 最后报告修改文件、测试结果、未完成项和已知限制。 所有新增API统一放在 /api/v1/ 下。 后端IO操作优先使用 async/await。 数据库结构变更必须使用Alembic,不使用create_all代替迁移。 前端使用Vue 3、TypeScript、Pinia和<script setup lang="ts">。前置阶段:需求与规格设计请作为产品经理和系统架构师,为 CoursePilot 建立完整的需求与设计基线。 项目定位: CoursePilot 是一个课程无关、资料驱动、证据驱动、来源可追溯的AI个性化学习教练。系统需要形成: 创建课程 → 添加资料 → 构建知识结构 → 设置学习目标 → 初始诊断 → 知识画像 → 学习计划 → 学习与练习 → 错因诊断 → 掌握度更新 → 动态调整计划 请检查当前项目骨架,并编写或完善: - docs/product-spec.md - docs/requirements.md - docs/mvp-acceptance.md - docs/user-flows.md - docs/domain-model.md - docs/skill-design.md - docs/mcp-design.md - docs/development-roadmap.md - docs/current-gap-analysis.md 具体任务: 1. 定义目标用户、用户痛点、产品定位和产品边界; 2. 将需求划分为Must、Should、Could和Won't; 3. 为每项Must需求定义正常流程、异常流程和验收条件; 4. 使用Given/When/Then编写可执行验收标准; 5. 设计课程、资料、知识点、题目、诊断、画像、计划和Agent等领域实体; 6. 设计4个业务Skill及13个MCP工具; 7. 冻结掌握度、简答题、诊断题数量、模型Provider、账号体系和课程无关性决策; 8. 将开发工作拆分为阶段0至阶段7; 9. 明确每个阶段的目标、任务、边界、验收标准和交付物。 本阶段只编写需求和设计文档,不修改业务代码。 不得提前将尚未实现的功能标记为完成。阶段0:可运行基础设施基线请执行 CoursePilot 阶段0:可运行基础设施基线。 阶段目标: 让FastAPI后端、Vue前端、异步数据库、Alembic和MCP Server形成可启动、可测试的基础工程。 具体任务: 1. 修复FastAPI启动流程,确保GET /health返回200; 2. 建立统一的SQLAlchemy Base、异步engine和AsyncSession; 3. 配置Alembic target_metadata及异步迁移环境; 4. 验证upgrade head、downgrade base、再次upgrade head; 5. 统一Python模块路径和项目依赖,消除循环引用; 6. 修复Vue 3开发启动、TypeScript检查、ESLint和生产构建; 7. 将MCP Server统一为Streamable HTTP传输,端点为/mcp; 8. 确定FastAPI后端是唯一MCP Client,移除前端直连MCP的设计; 9. 修复后端、前端和MCP Server的Dockerfile及docker-compose.yml; 10. 建立后端健康检查、MCP连通性和前端页面加载冒烟测试; 11. 更新AGENTS.md和docs/deployment.md中的启动命令。 阶段边界: - 不实现课程CRUD; - 不实现资料解析; - 不创建完整业务领域模型; - 不实现正式业务Skill和MCP工具; - 不接入真实大模型; - 不实现完整注册、登录和管理员后台。 验收要求: - 后端、前端和MCP Server均可独立启动; - Alembic往返迁移通过; - MCP Streamable HTTP调用通过; - 前端type-check、lint和build通过; - docker compose config验证通过。阶段1:课程、资料与知识结构闭环请执行 CoursePilot 阶段1:课程、资料和知识结构垂直闭环。 请重点阅读: - docs/product-spec.md - docs/requirements.md中的FR-001至FR-003 - docs/domain-model.md - docs/user-flows.md中的流程1至流程4 - docs/mvp-acceptance.md中的AC-001至AC-003 阶段目标: 完成“创建课程→添加资料→解析资料→形成知识结构”的完整闭环。 具体任务: 1. 创建Course、CourseMaterial、MaterialChunk、KnowledgePoint和KnowledgeRelation模型; 2. 编写对应Alembic迁移、约束、外键和索引; 3. 实现课程创建、列表、详情、编辑和软删除API; 4. 实现PDF、Markdown、TXT文件上传及文本粘贴; 5. 实现资料状态、失败原因、重试和删除; 6. 实现规则型文本提取和资料分块; 7. 保存文件名、页码、章节或字符范围等来源信息; 8. 实现知识点新增、编辑、删除、排序和父子层级; 9. 实现prerequisite、contains和related知识关系; 10. 防止知识点关系自引用和循环依赖; 11. 实现课程列表、课程详情、资料管理和知识结构页面; 12. 使用两门内容不同的课程验证业务代码没有学科硬编码。 阶段边界: - 不实现题库和诊断; - 不实现知识画像、掌握度和学习计划; - 不实现正式业务Skill和MCP工具; - 不调用真实大模型。 验收要求: 用户能够创建课程,上传或粘贴资料,查看解析状态、资料分块和来源,并获得可编辑的树形知识结构。阶段2:题库、诊断与作答记录请执行 CoursePilot 阶段2:题库、初始诊断和作答记录。 请重点阅读: - requirements.md中的FR-004、FR-006和FR-010 - mvp-acceptance.md中的AC-004、AC-006和AC-010 - product-spec.md中的D-002和D-003 - domain-model.md中的题目、诊断和作答实体 阶段目标: 完成“建立题库→开始诊断→逐题作答→完成诊断”的业务流程。 具体任务: 1. 创建Question、QuestionOption和QuestionSource模型; 2. 创建question_knowledge_point多对多关联表; 3. 支持单选题、判断题和简答题; 4. 实现题目新增、编辑、删除、列表、筛选和审核状态; 5. 手动题目默认confirmed,AI或导入题目默认pending; 6. 题目必须关联至少一个当前课程知识点; 7. 保存题目对应的资料分块和来源位置; 8. 创建DiagnosticAttempt和AnswerRecord; 9. 按D-003规则选择诊断题: target_count = min(max(核心知识点数量, 10), 20); 10. 题库不足时阻止诊断并提示用户补充; 11. 诊断开始时保存不可变题目快照; 12. 保存答案、正确性、作答时间、跳过状态、提示次数和最高提示等级; 13. 实现L1至L4渐进式提示,L4完整解析需要二次确认; 14. 实现题库、诊断作答和诊断结果前端页面; 15. 为AI辅助出题预留接口,但本阶段不接入真实模型。 阶段边界: - 不计算知识画像和最终掌握度; - 不实现错因诊断; - 不实现学习目标和学习计划; - 不实现业务Skill、正式MCP工具和Agent。 验收要求: 用户能够管理题库并完成一次10至20题的诊断;系统保存完整作答证据,诊断题响应不得提前泄露正确答案和解析。阶段3:知识画像、错因诊断与掌握度请执行 CoursePilot 阶段3:知识画像、错因诊断和掌握度算法。 请重点阅读: - requirements.md中的FR-007、FR-011和FR-012 - mvp-acceptance.md中的对应验收条件 - product-spec.md中的D-001和D-002 - docs/adr/ADR-003-mastery-algorithm.md 阶段目标: 将用户作答记录转换为确定、可解释、可追溯的知识画像。 具体任务: 1. 创建MasteryRecord和ErrorDiagnosis模型及Alembic迁移; 2. 实现mastery-v1确定性掌握度算法; 3. 掌握度范围为0至100,置信度范围为0至1; 4. 算法考虑正确性、难度、作答时间、提示等级、连续错误、时间间隔和前置知识; 5. 使用Decimal和ROUND_HALF_UP,禁止依赖浮点round; 6. 每次有效证据追加MasteryRecord,不覆盖历史记录; 7. 保存旧值、新值、计算依据、变化原因和关联AnswerRecord; 8. 保证同一作答记录不会重复生成掌握度记录; 9. 实现10类规则型错因判断; 10. 保存错因类型、诊断依据、置信度、建议行动和关联知识点; 11. 支持用户确认或修改错因; 12. 实现知识画像列表和掌握度证据详情API; 13. 实现掌握度、置信度、薄弱点、待复习和证据链前端页面。 阶段边界: - 大模型不能直接计算或写入掌握度; - 本阶段不得调用真实LLM; - 不实现学习目标、学习计划和Agent; - 不实现正式业务Skill和MCP工具。 验收要求: 相同输入必须产生相同掌握度结果,每次变化均可追溯到具体作答记录;未经确认的简答题不得影响掌握度。阶段4:学习目标、计划与动态调整请执行 CoursePilot 阶段4:学习目标、个性化学习计划与动态调整。 请重点阅读: - requirements.md中的FR-005、FR-008和FR-013 - mvp-acceptance.md中的对应验收条件 - docs/adr/ADR-004-study-plan-algorithm.md 阶段目标: 根据学习目标、知识画像、知识点关系和时间约束生成确定、可解释的学习计划。 具体任务: 1. 创建LearningGoal、StudyPlan和StudyTask模型及迁移; 2. 每个用户每门课程只维护一个LearningGoal; 3. 支持目标日期、目标掌握度、每日时长和每周学习日; 4. 实现study-plan-v1确定性计划算法; 5. 根据掌握度差距、重要性、复习状态、连续错误和前置关系计算优先级; 6. 使用Kahn算法对前置关系稳定拓扑排序; 7. 检测知识点关系环; 8. 将任务分配到目标日期范围内的可用学习日; 9. 每日总时长不得超过daily_minutes; 10. 超过60分钟的任务拆分为多个子任务; 11. 容量不足时返回结构化错误和调整建议; 12. 每个任务保存generation_reason和generation_basis; 13. 支持完成、跳过、延期和手动调整; 14. 支持评估是否需要重新规划; 15. 重新规划时将旧计划设为superseded,并通过previous_plan_id保留历史; 16. 实现学习目标、当前计划和历史计划前端页面。 阶段边界: - 不调用真实大模型; - 不实现Agent、业务Skill和正式MCP工具; - 不实现错题本、学习看板、日历同步和消息推送。 验收要求: 计划生成结果可重复、可解释,不违反前置关系和时间容量;用户操作任务后能够评估调整需求并保留计划版本历史。阶段5:Skill、MCP、Agent 与 LLM Provider请执行 CoursePilot 阶段5:业务Skill、MCP工具、Agent和LLM Provider。 请重点阅读: - docs/skill-design.md - docs/mcp-design.md - docs/adr/ADR-005-agent-provider-and-orchestration.md - 阶段1至阶段4已经实现的业务服务 阶段目标: 建立可配置、可审计、可降级的CoursePilot Agent体系。 具体任务: 1. 删除course_recommend、schedule_optimizer和learning_analyzer占位Skill; 2. 实现4个正式Skill: - course_material_structuring - learning_diagnosis - study_plan_generator - socratic_tutor 3. 每个Skill包含skill.py、config.yaml和async execute(params); 4. Skill不直接操作数据库,通过业务服务或MCP工具获取数据; 5. 实现13个正式MCP业务工具; 6. 将MCP工具划分为只读工具和写入工具; 7. MCP Server通过BackendGateway调用FastAPI业务API; 8. 前端不得直接连接MCP Server; 9. 实现可配置的LLM Provider抽象; 10. 支持Mock Provider和OpenAI兼容Provider; 11. 自动测试只能使用Mock/Fake Provider; 12. 创建AgentSession、AgentMessage和ToolCallLog; 13. 实现Agent会话创建、消息发送、历史查询和结束会话; 14. 实现L1至L4苏格拉底式辅导; 15. 标记course_material、ai_supplement、mixed和unverified来源; 16. 所有Skill和MCP调用保存审计记录; 17. 对API Key、Token、Cookie、密码和密钥进行递归脱敏; 18. Agent写操作必须先请求用户确认; 19. 实现Agent对话和来源展示前端页面; 20. 实现Provider和MCP不可用时的规则降级。 阶段边界: - 不实现错题本和学习看板; - 不实现管理员后台; - 不允许把具体模型写成不可替换依赖; - Skill不得复制确定性掌握度和计划算法。 验收要求: 4个Skill和13个MCP工具能够独立调用;Agent可读取课程资料、画像和计划,能够恢复会话、显示来源、记录调用并在模型不可用时降级。阶段6:错题本、看板与日志展示请执行 CoursePilot 阶段6:完整前端交互、错题本、学习看板和调用日志展示。 请先检查阶段1至阶段5的数据模型和业务调用链,特别是: - AnswerRecord - DiagnosticAttemptQuestion不可变快照 - ErrorDiagnosis - MasteryRecord - StudyPlan和StudyTask - AgentSession和ToolCallLog 阶段目标: 补齐学习数据展示、错题复习和完整前端体验。 具体任务: 1. 实现WrongQuestionState模型及Alembic迁移; 2. 按user_id、course_id和question_id聚合错题; 3. 错题内容优先读取不可变题目快照; 4. 仅将有效错误作答计入错误次数; 5. 支持按知识点、错因、状态和关键词筛选; 6. 展示历史错误、资料来源、错因证据和掌握度证据; 7. 支持标记已掌握; 8. 用户后续再次答错时自动重新打开错题状态; 9. 复用DiagnosticAttempt体系创建单题练习; 10. 实现学习看板10类确定性指标; 11. 展示今日任务、总体进度、掌握度分布、薄弱点、待复习项、错因分布、本周有效作答时长和计划完成率; 12. 实现课程级ToolCallLog查询; 13. 支持类型、状态、工具、会话、时间和分页筛选; 14. 保存日志和查询输出时均执行敏感信息脱敏; 15. 实现错题本、看板和调用日志前端页面; 16. 完善加载状态、错误提示、空状态、导航、路由参数和刷新恢复。 阶段边界: - 不修改4个Skill核心逻辑; - 不修改13个MCP工具契约; - 不修改mastery-v1和study-plan-v1; - 不实现管理员后台和阶段7部署功能。 验收要求: 错题复习、学习看板和调用日志形成前后端闭环;跨用户访问统一返回404;页面刷新后数据可以从API恢复。3.3 Skill前端美化AI直接生成的前端通常不符合我们的胃口,存在以下问题:全站仍是系统默认字体、同一字号层级和同一种 8px 圆角,页面缺少品牌辨识度。紫色高饱和主色、纯白卡片加灰边框在所有页面重复,是典型的通用 AI 后台视觉。顶栏只是文本平铺,当前页面反馈弱,宽屏松散、窄屏拥挤。首页、课程列表和登录页过度居中,信息层级单薄;题库等高频页面则过密。按钮、表单、弹窗样式在各页面重复且状态不统一,Hover、Pressed、Focus 反馈不足。加载和空状态大多只是一行文字,视觉完成度不足。因此我们可以为Code添加Skill对前端进行美化我们选用GitHub - Leonxlnx/taste-skill: Taste-Skill - gives your AI good taste. stops the AI from generating boring, generic slop · GitHub 这个67.7k Star的Github开源skill进行优化请你根据skill修改现有前端界面,做的更好看一些效果也是很明显:美化前首页美化后首页四、核心功能实现具体核心功能展示请参考仓库内的demo视频,或者通过打开网站或本地部署实际操作,这里简单展示一下界面和操作功能4.1 从课程资料生成可追溯知识结构用户可以上传 PDF、Markdown、TXT 文件,或者直接粘贴文本。后端解析后将内容切分为资料块,并保存文件、位置与内容之间的对应关系。知识结构生成时,系统不会只保存一个无法解释的标题,而是将知识点关联到原始资料。用户可以查看、调整层级和关系,降低模型幻觉对后续诊断的影响。如果知识结构生成不清晰,你可以使用AI进行结构的优化,也可以手动进行修改,使结构更加清晰4.2 基于资料的 AI 辅助出题在题库管理界面你可以手动添加题目,也可以使用AI辅助出题AI 出题只允许引用当前课程中有效的知识点 ID 和资料块 ID。模型输出后,后端还会再次校验:题型和难度是否符合请求;knowledge_point_ids 是否属于允许范围;source_chunk_id 是否来自本次课程资料;选项、答案和解析结构是否完整。如果模型第一次返回了越界 ID,系统会把错误约束和合法范围反馈给模型并重试;连续失败时停止保存,避免产生半成品题目。4.3 测验与知识画像当题库足够完整,能够覆盖全部知识点时,可以进行测验与诊断:测验过程中可以申请不同等级的提示,或者跳过,但是这和答错一样会不同程度影响你的掌握度判定!系统不会让大模型直接决定最终掌握度,而是使用确定性规则综合以下证据:作答是否正确;题目难度;作答耗时;提示次数与提示等级;最近正确率;是否重复犯错;前置知识掌握情况。每次掌握度变化都会保存旧值、新值、变化原因和关联作答记录,用户能够查看“为什么发生了这次变化”。错题可以在“错题本”中进行复习,或者重新做题:4.4 学习计划与动态调整用户可以设置目标日期、目标掌握度、每日学习时长和每周可学习日期。系统根据知识画像、知识点重要程度、前置关系、历史错题和可用时间生成学习任务。当用户完成任务、连续答错或掌握度明显变化时,系统可以触发重新规划,并保留计划版本和调整原因。同时用户也可以在学习看板上查看一系列学习数据:4.5 渐进式学习辅导 Agent学习辅导 Agent 通过 MCP 工具读取当前课程资料、知识结构、学生画像和学习计划,再由 Skill 控制提示节奏:L1:提醒相关知识点;L2:指出思路方向;L3:给出关键步骤;L4:在用户确认后给出完整解析。回复通过 SSE 流式返回,并标记内容来自课程资料、AI 补充或混合来源。模型不可用时,系统可以降级为规则型提示。五、部署到华为云 ECS5.1 案例环境本案例采用一台华为云 ECS 完成演示部署:配置项案例选择区域华东-上海一ECS通用计算增强型,2 vCPU / 4 GiB操作系统Ubuntu 24.04 Server 64 位系统盘通用型 SSD,60 GiB公网访问弹性公网 IP,按流量计费,5 Mbit/s容器编排Docker Compose安全组:端口用途来源建议22SSH 运维仅允许管理员当前公网 IP /3280HTTP0.0.0.0/0443HTTPS0.0.0.0/05.2 登录服务器这里我采用的是密钥对登录:$key = "D:\EdgeDownload\KeyPair-e9f4.pem" icacls $key /inheritance:r icacls $key /grant:r "$($env:USERDOMAIN)\$($env:USERNAME):(R)" icacls $key先执行这一步是为了防止Window私钥文件权限过宽然后执行登录:ssh -i $key root@115.120.251.215.3 安装 Docker 和 Git登录 ECS 后执行:apt update apt install -y ca-certificates curl git install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo ${UBUNTU_CODENAME:-$VERSION_CODENAME}) stable" \ > /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable --now docker docker --version docker compose version这里可能会出现报错,可能是因为访问 Docker 官方源被重置。直接改用华为云 Docker 镜像源即可。curl -fsSL https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu $(. /etc/os-release && echo ${UBUNTU_CODENAME:-$VERSION_CODENAME}) stable" \ > /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable --now docker5.4 克隆 CoursePilot输入:cd /opt git clone cid:link_7.git cd CoursePilot5.5 创建生产环境变量先生成三个密钥,分别复制输出结果:python3 -c "import secrets; print(secrets.token_urlsafe(48))" python3 -c "import secrets; print(secrets.token_urlsafe(48))" python3 -c "import base64,secrets; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode())"创建环境变量文件:nano .env填入:SECRET_KEY=第一个随机值 MCP_INTERNAL_API_KEY=第二个随机值 LLM_CREDENTIAL_ENCRYPTION_KEY=第三个随机值 ALLOWED_ORIGINS=["http://你的EIP"]保存退出即可。5.6 添加持久化配置现有 Compose 没有持久化 SQLite 和上传文件,所以不要直接启动。创建覆盖文件:nano docker-compose.override.yml填入:services: backend: environment: DATABASE_URL: sqlite+aiosqlite:////data/coursepilot.db DEBUG: "False" SECRET_KEY: ${SECRET_KEY} LLM_CREDENTIAL_ENCRYPTION_KEY: ${LLM_CREDENTIAL_ENCRYPTION_KEY} MCP_INTERNAL_API_KEY: ${MCP_INTERNAL_API_KEY} MCP_SERVER_URL: http://mcp-server:8001/mcp UPLOAD_DIR: /data/uploads ALLOWED_ORIGINS: '${ALLOWED_ORIGINS}' volumes: - ./data:/data restart: unless-stopped frontend: restart: unless-stopped mcp-server: environment: BACKEND_API_URL: http://backend:8000/api/v1 MCP_INTERNAL_API_KEY: ${MCP_INTERNAL_API_KEY} restart: unless-stopped保存退出,创建数据目录:mkdir -p data/uploads chmod 700 data5.7. 构建并启动docker compose build --pull如果出现报错可能是因为Docker Hub 在大陆网络访问超时。需要给 Docker 配置华为云 SWR 镜像加速器。在华为云控制台:切换到“华东-上海一”。搜索并进入“容器镜像服务 SWR”。左侧选择“镜像资源 → 镜像中心”。点击“镜像加速器”。复制地址在ECS执行:mkdir -p /etc/docker nano /etc/docker/daemon.json填入复制的真实地址:{ "registry-mirrors": [ "https://xxxxxxxx.mirror.swr.myhuaweicloud.com" ] }保存退出即可!然后拉取基础镜像:docker pull python:3.11-slim docker pull node:20-alpine docker pull nginx:alpine三个都成功后,重新构建:cd /opt/CoursePilot docker compose build5.8 文件上传问题解决课程文件上传和 AI 知识结构优化都可能超过 Nginx 默认限制。可以在 /api/ 代理中补充:server { listen 80; server_name _; client_max_body_size 20m; location /api/ { proxy_pass http://backend:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }修改后重新构建并启动前端容器:docker compose build frontenddocker compose up -d --no-deps frontend六、问题排查与踩坑复盘AI生成的代码在一些小细节上会出现疏忽和错误,同时部署过程中一些文件的配置不完全也可能会带来一些问题。这里是我列出的一部分可能会出现的问题可解决方案,如果大家部署过程中产生错误可参考以下内容:6.1 Docker Hub 连接超时现象failed to resolve source metadata for docker.io/library/python:3.11-slimdial tcp ...:443: i/o timeout原因ECS 访问 Docker Hub 不稳定,构建阶段无法获取基础镜像元数据。解决配置华为云 SWR 镜像加速器,先单独执行 docker pull 验证,再重新执行 Compose 构建。拉取完成后若 referrers 请求偶发超时,可重试构建。6.2 Alembic 找不到 app 模块现象ModuleNotFoundError: No module named 'app'原因迁移进程启动时,后端源码目录没有进入 Python 模块搜索路径。解决docker compose run --rm \ -e PYTHONPATH=/app/backend \ backend python -m alembic upgrade head6.3 上传课程资料返回 413现象Request failed with status code 413原因请求在进入 FastAPI 前就被 Nginx 的默认请求体大小限制拒绝。解决在 Nginx server 中设置 client_max_body_size,同时保证该值不小于后端允许的上传上限。6.4 AI 优化知识结构返回 504现象Request failed with status code 504原因模型需要读取多份资料并生成分层结构,耗时超过 Nginx 默认代理等待时间。解决提高 proxy_read_timeout 和 proxy_send_timeout。更长期的方案是将长任务改造成异步任务,并通过任务状态接口或 SSE 返回进度。6.5 模型返回越界知识点 ID现象第 4 道题结构不合法:knowledge_point_ids 不在允许范围内原因旧逻辑只重试题型和难度错误,知识点 ID 到保存阶段才校验,模型没有纠正机会。解决将知识点 ID 和资料块 ID 校验前移到模型重试阶段,反馈非法值与允许范围;连续失败则停止整批保存。6.6 诊断退出后无法再次进入现象该课程已有进行中的诊断,attempt_id=...原因后端正确阻止了重复创建,但前端没有恢复已有 attempt 的入口。解决将“开始诊断”设计为幂等操作:发现进行中的 attempt 时直接返回原记录,前端显示“继续诊断”,再从下一道未答题恢复。八、案例总结CoursePilot 的开发让我认识到,AI Agent 应用的难点不只是“接入一个大模型”,而是如何把模型放进一个可信、可解释、可恢复的业务闭环中。在开发阶段,华为云码道(CodeArts)代码智能体的价值主要体现在:通过 Codebase 理解跨前后端、MCP 与 Skill 的项目上下文;将自然语言需求拆解成可执行、可追踪的开发任务;在多文件修改、测试补充和日志排障中提高效率;结合仓库规范与验收条件,减少无边界生成;帮助整理从本地开发到 ECS 部署的完整过程。在运行阶段,CoursePilot 则通过资料来源、确定性算法、用户确认、调用审计和降级策略约束大模型,让 AI 真正服务于学习过程,而不是只生成看似合理的答案。九、参考资料华为云社区 HCSD 板块华为云码道(CodeArts)代码智能体产品介绍华为云码道(CodeArts)代码智能体下载安装CoursePilot GitCode 项目仓库
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的上海药品监管信息平台
    基于华为云码道(CodeArts)代码智能体的上海药品监管信息平台项目仓库:https://github.com/jks0730/SH-Drug-Mgmt部署网址:http://120.46.223.11一、概述1.1 案例介绍药品流通业务涉及供应商、药店、物流企业与监管机构。传统表格式管理难以将药品批号、库存数量、订单履约、运输状态与企业资质建立稳定关联,出现异常时也难以快速定位责任节点。本项目以“上海药品监管信息平台”为实践对象,采用 Vue 3 + Vite 前端、Flask 后端与 SQLite 数据库实现 B/S 架构。系统围绕用户认证、企业认证、库存管理、B2B 供需、订单流转、物流上报、批次追溯、监管分析与操作审计建立数据闭环。1.2 适用对象需要学习 Vue 3 + Flask 前后端分离项目落地流程的开发者;希望了解 RBAC、JWT 与多租户数据隔离设计的学习者;需要构建库存预警、供应链协同、订单状态机或流通追溯系统的开发者;希望将项目过程整理为社区技术帖、课程设计或实训案例的同学。1.3 案例目标目标说明真实场景建模按企业、药品、批次、订单和运单梳理药品流通数据多角色协同为药店、供应商、物流、监管及管理员提供不同工作台全流程追溯将订单、批次、流通记录和物流节点关联起来风险前置对低库存、近效期、过期及运输异常提供预警基础文档可复现给出技术选型、核心代码、流程图与真实页面截图1.4 案例时间与资源资源用途成本Vue 3 + Vite前端页面与构建工具免费Flask + SQLAlchemyREST API 与业务逻辑免费SQLite开发环境业务数据免费Element Plus + ECharts表单、表格与监管可视化免费高德地图 API / WebSocket地图定位、路径与位置推送扩展按服务配置1.5 案例总流程系统业务从供应发布开始,经采购、履约、运输和收货后沉淀为库存与监管数据。下图为项目的总流程图。图 1:药品监管业务总流程。1.6 功能需求对应关系需求方向项目对应能力账户与权限注册、登录、密码重置、JWT 会话、RBAC 角色控制企业资质药店/供应商/物流企业认证与管理员审核库存管理药品批次、库存项、库存流水、效期与低库存预警供需协作供应信息发布、药店采购、订单确认与取消流通监管运单关联、物流节点上报、批次追溯与监管查询审计分析监管工作台、合规分析、操作日志二、环境和资源准备2.1 项目资源项目采用前后端分离结构:frontend 目录保存 Vue 3 前端,backend 目录保存 Flask API、模型和业务模块,data 目录保存示例数据,docs 目录保存项目文档和本文所引用的截图、流程图。2.2 本地开发环境工具推荐版本用途Node.js20+前端依赖安装与 Vite 开发服务Python3.8+Flask 后端运行环境npm与 Node.js 配套前端依赖管理Edge / Chrome现代版本页面访问与功能验证2.3 技术选型层级技术选型说明前端框架Vue 3 + Vite组件化开发与快速热更新UI 与图表Element Plus + ECharts管理端表格、表单、通知和统计图表后端框架Flask轻量 REST API 与模块化蓝图数据访问SQLAlchemy实体关系与事务管理身份授权Flask-JWT-Extended + RBAC保护 API 与限制角色功能范围数据库SQLite / PostgreSQL开发轻量化,生产可平滑扩展三、码道搭台:需求分析与系统设计3.1 向开发助手描述初始需求项目的初始需求可以概括为:构建一个服务于药店、供应商、物流企业和监管机构的药品监管平台。系统需要支持用户与企业认证、药品和批次库存、B2B 供需、采购订单、运输状态、药品流通追溯、库存预警、监管看板和操作审计;所有企业业务数据必须遵守租户隔离。该描述进一步拆分为用户权限、企业认证、库存、供需订单、流通物流、监管审计六类模块。3.2 功能模块划分模块核心功能主要页面 / API账户信息管理注册、登录、找回密码、角色权限Login.vue、Register.vue、/api/auth/*企业库存管理批次库存、入出库、库存预警Inventory.vue、/api/v1/inventory/*B2B 供求平台供应发布、采购下单、订单处理B2B.vue、/api/supply/*、/api/orders/*流通监管运单上报、物流状态、批次追溯Circulation*.vue、/api/circulation/*监管分析风险概览、企业监控、合规报告Analysis.vue、/api/regulator/*系统管理企业审核、用户管理、审计日志Admin*.vue、/api/admin/*3.3 系统架构设计前端通过 JWT 保存登录会话;后端按接口执行 RBAC 和租户边界校验;业务数据按药品库存、供给订单、流通物流和审计日志分类保存。高德地图与 WebSocket 作为定位和实时状态能力的扩展服务。图 2:药品监管平台技术架构。3.4 数据模型设计系统的核心实体包括:领域关键实体作用权限users、roles、permissions、user_roles账户、角色和细粒度权限企业tenants、enterprise_certifications企业资料与认证审核流程药品库存drugs、inventory_items、inventory_transactions药品主数据、批次余额与流水交易supply_info、orders、order_items供给信息与采购履约追溯circulation_records、logistics_records运单、节点状态与坐标审计operation_logs、password_reset_tokens关键操作留痕与密码安全库存项使用“企业 + 药品 + 批号”作为唯一维度;任何数量变化都单独记录为库存流水,不将来源企业或订单信息混入库存余额表。3.5 接口设计模块接口示例方法说明登录/api/auth/loginPOST校验账户,签发 JWT库存/api/v1/inventory/itemsGET / POST查询或新建企业库存批次库存预警/api/v1/inventory/warningsGET查询低库存、临期等风险项供应信息/api/supply/infoGET / POST查询或发布供给订单/api/ordersGET / POST查询或创建采购订单流通记录/api/circulation/*POST / GET上报或查询追溯节点管理审计/api/admin/audit-logsGET按条件查询审计日志四、码道领航:功能实现与界面落地4.1 账户、认证与角色会话注册成功后账号默认处于未认证状态,用户可提交企业认证;审核通过后获得对应业务角色。前端对 token 与用户信息做统一会话封装:// frontend/src/utils/authSession.js export const AUTH_TOKEN_KEY = 'access_token' export const AUTH_USER_KEY = 'current_user' export function setAuth(token, user) { if (token) localStorage.setItem(AUTH_TOKEN_KEY, token) if (user) localStorage.setItem(AUTH_USER_KEY, JSON.stringify(user)) } export function isAuthenticated() { return !!getToken() && !!getCurrentUser() } 图 3:账号注册页。图 4:登录页。4.2 批次库存、流水与租户隔离库存读写必须首先确认用户是否有当前企业的访问权。监管员和管理员具有额外查看范围,其余角色只能访问自身 tenant_id 对应的数据。# backend/inventory_warning.py def _ensure_tenant_access(user: User, tenant_id: int): if user.role in {'admin', 'regulator'}: return if not user.tenant_id: abort(403, description='当前账号尚未关联企业') if user.tenant_id != tenant_id: abort(403, description='无权访问其他企业库存') @bp.route('/items', methods=['GET']) @jwt_required() def list_inventory_items(): user = _get_current_inventory_user() tenant_id = request.args.get('tenant_id', type=int) if user.role not in {'admin', 'regulator'}: tenant_id = user.tenant_id _ensure_tenant_access(user, tenant_id) 4.3 B2B 订单状态流转药店创建订单后,订单从待确认开始。供应商负责确认与发货,物流企业负责在途更新和送达,药店确认收货后订单完成。待确认阶段存在药店取消、供应商拒绝和系统超时取消三条分支。图 5:B2B 采购订单状态流转。4.4 流通追溯与监管分析订单发货后生成流通记录,物流企业依据运单持续上传位置和状态。监管人员可按订单、运单或药品批号检索流通链路;库存预警、运输异常和认证风险能够进入监管工作台。图 6:监管分析仪表盘。4.5 UI 美化与多角色界面平台为不同角色提供各自导航、快捷入口和业务面板,避免将监管、采购和运输操作混在同一界面中。图 7:平台首页。图 8:药店运营仪表盘。图 9:供应协同仪表盘。图 10:物流履约仪表盘。五、关键技术难点与解决思路问题原因解决方式结果跨企业越权访问请求参数可能携带其他企业 ID后端根据角色覆盖或校验 tenant_id非监管角色不能读取其他企业库存库存余额无法追溯仅保存当前数量会丢失变动来源单独维护 inventory_transactions可按时间、订单与操作者回溯订单状态混乱多角色可操作同一订单以状态机约束可转换状态与操作角色履约过程可解释、可审计批次链路断裂库存、订单、物流独立建模在订单明细、流通记录中关联批号支持批次级追溯风险发现滞后仅在人工查询时发现临期或缺货定时扫描库存并提供预警 API可提前处理库存风险六、系统启动与验证6.1 启动后端cd backend python run.py后端默认运行于:http://127.0.0.1:50006.2 启动前端cd frontend npm install npm run dev前端默认运行于:http://127.0.0.1:51736.3 页面功能验证可依次验证注册、登录、企业认证、库存管理、供给发布、采购订单、物流工作台和监管工作台。密码找回页支持邮箱或手机号验证方式,验证码有效期按项目规则控制。图 11:找回密码页。6.4 API 验证# 登录获取 JWT curl -X POST http://127.0.0.1:5000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"pharmacy1","password":"password123"}' # 查询库存预警(需替换为实际 token) curl "http://127.0.0.1:5000/api/v1/inventory/warnings?page=1&per_page=20" \ -H "Authorization: Bearer <access_token>" # 查询采购订单 curl "http://127.0.0.1:5000/api/orders?page=1&per_page=20" \ -H "Authorization: Bearer <access_token>" 七、项目结构与成果文件7.1 项目目录SH-Drug-Mgmt/ ├── backend/ # Flask API、模型、业务模块与测试 │ ├── auth.py # 认证与密码管理 │ ├── inventory_warning.py # 库存与预警 │ ├── orders.py # 订单管理 │ ├── circulation.py # 流通追溯 │ ├── logistics.py # 物流状态 │ └── models.py # SQLAlchemy 模型 ├── frontend/ # Vue 3 前端 │ └── src/ │ ├── views/ # 角色页面与业务页面 │ ├── api/ # API 调用封装 │ ├── router/ # 路由守卫 │ └── utils/ # 会话、角色和地图工具 ├── data/ # 示例数据 └── docs/ ├── 上海药品监管信息平台-项目展示帖.md └── post-assets/ # 真实截图与流程图 PNG7.2 成果文件文件说明docs/上海药品监管信息平台-项目展示帖.md本项目展示帖docs/post-assets/real-screenshots/本地项目真实页面截图docs/post-assets/flowcharts/图像流程图与架构图backend/tests/后端测试用例frontend/tests/前端单元测试八、总结与展望本项目将药品批次、库存流水、供应信息、订单履约、物流节点和监管分析放入同一条数据链路中。与单一库存管理页面相比,它更关注多企业之间的数据协同、状态可控和过程可审计。后续可以从以下方向继续完善:接入冷链传感器数据,扩展温湿度异常预警;引入电子签章、召回流程与更严格的资质文件校验;扩展监管报表、风险规则引擎和跨区域流通分析;在 PostgreSQL 与消息队列基础上增强并发处理和实时推送能力;根据生产环境合规要求完善脱敏、备份、监控和审计策略。九、使用华为云码道(CodeArts)代码智能体辅助开发9.1 开发流程概述本项目在需求梳理、设计评审、编码实现、测试验证与部署脚本整理等阶段使用华为云码道(CodeArts)代码智能体进行辅助。整体采用以需求和设计为先的 SDD(Specification-Driven Development)思路:先明确业务角色、数据边界和验收规则,再拆分任务并实施代码,最后通过测试和部署验证形成反馈闭环。图 12:CodeArts 辅助的需求—设计—实现—测试—部署闭环。9.2 需求细化与设计文档审查项目启动时,先向 CodeArts 描述上海药品监管信息平台的业务目标、技术栈与核心约束:Vue 3 + Vite 前端、Flask 后端、SQLite 数据库、JWT 会话、RBAC 权限控制,以及药店、供应商、物流、监管员和管理员等多角色协作。随后由代码智能体读取项目目录、现有需求和技术约束,对药品批次、库存流水、采购订单、物流节点、企业认证、租户隔离与监管审计等内容进行系统性梳理。图 13:通过自然语言描述项目目标后,CodeArts 对项目代码与文档进行探索。在设计优化阶段,结合规划框架进一步审查需求澄清、架构决策、任务拆分、代码质量和测试保障等内容,重点检查角色权限边界、订单状态流转、批次追溯关系和风险预警场景。图 14:使用 CodeArts 对药品监管平台设计文档进行针对性优化。9.3 SDD 文档驱动与任务拆分围绕项目需求,可将设计工作沉淀为以下三类 SDD 文档:文档类型核心内容对应项目范围需求规格(spec)定义“做什么”、角色规则与验收条件认证、库存、供需、订单、物流、追溯、监管详细设计(design)定义“如何做”、数据模型、接口和页面交互Flask API、Vue 页面、RBAC、租户隔离、状态机任务清单(tasks)将设计拆分为可验证的开发任务模型、接口、页面、测试、部署与验收CodeArts 可依据自然语言需求协助补全结构化需求条目、接口边界与任务验收条件,减少因角色职责不清、库存与订单数据脱节或状态机遗漏带来的设计偏差。9.4 代码生成与迭代辅助在实现和迭代阶段,代码智能体主要辅助以下工作:数据模型与接口骨架:围绕用户、企业、药品、库存、供应信息、订单、流通记录与操作日志等实体,协助完善 SQLAlchemy 模型、字段校验和接口参数定义;业务规则实现:针对 JWT 鉴权、RBAC 权限、租户隔离、库存预警、订单状态机和批次追溯,协助定位规则边界并生成或优化后端逻辑;前端页面开发:围绕登录注册、企业认证、库存管理、B2B 采购、物流工作台和监管看板,协助生成 Vue 组件、路由守卫、状态管理和 API 调用代码;问题定位与修复:结合报错信息和调用链,对接口鉴权、数据校验、页面交互、依赖配置与样式问题给出排查方向和修复建议。9.5 测试、调试与部署辅助测试阶段可根据核心业务链路补充后端单元测试、API 集成测试和前端 Store/工具函数测试,重点覆盖:认证与权限、库存与预警、订单创建与状态流转、物流状态更新、批次追溯以及监管查询。部署与运维阶段,项目现有的部署脚本、Nginx 配置与 systemd 服务文件可作为自动化基础。CodeArts 可辅助检查部署命令、依赖安装、数据库初始化、前端构建产物发布、反向代理和服务守护配置,并根据验证结果回流到需求和设计文档,形成持续优化闭环。
  • [高校训练营] 基于华为码道(CodeArts)代码智能体开发的音乐分享平台
    基于华为云码道(CodeArts)的音乐共享平台开发——同济大学小学期课程实践一、项目概述1.1 项目简介本项目是一个基于华为云码道(CodeArts)代码智能体辅助开发的音乐共享平台,聚焦音乐内容管理、社区互动交流与个性化推荐三类核心能力。系统采用前后端分离架构,覆盖需求分析、系统设计、编码实现、联调测试与演示部署等完整开发流程,目标是构建一个可运行、可展示、可扩展的音乐社区平台。1.2 项目目标构建一个支持音乐上传/播放/搜索、用户社区互动、好友私聊、智能推荐等功能的音乐共享社区平台,要求:前后端分离架构,RESTful API设计完整的用户认证与权限控制多模块业务逻辑(音乐、社区、社交、推荐)可运行、可演示、可扩展1.3 技术选型层级技术选型理由前端React 18 + TypeScript + Vite + Ant Design 5 + Zustand组件化开发、类型安全、状态管理轻量后端Spring Boot 3 + MyBatis-Plus + JWT企业级框架、ORM简化、无状态认证数据库MySQL 8.0关系型数据、事务支持、成熟生态存储本地文件系统教学演示场景,避免OSS配置复杂度AI工具华为云码道(CodeArts)代码智能体课程指定开发工具1.4 项目链接视频演示:https://pan.quark.cn/s/e35f0aa3fe99项目源码仓库:https://github.com/rev2352350/music-sharing-platform二、AI辅助开发流程2.1 Day 1:需求分析与系统设计需求描述与补全在码道对话框中输入项目需求后,AI并非直接生成代码,而是首先执行需求补全——自动识别出原始需求中遗漏的关键设计决策:补全项说明优先级权限控制RBAC模型:普通用户/管理员,接口级权限校验P0隐私控制歌单公开/私密、下载记录仅自己可见P0文件上传限制音频≤50MB,格式限制MP3/WAV/FLAC/AACP0内容审核音乐上传需审核、举报机制P0分页与搜索统一分页参数、模糊搜索、多维度排序P1通知系统评论/好友/私聊通知P2在对话中输入"设计并实现一个音乐平台+音乐社区的Web项目,包含用户系统、音乐功能、搜索发现、收藏歌单、社区交流、智能推荐、管理后台、好友私聊、消息通知等功能"后,码道并未直接生成代码,而是首先对需求进行补全——自动识别出权限控制(RBAC)、隐私控制(歌单公开/私密)、文件上传限制、内容审核机制等原始需求中未明确的关键设计决策,并按P0/P1/P2优先级分类呈现。这一步的价值在于:AI充当了需求评审者的角色,帮助在编码前就识别出潜在的设计缺陷,避免了传统开发中"做到一半才发现遗漏"的问题。系统设计文档生成确认需求后,码道自动生成了一份结构化的系统设计文档(design.md),包含以下内容:数据库设计——17张业务表,完整的字段定义、约束和ER关系:User ──1:N──> Playlist ──M:N──> Music (via playlist_music) User ──1:N──> Collection ──N:1──> Music User ──1:N──> Rating ──N:1──> Music User ──1:N──> Comment ──N:1──> Music User ──1:N──> Post ──1:N──> PostComment User ──1:N──> Like (polymorphic: post/comment) User ──1:N──> Friendship ──1:N──> PrivateMessage Music ──M:N──> Tag (via music_tag) Music ──N:1──> CategoryAPI设计——8大模块、40+接口,统一的请求/响应规范:// 统一响应格式 { "code": 200, "message": "success", "data": {} } // 统一分页格式 { "total": 100, "pageNum": 1, "pageSize": 20, "list": [] } 推荐算法——基于标签相似度的个性化推荐,含冷启动降级策略。2.2 Day 2:核心功能编码后端实现基于设计文档,码道按照标准分层架构生成后端代码:com.music.platform/ ├── entity/ # 17个实体类(Music, User, Post, Friendship...) ├── dto/ # 请求DTO(MusicUploadDTO, PostDTO...) ├── vo/ # 响应VO(MusicVO, PostVO, ChatVO...) ├── mapper/ # MyBatis-Plus Mapper接口 ├── service/impl/ # 业务逻辑实现 ├── controller/ # REST控制器 ├── config/ # JWT拦截器、CORS、Security、上传配置 └── common/ # 统一响应R<T>、全局异常处理、UserContext后端按照标准分层架构组织代码:com.music.platform/ ├── entity/ # 17个实体类(Music, User, Post, Friendship...) ├── dto/ # 请求DTO(MusicUploadDTO, PostDTO...) ├── vo/ # 响应VO(MusicVO, PostVO, ChatVO...) ├── mapper/ # MyBatis-Plus Mapper接口 ├── service/impl/ # 业务逻辑实现 ├── controller/ # REST控制器 ├── config/ # JWT拦截器、CORS、Security、上传配置 └── common/ # 统一响应R<T>、全局异常处理、UserContext关键设计决策:JWT双Token机制:Access Token(30min)+ Refresh Token(7天),前端检测401自动刷新,避免用户频繁重新登录收藏/评分切换模式:重复操作自动取消而非报错,简化前端逻辑多态点赞:like_record表通过target_type字段支持动态和评论的统一点赞软删除:所有业务表使用deleted字段,保证数据可恢复前端实现前端采用React + Ant Design,码道生成了20+页面组件:页面核心功能首页热门推荐、最新上传、分类推荐歌曲详情播放、收藏、评分、歌词居中显示、评论、分享到社区社区动态发布动态、搜索选歌分享、评论、点赞个人主页动态、上传的歌曲、好友、歌单、收藏消息中心私聊窗口、通知列表、好友请求上传音乐音频+封面+歌词上传、分享到动态开关数据库初始化码道生成了完整的SQL脚本,包含建表语句和测试数据(5个用户、10首歌曲、分类标签、评论动态等)。2.3 Day 3:联调排错与功能迭代第三天是工作量最大的一天,主要处理运行时问题和功能增量开发。典型问题与解决问题1:PowerShell编码陷阱PowerShell的Set-Content默认使用GBK编码,导致Maven编译UTF-8源码时中文乱码。码道将中文消息字符串替换为英文,从根源上规避编码问题。问题2:类名冲突收藏实体类命名为Collection,与java.util.Collection冲突。码道将其重命名为UserCollection,并同步更新所有Mapper、Service、Controller中的引用。问题3:JWT认证401状态码被吞BusinessException(401)返回HTTP 200 + 业务码401,前端axios拦截器无法识别为认证失败。修改GlobalExceptionHandler,让401业务异常返回HTTP 401状态码:// GlobalExceptionHandler.java if (e.getCode() == 401) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } 前端配合实现Token自动刷新机制:检测到401响应时,用RefreshToken换取新AccessToken,自动重发原请求。问题4:文件位置与包名不一致JwtInterceptor.java文件放在interceptor目录下,但package声明为com.music.platform.config,导致运行时ClassNotFoundException。将文件移至config目录使其与包声明一致。问题5:歌词换行符处理MySQL存储的歌词中\n是字面量而非换行符,前端显示为一整行文本。解决方案:// 前端歌词渲染 music.lyrics.replace(/\\n/g, '\n').split('\n').map((line, i) => { const text = line.replace(/\[\d{2}:\d{2}\.\d{2,3}\]/g, '').trim() if (!text) return <div key={i} style={{ height: 16 }} /> return <div key={i}>{text}</div> }) 实现居中排版、去除时间标签、空行分段,达到类似百度音乐的歌词展示效果。问题6:BCrypt密码中的$符号PowerShell中BCrypt密码的$符号被解释为变量,直接命令行更新失败。改用SQL文件方式执行,避免Shell变量替换。功能迭代联调通过后,通过对话式需求描述进行增量开发:迭代需求描述实现内容好友系统“加好友、私聊”新增3张表(friendship, private_message, notification),完整的好友申请/同意/拒绝流程播放器增强“加进度条和音量控制”进度条、时间显示、音量滑块、单曲循环上传自动发动态“上传的歌自动分享到动态”MusicServiceImpl注入PostService,上传后自动创建动态,含"分享到动态"开关社区选歌分享“发布动态时可以选择歌曲”搜索选歌Select组件,动态关联musicId歌曲分享按钮“每首歌要有分享按钮”详情页分享按钮+配文弹窗,一键分享到社区个人主页上传tab“看到这个人上传的歌”新增/users/{id}/uploaded接口,Profile页面新增tab三、系统架构3.1 整体架构┌─────────────────────────────────────────────────┐ │ React SPA │ │ (Vite + Ant Design + Zustand + React Router) │ └──────────────────────┬──────────────────────────┘ │ HTTP/REST API (JWT Bearer) ┌──────────────────────▼──────────────────────────┐ │ Spring Boot 应用层 │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │Controller│ │ Service │ │ Interceptor │ │ │ └────┬─────┘ └────┬─────┘ │ (JWT认证/权限) │ │ │ │ │ └──────────────────┘ │ │ ┌────▼─────┐ │ │ │ Mapper │ │ │ └────┬─────┘ │ └───────┼───────────────────────────────────────────┘ │ ┌────▼────┐ │ MySQL │ └─────────┘3.2 核心设计原则前后端分离:后端仅提供RESTful API,前端SPA独立部署JWT无状态认证:双Token机制,前端自动刷新统一响应格式:{code, message, data},全局异常处理软删除:所有业务表使用逻辑删除(deleted字段)审计字段:所有表包含created_at, updated_at四、项目成果4.1 功能完成度模块已实现功能状态用户注册、登录、退出、资料编辑、头像上传、个人主页✅音乐上传、播放、搜索、详情、收藏、评分、评论、歌词、分享✅歌单创建、编辑、删除、添加/移除歌曲、公开/私密✅社区发布动态、选歌分享、评论、点赞(切换模式)✅好友加好友、同意/拒绝、好友列表、状态查询✅私聊发送消息、聊天列表、聊天窗口✅通知评论通知、好友请求、私聊通知、全部已读✅推荐热门/最新/分类推荐、标签相似度个性化推荐✅管理用户管理、音乐审核、统计仪表盘✅播放器进度条、时间显示、音量控制、单曲循环✅4.2 代码规模模块文件数代码行数(估算)后端Java50+~8000行前端React/TS20+~5000行SQL脚本3~500行设计文档1~600行4.3 运行效果展示五、反思与改进5.1 AI辅助开发的有效性分析环节AI表现评价需求补全自动识别遗漏项(权限、隐私、审核)优秀——弥补了需求描述的不足架构设计生成完整设计文档(表结构、API、推荐算法)优秀——结构清晰,可直接作为开发蓝图代码生成分层架构、命名规范、业务逻辑完整良好——核心逻辑正确,但需运行验证运行排错能定位问题根因并给出修复方案良好——但Windows环境适配问题需人工判断功能迭代对话式增量开发,理解上下文良好——简单需求一次通过,复杂需求需多轮交互5.2 当前不足与改进方向功能层面:单元测试缺失:当前项目未编写自动化测试,依赖手动验证。后续应补充Service层单元测试和Controller层集成测试管理后台不完善:目前仅实现了基础的审核和统计功能,评论管理、动态管理、举报处理等尚未完整推荐算法较简单:当前基于标签相似度,后续可引入基于用户的协同过滤(User-CF)提升推荐质量工程层面:缺少Docker部署方案:目前依赖本地环境手动启动,应编写Docker Compose配置实现一键部署未接入Redis缓存:设计文档中规划了Redis用于会话管理和热门数据缓存,但因环境限制暂未实现前端状态管理可优化:部分页面存在重复请求,应引入缓存策略和请求去重机制安全层面:JWT黑名单未实现:当前Token签发后无法主动失效,应结合Redis实现Token黑名单文件上传安全:未对上传文件内容进行深度校验(如文件头验证),存在潜在安全风险SQL注入:MyBatis-Plus的LambdaQueryWrapper已参数化查询,但自定义SQL需注意5.3 与同类项目的对比与其他选题相比,音乐共享平台的特殊挑战在于:媒体文件处理:音频文件体积大(50MB+),需要考虑上传限制、流式播放、存储策略实时交互需求:私聊消息、通知推送等场景对实时性有要求,当前采用轮询方式,后续可引入WebSocket推荐系统复杂度:音乐推荐的冷启动问题比商品推荐更突出,因为用户行为数据更稀疏社区互动模式:动态+评论+点赞的多态交互设计,比简单的CRUD更复杂六、总结本项目通过华为云码道(CodeArts)代码智能体,在三天内完成了一个包含9大功能模块、17张数据库表、40+API接口的音乐共享平台。从实践来看,AI辅助开发在需求分析和代码生成环节效率提升显著,但在运行时排错和环境适配方面仍需开发者具备足够的技术判断力。AI编程工具并非"替代程序员",而是将开发者从重复性编码工作中解放出来,使其能将更多精力投入到架构决策、业务逻辑设计和质量保障上。对于课程项目而言,这种开发模式让学生能更关注软件工程的全流程理解,而非陷入语法细节的泥潭。项目信息:技术栈:Spring Boot 3 + React 18 + MySQL 8.0开发工具:华为云码道(CodeArts)代码智能体开发周期:3天代码规模:13000+行
  • [高校训练营] 银发智伴:基于华为云码道(CodeArts)代码智能体的智能体检报告应用
    一、概述1.1 案例介绍银发智伴(ElderlyCare AI) 是一款面向子女、老年家庭成员和应用后台管理员三类用户的智能体检报告管理应用。子女可在 PC 端上传父母的 PDF、JPG 或 PNG 体检报告,系统通过 OCR 识别、指标提取和大模型健康解读,将专业检验结果转换为通俗说明、健康建议和饮食计划;随后生成适老化 H5 分享链接与二维码,父母通过手机即可查看大字版报告并使用语音播报。后台管理员负责用户状态、角色、系统概览和审计信息管理,不参与用户报告内容的日常操作。本案例采用 FastAPI、Vue 3、SQLite、Redis、Nginx 和华为云 ECS 构建,集成华为云 OBS 与 OCR,并使用华为云码道(CodeArts)代码智能体完成需求分析、存量代码理解、任务拆解、增量开发和问题调试。应用还提供家庭成员管理、历年指标趋势、异常变化提醒、报告对比、分享密码、访问次数限制和后台治理,形成“报告上传、智能解析、健康解读、长期跟踪、适老分享、后台治理”的完整业务闭环。GitCode 源码与演示视频:https://gitcode.com/SDSXshlbz/elderlycare-ai本案例中的演示账号、家庭成员和体检指标均为合成数据,不对应任何真实个人。健康解读仅供参考,不构成医疗诊断建议。1.2 适用对象企业开发者个人开发者高校学生学习本案例前,建议具备 Python、JavaScript、Linux 常用命令和 HTTP API 的基础知识。1.3 案例时间本案例总时长预计90分钟,其中云资源准备约20分钟,项目配置与部署约40分钟,功能验证与资源清理约30分钟。1.4 案例流程[1. 准备云资源] | v [2. 配置项目与密钥] -> [3. 构建 PC/H5 前端和 FastAPI 后端] | v [5. H5适老分享] <- [4. OCR识别、指标提取与健康解读]说明:在华为云创建 ECS、VPC、安全组、EIP 和 OBS 桶,公网仅长期开放演示所需的 80 端口;准备华为云 AK/SK、OCR、OBS 和大模型配置,通过 .env 注入运行参数,不将密钥写入源码;将源码上传到 Ubuntu 22.04 ECS,执行 deploy_ecs.sh,自动安装依赖、构建两个前端并配置 Nginx、Redis 和 systemd;用户上传报告后,后端依次完成 OCR 降级识别、指标提取、风险判定、健康解读和饮食计划生成;子女在 PC 端查看趋势和对比结果,并生成带二维码、可选访问密码和语音播报的适老化 H5 分享页面。1.5 资源总览本案例使用按需计费资源,建议将完整体验控制在2小时内。不同区域和活动价格可能变化,实际费用以华为云控制台订单页为准。体验完成后请及时释放 ECS、EIP 和不再使用的 OBS 数据,避免产生多余费用。资源名称规格单价(元)弹性云服务器 ECS通用计算增强型 c7.large.2 | 2 vCPUs | 4 GiB | Ubuntu 22.04 Server | 40 GiB GPSSD以控制台实时价格为准弹性公网IP(Elastic IP,简称EIP)按流量计费 | 5Mbit/s按实际公网流量计费虚拟私有云 VPC 和安全组1个VPC、1个子网、1个安全组VPC和安全组本身免费对象存储服务 OBS标准存储,用于报告文件、二维码等对象按存储量与请求次数计费文字识别 OCR通用文字识别、通用表格识别按调用量计费或使用套餐包华为云码道(CodeArts)代码智能体通用体验版以开通页面为准阿里云百炼大模型 APIqwen-turbo、qwen-vl-ocr、qwen-vl-plus按模型调用量计费二、环境和资源准备2.1 购买华为云 ECS 弹性云服务器登录华为云控制台,依次进入 服务列表 > 计算 > 弹性云服务器 ECS,点击 购买弹性云服务器。计费模式选择 按需计费,区域选择 北京四 cn-north-4,规格选择 通用计算增强型 c7.large.2,2 vCPUs,4 GiB。镜像选择 Ubuntu Server 22.04 64bit,系统盘选择 40 GiB GPSSD。创建或选择 VPC 与子网,购买 5Mbit/s、按流量计费 的弹性公网 IP。创建安全组,长期入方向规则只放行 TCP/80。部署期间如需 SSH,可临时放行 TCP/22,并将源地址限制为管理员当前公网 IP,部署完成后立即删除 22 端口规则。点击 立即购买,确认按需资源并等待 ECS 状态变为“运行中”。记录 ECS 公网 IP,后文用 <ECS公网IP> 表示。关键节点说明:安全组只控制云侧入站流量,Nginx 仍需在实例内监听 80 端口。后端 Uvicorn 仅监听 127.0.0.1:8005,不能绕过 Nginx 直接从公网访问。2.2 准备华为云 OBS、OCR 和访问密钥进入 服务列表 > 存储 > 对象存储服务 OBS,创建私有桶,例如 elderlycare,区域需与 ECS 一致。进入 服务列表 > 人工智能 > 文字识别 OCR,开通通用文字识别和通用表格识别。点击控制台右上角用户名,进入 我的凭证 > 访问密钥,创建并妥善保存 AK/SK。在 我的凭证 > API凭证 中记录项目 ID,项目所属区域应为 cn-north-4。AK/SK 具有云资源访问权限,只能写入服务器上的 .env,不得提交到 Git、案例文档、截图或前端代码中。OBS 桶保持私有,文件由后端 SDK 访问。2.3 准备大模型与 OCR 降级服务登录阿里云百炼控制台,地址:https://dashscope.console.aliyun.com/,开通 DashScope 服务。在 API-KEY 管理 中创建 API Key,并确认账号可调用 qwen-turbo、qwen-vl-ocr 和 qwen-vl-plus。将 API Key 仅配置在 .env 中。项目首先调用华为云 OCR;若该调用失败,再依次尝试 qwen-vl-ocr 和 qwen-vl-plus,避免单一识别服务异常导致整条解析链路不可用。2.4 准备本地和云端环境本案例以 Windows 作为开发端、Ubuntu 作为运行端,建议环境如下:环境软件及版本用途Windows 10/11PowerShell 5.1+、OpenSSH Client、tar.exe源码检查、测试、打包和上传本地 PythonPython 3.10+,本案例测试环境为 Python 3.12后端测试本地 Node.jsNode.js 20、npm 10PC/H5 生产构建Ubuntu ECSUbuntu 22.04、Python 3.10、Node.js 20、Nginx、Redis演示环境运行执行以下命令复制配置模板:Copy-Item .env.example .env编辑 .env,将占位内容替换为实际配置。不要删除未使用的键,也不要在等号两侧添加多余引号:HUAWEI_CLOUD_AK=你的华为云AK HUAWEI_CLOUD_SK=你的华为云SK HUAWEI_CLOUD_REGION=cn-north-4 HUAWEI_CLOUD_PROJECT_ID=你的华为云项目ID OBS_BUCKET_NAME=elderlycare OBS_ENDPOINT=obs.cn-north-4.myhuaweicloud.com JWT_SECRET_KEY=至少32字节的随机字符串 REDIS_URL=redis://localhost:6379/0 DATABASE_URL=sqlite+aiosqlite:///./elderlycare.db MCP_SERVER_URL= LLM_API_KEY=你的千问APIKey LLM_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1 LLM_MODEL_NAME=qwen-turbo ALIYUN_OCR_API_KEY=你的阿里云OCR_APIKey ALIYUN_OCR_MODEL=qwen-vl-ocr SHARE_BASE_URL=http://<ECS公网IP>/h5在 Windows PowerShell 中生成随机 JWT 密钥:$bytes = New-Object byte[] 48 [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes) [Convert]::ToBase64String($bytes) 三、构建银发智伴应用3.1 使用 CodeArts 代码智能体创建项目登录华为云码道(CodeArts),创建 Python + Vue 3 项目。在 CodeArts IDE 中输入以下需求描述,让代码智能体先理解目标和约束,再结合本案例存量源码进行增量开发:创建“银发智伴”体检报告管理应用。后端使用 Python FastAPI 和 SQLAlchemy Async,PC 端与 H5 端使用 Vue 3。子女在 PC 端上传父母体检报告,后端通过 OCR 提取指标,生成健康解读、饮食计划、趋势分析和报告对比;H5 使用大字号、清晰风险标签和中文语音播报。项目部署到 Ubuntu ECS,由 Nginx 统一提供 PC、H5 和 API 入口。本项目工作区保留了代码智能体生成并持续修订的规格、设计和任务文件,使用过程如下:阶段代码智能体产物或操作人工确认的关键节点需求规格化.codeartsdoer/specs/elderlycare_ai/spec.md明确子女、父母、管理员三类角色,以及“仅提供健康参考、不替代医生诊断”的职责边界存量代码分析.codeartsdoer/specs/elderlycare_ai/design.md对照现有认证、报告和分享模块,判断哪些功能复用、哪些功能增量扩展,避免大幅改变原有结构任务拆解.codeartsdoer/specs/elderlycare_ai/tasks.md将工作拆分为认证、报告、OCR、健康解读、分享、管理员、测试和部署等可验证任务代码开发根据任务逐个生成或补全 FastAPI 服务、Vue 页面和部署配置审查接口权限、异步数据库事务、上传限制、异常映射和前后端字段契约调试验证结合错误日志定位登录、复制、H5 子路径和 Ubuntu 兼容问题每次修复后执行后端测试、两个前端生产构建和 ECS 健康检查本案例使用代码智能体辅助完成的典型调试过程如下:登录错误调试:根据后端日志和认证服务调用链,发现错误凭据触发的业务异常未正确映射。修正空用户判断和异常处理器后,错误账号由 HTTP 500 变为 HTTP 401,并返回“账号或密码错误”;分享链接复制调试:公网演示环境使用 HTTP,浏览器可能禁用安全上下文中的 Clipboard API。智能体协助定位兼容性原因,并在 navigator.clipboard.writeText() 失败时使用 document.execCommand('copy') 回退;Windows 到 Ubuntu 迁移调试:检查 CRLF/LF、文件名大小写、依赖锁文件和路径分隔符;前端使用 npm ci 复现依赖,部署脚本保持 LF,源码导入路径与真实文件名大小写一致;H5 子路径调试:统一 Vite base: '/h5/'、Vue Router 的 import.meta.env.BASE_URL 与 Nginx try_files,解决分享深层路由刷新 404;验证闭环:本地运行 python -m pytest tests -q,分别执行 PC/H5 的 npm run build,部署后访问 /health,并验证登录、趋势、对比、分享和管理员接口。代码智能体用于加速分析、编码和定位问题,不能替代人工评审。代码生成后必须逐项检查权限边界、异常处理、上传限制、密钥加载、医疗免责声明和敏感信息,并通过测试及生产构建后才能部署。3.2 部署项目代码1)解决方案总体设计银发智伴采用“多端访问、统一 API、智能服务可降级、云上统一接入”的解决方案。PC 端承载报告管理、趋势对比和后台治理,H5 端专注适老化查看与语音播报;Nginx 提供统一公网入口,FastAPI 编排认证、报告、分享和智能解析流程;OBS 保存私有报告对象,SQLite 保存结构化业务数据,Redis 保存令牌黑名单和运行期状态。OCR 与大模型均设置超时、错误处理和本地降级,避免第三方服务短暂不可用时整个应用失效。用户上传报告后,请求依次经过文件校验、私有存储、OCR 识别、指标提取、风险判定、大模型健康解读和合规过滤;处理状态通过状态机管理。子女可在 PC 端查看结果、趋势和对比,也可生成带随机状态 ID、有效期、可选密码和访问次数限制的分享链接。父母通过 H5 查看大字版内容;管理员通过角色鉴权后的接口查看系统概览和管理用户。2)系统架构设计用户层:PC 子女端 / H5 父母端 / PC 管理后台 | 接入层:EIP + Nginx(/、/h5/、/api/、/health) | 应用层:FastAPI API / JWT认证 / 报告 / 分享 / 趋势 / 对比 / 管理 | 智能层:华为云OCR -> 百炼OCR -> Qwen VL / MCP大模型 / 合规工具 / 本地规则 | 数据层:SQLite业务数据 / Redis状态与令牌 / OBS私有对象 | 运维层:systemd / 健康检查 / 审计日志 / 华为云安全组架构关键点:公网只暴露 Nginx 的 80 端口,FastAPI 仅监听 127.0.0.1:8005;PC、H5 与 API 共用同一主机,减少跨域配置;智能服务通过统一服务层调用,业务 API 不直接依赖某一家模型厂商;配置和密钥全部由 .env 注入,仓库只提供不含真实值的 .env.example。核心技术难点与解决思路核心难点解决思路验证方式OCR 服务超时、配额不足或结果为空依次调用华为云 OCR、百炼 OCR 和 Qwen VL,仅在获得有效文本时结束;全失败时明确标记报告失败Mock 各级返回值,检查降级顺序和失败状态大模型输出不稳定且健康内容有合规风险传入结构化指标,以系统提示词约束输出;执行合规过滤并固定展示免责声明;调用失败时使用本地规则生成基础解读断开模型服务后仍能生成可查看的基础结果报告解析耗时,用户难以判断进度使用 OCR_PROCESSING、EXTRACTING、INTERPRETING、COMPLETED、FAILED 状态机,并通过 SSE 推送进度检查页面进度变化及异常后最终状态Windows 开发代码迁移到 Ubuntu锁定 Python/Node 依赖,使用 npm ci;Shell 脚本使用 LF;检查源码路径大小写,不使用 Windows 专属路径本地测试、双前端生产构建和 ECS 健康检查均通过H5 部署在 /h5/ 后深层路由刷新 404Vite base、Router base 和 Nginx try_files 使用一致的 /h5/ 前缀直接访问 /h5/share/<state_id> 返回 HTTP 200HTTP 演示站点复制分享链接失败优先使用 Clipboard API,失败时回退到隐藏文本框和 document.execCommand('copy')本地 HTTPS/localhost 与 ECS HTTP 环境分别点击复制医疗报告、账号和后台权限安全bcrypt 保存密码,JWT 鉴权,失败次数锁定,角色依赖保护管理员接口,OBS 私有存储并记录审计日志错误登录返回 401,普通用户访问管理员接口返回 4033)通过 GitCode 下载源码并了解项目结构本案例源码公开托管于 GitCode:https://gitcode.com/SDSXshlbz/elderlycare-ai。在 Windows PowerShell 或 Ubuntu 终端执行:git clone https://gitcode.com/SDSXshlbz/elderlycare-ai.git cd elderlycare-ai仓库不包含 .env、数据库、用户上传文件或真实医疗图片。克隆后需根据 .env.example 创建本地 .env 并填写自己的服务配置。项目结构如下:├── app/ # FastAPI后端 │ ├── api/ # 登录、报告、分享、趋势、对比等API路由 │ ├── core/ # 配置、数据库、安全、OBS、OCR、异常处理 │ ├── mcp/ # 大模型调用和本地工具降级 │ ├── models/ # SQLAlchemy ORM模型 │ ├── schemas/ # 请求和响应数据模型 │ ├── services/ # 认证、报告、解析、解读、分享等业务服务 │ └── main.py # FastAPI入口、路由和健康检查 ├── frontend/ │ ├── pc/ # 子女使用的PC端Vue 3应用 │ │ └── src/views/ # 工作台、详情、趋势、对比、家庭成员等页面 │ └── h5/ # 父母使用的适老化H5应用 │ └── src/views/SharePage.vue # 大字版健康报告和语音播报 ├── mcp_server/ # 可独立运行的模型编排与工具服务 ├── migrations/ # Alembic数据库版本记录 ├── tests/ # 后端单元测试与集成测试 ├── deploy_ecs.sh # Ubuntu ECS一键部署脚本 ├── requirements.txt # 固定版本的Python依赖 └── .env.example # 环境变量模板,不包含真实密钥 项目采用前后端分离和 API、服务、模型分层结构。浏览器请求先到 app/api/ 路由层,Pydantic app/schemas/ 完成输入输出校验,app/services/ 编排业务规则,app/models/ 通过异步 SQLAlchemy 持久化数据;OCR、OBS、安全和异常处理集中在 app/core/,模型调用与合规、营养、参考范围工具位于 app/mcp/。PC 与 H5 分别构建为静态文件,Nginx 将 / 映射到 PC,将 /h5/ 映射到 H5,将 /api/ 和 /health 反向代理到 FastAPI。4)在 Windows 本地执行构建与测试在项目根目录执行后端测试:.\.venv\Scripts\python.exe -m pytest tests -q预期结果:54 passed分别构建 PC 和 H5 生产包:Set-Location frontend\pc npm ci npm run build Set-Location ..\h5 npm ci npm run build Set-Location ..\.. npm ci 会严格按照 package-lock.json 安装依赖,避免 Windows 和 Ubuntu 使用不同依赖版本。两个 npm run build 均应成功生成各自的 dist 目录。PC 端构建时可能提示 ECharts 相关分块超过 Vite 默认的 500 KB 建议阈值,该提示不影响产物生成,后续可通过 manualChunks 进一步拆包。依赖审计警告不会阻断构建,但应单独评估,不建议直接执行可能引入破坏性升级的 npm audit fix --force。5)关键代码讲解OCR 三级降级机制(app/core/ocr_client.py)OCR 是报告解析的入口。代码先调用华为云通用文字和表格识别;如果没有识别到有效文本,再调用百炼 OCR 模型;最后使用千问 VL 多模态模型兜底。每一级仅在返回非空文本时结束链路,所有方法失败时返回空结果并由解析状态机标记失败。async def recognize_medical_report(self, image_data: bytes, file_type: str = "image") -> dict: image_b64 = base64.b64encode(image_data).decode("utf-8") result = await self._try_huawei_ocr(image_b64) if result: return result result = await self._try_aliyun_ocr(image_b64, file_type) if result: return result result = await self._try_qwen_vl(image_b64, file_type) if result: return result logger.error("All OCR methods failed (huawei -> aliyun -> qwen-vl)") return {"text": "", "confidence": 0.0} 关键释义:base64.b64encode() 将图片转为云 OCR API 可接收的 Base64 内容;降级调用相互独立,单个云服务超时或配额不足不会立即终止处理;日志只记录调用结果和错误,不输出图片、AK/SK 或 API Key;最终空文本不是伪造成功结果,业务层会将报告标记为 FAILED,便于用户重新处理。报告解析状态机和指标风险判定(app/services/parse_service.py)报告处理依次进入 OCR_PROCESSING、EXTRACTING、INTERPRETING 和 COMPLETED。前端根据状态显示处理进度;任何未捕获异常都会进入 FAILED,避免报告长期停留在处理中。await self._update_status(report, ParseStatus.OCR_PROCESSING) ocr_text = await self._run_ocr(report) if not ocr_text or not ocr_text.strip(): report.status = ParseStatus.FAILED await self.db.flush() return await self._update_status(report, ParseStatus.EXTRACTING) indicators = self._extract_indicators(ocr_text) abnormal = [i for i in indicators if i.status != IndicatorStatus.NORMAL] if abnormal: names = [i.name for i in abnormal[:5]] report.abnormal_summary = f"发现{len(abnormal)}项异常指标: {', '.join(names)}" await self._update_status(report, ParseStatus.INTERPRETING) report.status = ParseStatus.COMPLETED指标提取阶段会校验名称长度、医学单位、数值与参考范围。高于上限标记为 HIGH,低于下限标记为 LOW;偏离比例达到 1.2 或 1.5 时,风险等级依次提升为中风险或高风险。大模型健康解读与本地降级(app/mcp/mcp_client.py)后端使用 OpenAI 兼容接口调用配置的大模型,系统提示词约束输出范围,用户提示词携带结构化指标。HTTP 状态异常通过 raise_for_status() 进入异常分支;大模型不可用时,generate_interpretation() 会调用本地规则生成基础解读,保证报告仍可查看。async def _call_llm(self, system_prompt: str, user_prompt: str, temperature: float = 0.7) -> str: if not self._can_call_llm(): raise AppException(40004, "LLM API 未配置") async with httpx.AsyncClient(timeout=settings.LLM_TIMEOUT, proxy=None) as client: response = await client.post( f"{self._llm_api_base}/chat/completions", json={ "model": self._llm_model, "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], "temperature": temperature, }, headers={"Authorization": f"Bearer {self._llm_api_key}"}, ) response.raise_for_status() data = response.json() return data.get("choices", [{}])[0].get("message", {}).get("content", "") 登录失败返回业务错误而不是服务器内部错误(app/services/auth_service.py、app/core/exceptions.py)登录时先判断用户是否存在,再校验 bcrypt 密码。账号不存在或密码错误均抛出业务码 60003,统一异常处理器将其映射为 HTTP 401。这样错误凭据不会因为空用户访问、密码哈希异常或未处理业务异常而显示“服务器内部错误”。if user is None: raise AppException(60003, "账号或密码错误") if not verify_password(password, user.password_hash): user.login_fail_count += 1 if user.login_fail_count >= settings.LOGIN_MAX_FAILURES: user.status = AccountStatus.LOCKED user.locked_until = datetime.utcnow() + timedelta( minutes=settings.LOGIN_LOCK_MINUTES ) await self.db.flush() raise AppException( 60002, f"密码错误次数过多,账号已锁定{settings.LOGIN_LOCK_MINUTES}分钟", ) await self.db.flush() raise AppException( 60003, f"账号或密码错误,还剩{settings.LOGIN_MAX_FAILURES - user.login_fail_count}次机会", ) if exc.code in (60002, 50005): status_code = 429 elif exc.code in (60003, 60004): status_code = 401 连续失败达到阈值后账号临时锁定,可以降低暴力尝试风险;成功登录后失败次数会被清零,并签发访问令牌和刷新令牌。报告分享、二维码和访问限制(app/services/share_service.py)分享状态使用随机 UUID,默认30天有效。可选4位数字访问密码使用 bcrypt 哈希保存,数据库中不存储明文;同时支持访问次数上限、失败次数锁定和主动撤销。state_id = str(uuid.uuid4()) expire_time = datetime.utcnow() + timedelta( days=settings.SHARE_DEFAULT_EXPIRE_DAYS ) password_hash = None if access_password: if not access_password.isdigit() or len(access_password) != 4: raise AppException(10001, "访问密码需为4位数字") password_hash = _bcrypt.hashpw( access_password.encode("utf-8"), _bcrypt.gensalt() ).decode("utf-8") share_url = f"{settings.SHARE_BASE_URL}/share/{state_id}" qr = qrcode.QRCode(version=1, box_size=10, border=5) qr.add_data(share_url) qr.make(fit=True) H5 适老化语音播报(frontend/h5/src/views/SharePage.vue)H5 使用浏览器原生 Web Speech API,无需额外安装播放器。播报内容由健康解读、建议、注意事项和指标组成,语速设置为 0.8,优先选择中文语音;用户再次点击按钮时立即停止。function toggleSpeech() { if (!speechSupported.value) return const synth = window.speechSynthesis if (isSpeaking.value) { synth.cancel() isSpeaking.value = false return } speechUtterance = new SpeechSynthesisUtterance(getSpeechText()) speechUtterance.lang = 'zh-CN' speechUtterance.rate = 0.8 speechUtterance.pitch = 1.0 speechUtterance.volume = 1.0 synth.speak(speechUtterance) isSpeaking.value = true } H5 子路径适配(frontend/h5/vite.config.ts、frontend/h5/src/router/index.ts)生产环境将 H5 部署在 /h5/,构建资源路径和 Vue Router 必须使用同一个基础路径,否则在 Ubuntu Nginx 下刷新分享深层路由会出现资源 404 或空白页。export default defineConfig({ base: '/h5/', plugins: [vue()], }) const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/share/:stateId', name: 'SharePage', component: () => import('../views/SharePage.vue'), }, ], }) 6)打包并上传源码不要上传 .env 等本地敏感文件,也不要上传真实 elderlycare.db、测试数据库、医疗图片、.venv、node_modules 和 dist。在 Windows PowerShell 的项目根目录执行:tar.exe -czf elderlycare-deploy.tar.gz ` --exclude='.venv' ` --exclude='*/node_modules' ` --exclude='*/dist' ` --exclude='.env' ` --exclude='elderlycare.db' ` --exclude='test.db' ` --exclude='*.jpg' ` . scp .\elderlycare-deploy.tar.gz root@<ECS公网IP>:/tmp/ scp .\.env root@<ECS公网IP>:/tmp/elderlycare.env ssh root@<ECS公网IP> 如果使用 SSH 密钥,则在三个 SSH/SCP 命令中增加 -i <私钥路径>。上传完成后,在 ECS 中执行:sudo mkdir -p /opt/elderlycare sudo tar -xzf /tmp/elderlycare-deploy.tar.gz -C /opt/elderlycare sudo install -m 600 /tmp/elderlycare.env /opt/elderlycare/.env cd /opt/elderlycare sudo chmod +x deploy_ecs.sh sudo ./deploy_ecs.sh也可以先在 Windows PowerShell 中单独上传仅保存在本地的 .env:scp .\.env root@<ECS公网IP>:/tmp/elderlycare.env ssh root@<ECS公网IP> 登录 ECS 后,直接通过 GitCode 拉取公开源码并部署:/opt/elderlycare 是 Ubuntu ECS 上的绝对安装目录,不是 GitCode 仓库中的 opt 文件夹。git clone 命令的第二个参数会把仓库内容直接检出到该目录;后续部署脚本、Nginx 和 systemd 均统一使用此路径。sudo mkdir -p /opt/elderlycare sudo chown -R "$USER:$USER" /opt/elderlycare git clone https://gitcode.com/SDSXshlbz/elderlycare-ai.git /opt/elderlycare sudo install -m 600 /tmp/elderlycare.env /opt/elderlycare/.env cd /opt/elderlycare sudo chmod +x deploy_ecs.sh sudo ./deploy_ecs.sh关键节点说明:GitCode 只传输可公开的源码和合成演示截图,.env 必须沿独立安全通道上传。后续更新可在确认服务器无未提交修改后执行 git pull --ff-only,再重新运行 deploy_ecs.sh;数据库和用户上传文件应提前备份,不能用代码仓库代替业务数据备份。7)理解并执行一键部署脚本deploy_ecs.sh 使用 set -euo pipefail,任一关键命令失败都会终止部署。脚本执行七个阶段:安装系统依赖、准备运行用户、安装 Python 依赖、构建 PC/H5、配置 Nginx、注册 systemd 服务、执行健康检查。Nginx 的关键配置如下:location /h5/ { alias /opt/elderlycare/frontend/h5/dist/; index index.html; try_files $uri $uri/ /h5/index.html; } location /api/ { proxy_pass http://127.0.0.1:8005; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 120s; } location / { root /opt/elderlycare/frontend/pc/dist; index index.html; try_files $uri $uri/ /index.html; } try_files 是 PC 和 H5 深层路由刷新可用的关键。后端服务使用独立用户运行,并等待网络和 Redis:[Unit] After=network-online.target redis-server.service Wants=network-online.target redis-server.service [Service] User=elderlycare Group=elderlycare WorkingDirectory=/opt/elderlycare ExecStart=/opt/elderlycare/.venv/bin/python -m uvicorn app.main:app --host 127.0.0.1 --port 8005 Restart=always RestartSec=5 脚本结束前会轮询后端健康接口。成功时输出:Backend health check passed. ======================================== Deployment completed PC: http://<ECS_PUBLIC_IP>/ H5: http://<ECS_PUBLIC_IP>/h5/ Health: http://<ECS_PUBLIC_IP>/health ========================================8)记录数据库版本并检查服务项目启动时通过 SQLAlchemy create_all() 创建当前模型表。首次部署成功后,执行 alembic stamp head 记录当前迁移基线,不重复执行已由模型创建的历史表结构:cd /opt/elderlycare source .venv/bin/activate alembic stamp head deactivate sudo nginx -t sudo systemctl is-active nginx redis-server elderlycare curl --fail http://127.0.0.1:8005/health预期结果:nginx: configuration file /etc/nginx/nginx.conf test is successful active active active {"status":"ok","version":"1.0.0"}如健康检查失败,使用以下命令定位问题:sudo journalctl -u elderlycare -n 100 --no-pager sudo tail -n 100 /var/log/nginx/error.log常见问题与处理方法:现象原因处理方法deploy_ecs.sh: /bin/bash^MWindows CRLF 换行将脚本保存为 LF 后重新上传H5 分享链接刷新后 404Vite 基础路径或 Nginx 回退错误检查 base: '/h5/' 和 /h5/index.html登录显示服务器内部错误业务异常未映射或数据库字段不完整查看 journalctl,确认 60003 返回 401,数据库版本已记录上传后一直处理中OCR、OBS 或大模型配置错误检查 .env、OBS 区域、OCR权限及后端日志CSS/模块在 Ubuntu 找不到Windows 文件名大小写不敏感统一源码导入路径与真实文件名大小写9)安全收尾部署完成后删除包含密钥的临时文件和部署压缩包,并在安全组中删除临时 22 端口规则:rm -f /tmp/elderlycare.env /tmp/elderlycare-deploy.tar.gz服务器上的 /opt/elderlycare/.env 权限应为 600,所有者应为 elderlycare:sudo stat -c '%U:%G %a %n' /opt/elderlycare/.env预期输出:elderlycare:elderlycare 600 /opt/elderlycare/.env3.3 运行效果展示本案例已部署到华为云北京四 ECS。演示环境仅使用合成数据,环境信息如下:项目演示环境信息区域北京四 cn-north-4ECS实例elderlycare-demo,实例ID 5d96458e-5a74-47e7-8859-b78c14be13a8规格与系统c7.large.2,2 vCPU / 4 GiB,Ubuntu 22.04公网IP1.92.111.234PC端URLhttp://1.92.111.234/H5端URLhttp://1.92.111.234/h5/健康检查http://1.92.111.234/health,HTTP 200GitCode源码https://gitcode.com/SDSXshlbz/elderlycare-ai普通功能测试账号邮箱:demo@elderlycare.cn密码:Demo2026!应用后台管理员测试账号邮箱:admin20260726@elderlycare.cn密码:Sc9!Vt4#Lq7@Hm2普通账号用于演示报告上传、解读、趋势、对比和分享;管理员账号登录后进入后台管理页面,用于演示系统概览、用户列表、账号状态和角色权限。演示 ECS 当前为运行状态,公网安全组不保留 SSH 入站规则,只开放作品 Web 演示所需端口。当前地址使用 HTTP,仅用于作品演示,不要录入真实个人信息、医疗报告或其他敏感数据。正式上线应配置域名、HTTPS、数据库备份、日志脱敏和监控告警。核心功能1:报告上传与年度报告管理登录后进入工作台,选择家庭成员后拖拽或点击上传 PDF、JPG、PNG 文件。页面同步展示解析状态和历史报告。演示账号已准备 2024、2025、2026 三份年度报告,用于展示长期健康变化。关键节点说明:上传请求先校验文件数量、扩展名和大小,再将报告与家庭成员关联。后端完成 OCR、指标提取和解读后,状态变为“已完成”,点击报告名称进入详情。核心功能2:智能健康解读与饮食计划报告详情将异常指标转换为通俗说明,展示风险提示、健康建议、推荐食物、忌口食物、每日食谱和指标参考范围。每份解读固定展示医疗免责声明。执行后效果:2026年度合成报告识别出空腹血糖、总胆固醇、尿酸、收缩压和 BMI 偏高,并给出饮食控制、运动、定期监测等建议;血红蛋白显示为正常。核心功能3:历次指标趋势和异常变化提醒进入 趋势分析,可以按家庭成员和指标筛选。ECharts 折线图按报告时间排序,并使用参考范围背景区间辅助判断。执行后效果:演示数据包含6个指标,每个指标有3个年度数据点。系统可识别“正常转异常”“异常恢复”“状态变化”和“数值变化”,当前演示数据生成12条异常变化记录。核心功能4:两份报告逐项对比进入 报告对比,选择较早报告 A 与较近报告 B,点击 开始对比。后端按指标名称求交集,计算 报告B数值 - 报告A数值,并按变化绝对值排序。执行后效果:2024与2026两份报告共有6项指标。尿酸由 330 umol/L 变为 455 umol/L,收缩压由 128 mmHg 变为 148 mmHg,状态从正常变为偏高;页面同时展示 BMI、空腹血糖、总胆固醇和血红蛋白的变化。核心功能5:适老化 H5 分享与语音播报在报告详情中生成分享链接或二维码,父母通过手机打开 H5。页面采用大字号、高行距、明显风险标签和大尺寸圆形播报按钮;点击播放按钮后,图标切换为暂停,再次点击立即停止。执行后效果:在 390 × 844 移动视口下页面无横向溢出,分享接口返回6项指标;语音播报可以正常开始与暂停,H5 深层路由及生产资源均返回 HTTP 200。核心功能6:家庭成员管理进入 家庭成员,可维护父母等家庭成员的关系、性别、出生日期、身高、体重、慢性病、过敏史、用药和备注。报告关联成员后,趋势与对比功能可以按成员筛选,避免多人报告混合统计。核心功能7:应用后台管理与角色权限管理员登录后可查看系统用户、报告和分享数量,按角色或账号状态筛选用户,并执行受保护的管理操作。注册页面不提供管理员角色选择,普通用户不能通过修改前端参数自行获得管理员权限;管理员接口由后端角色依赖统一保护,并具有禁止管理员自降级和最后一名管理员保护逻辑。执行后效果:管理员账号可进入 /admin 页面,普通演示账号访问同一路由时会被前端守卫拦截,直接请求管理员 API 时后端返回 HTTP 403。角色变更记录写入审计日志,便于追溯操作者、目标用户和变更时间。功能验收结果验证项实际结果正确账号登录HTTP 200,进入工作台错误账号登录HTTP 401,返回“账号或密码错误”,无服务器内部错误报告列表3份合成年度报告趋势分析6项指标,每项3个年度数据点异常变化12条变化记录报告对比6项共有指标及数值、状态变化H5分享返回健康解读、饮食计划和6项指标二维码返回 image/png管理员权限管理员可访问后台,普通用户访问管理员接口返回 HTTP 403PC/H5控制台无错误或警告Ubuntu服务Nginx、Redis、FastAPI均为 active自动化测试54 passed演示视频已上传至gitcode四、释放资源4.1 删除ECS弹性云服务器登录华为云控制台,进入 服务列表 > 计算 > 弹性云服务器 ECS。在 ECS 列表勾选本案例创建的服务器,点击 更多 > 删除。在确认对话框中勾选 释放云服务器绑定的弹性公网IP地址;如创建了额外数据盘,同时勾选删除对应数据盘。核对实例名称和公网 IP,确认无需要保留的数据后点击 是。进入 网络 > 弹性公网IP和带宽,确认 EIP 已释放;进入 对象存储服务 OBS,删除不再需要的报告、二维码和桶;进入安全组确认不存在遗留的公网 22 端口规则。删除 ECS、EIP、系统盘或 OBS 数据属于不可逆操作。释放前请先备份需要保留的源码、数据库和日志。仅关机通常仍会产生系统盘、EIP等费用,应以控制台资源状态和账单为准。五、扩展资料说明华为云 ECS:cid:link_2华为云 OBS:cid:link_4华为云 OCR:cid:link_1华为云开发者空间:cid:link_6华为云码道 CodeArts:cid:link_7银发智伴 GitCode 源码:https://gitcode.com/SDSXshlbz/elderlycare-aiFastAPI:https://fastapi.tiangolo.com/Vue 3:https://vuejs.org/Nginx:https://nginx.org/en/docs/阿里云百炼 Model Studio:https://help.aliyun.com/zh/model-studio/
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的电脑销售管理系统
    gitcode仓库链接:https://gitcode.com/dyx131313/computer-sales-system一、概述1.1 案例介绍在中关村电子市场的日常经营中,电脑销售门店通常同时面对品牌机销售、配件零售、兼容机组装、客户资料维护、订单结算与售后跟踪等多类业务。传统手工登记方式容易出现产品库存更新不及时、配件价格计算繁琐、客户订单记录分散、销售数据难以汇总等问题。本案例以“中关村电脑销售管理系统”为实践对象,使用华为云码道(CodeArts)代码智能体辅助完成从需求分析、系统设计、前后端代码生成、问题修复、界面优化到运行验证的完整应用构建过程。案例参考 AssetMgmt 固定资产管理系统系列案例的写法,将开发过程拆分为“码道搭台,设计筑基”和“码道领航,落地生根”两个阶段:前者强调需求、架构、数据模型和接口设计,后者强调代码落地、调试修复、功能验证和成果展示。系统最终实现品牌机产品管理、电脑配件管理、兼容机组装、客户管理、订单管理、仪表盘统计和智能推荐等功能,形成一套可运行、可演示、可说明的前后端分离 Web 应用。1.2 适用对象希望快速体验 CodeArts 代码智能体应用构建能力的高校学生;需要学习 Spring Boot + Vue 3 前后端分离项目落地流程的初学者;希望借助 AI IDE 完成管理系统原型构建和案例文档整理的个人开发者。1.3 案例目标目标说明真实场景建模围绕电脑销售门店的产品、配件、客户和订单业务建模AI 辅助开发使用华为云码道完成需求拆解、代码生成、调试修复和文档整理功能可运行前端页面、后端接口、数据库初始化和业务流程均可本地运行验证文档可复现记录关键对话、架构图、数据模型、接口清单、运行命令和截图成果可提交输出适用于训练营提交的应用构建案例文档和演示材料1.4 案例时间与资源本案例预计总时长约 4 小时,开发与演示阶段本地运行即可完成,预计资源花费 0 元。规格资源名称单价体验版华为云码道 CodeArts 代码智能体免费本地开发环境JDK、Maven、Node.js、npm免费演示数据库H2 内存数据库免费1.5 案例总流程整体流程如下:安装部署华为云码道(CodeArts)代码智能体;使用自然语言向码道描述电脑销售管理系统需求;在码道辅助下完成系统架构、数据模型和接口设计;生成并完善 Spring Boot 后端项目;生成并完善 Vue 3 前端项目;实现兼容机组装、订单结算、库存扣减和智能推荐等核心业务;解决跨域、实体命名、订单金额、库存事务等联调问题;启动系统,使用页面截图和接口测试验证功能。1.6 训练营要求对应关系训练营要求本案例对应成果使用华为云码道 CodeArts 代码智能体完成应用构建需求分析、架构设计、前后端代码、调试修复和文档整理均围绕码道展开输出应用构建案例文档本文档说明案例背景、系统设计、开发过程、关键难点、运行验证和成果展示核心功能可运行系统提供产品管理、配件管理、兼容机组装、客户管理、订单管理和智能推荐有关键节点文字说明与截图文档包含架构图、ER 图、业务流程图和系统运行截图突出关键代码释义和步骤说明文档列出实体设计、接口设计、事务逻辑和典型问题修复过程二、环境和资源准备2.1 华为云码道安装部署参考训练营指导书完成 Windows 版 AI IDE 华为云码道(CodeArts)代码智能体安装部署,并登录华为云账号。本案例使用码道智能体模式,通过连续对话完成项目生成、功能补全、错误修复和文档整理。2.2 本地开发环境工具版本用途JDK21后端 Java 运行环境Maven3.9.x后端依赖管理与项目构建Node.js22.x前端运行环境npm10.x前端依赖管理浏览器Edge / Chrome页面访问与效果验证华为云码道训练营版本AI 辅助编码、问答、调试、文档整理2.3 技术选型层次技术选择原因前端框架Vue 3 + Vite开发启动快,适合构建管理系统单页应用UI 组件库Element Plus表格、表单、弹窗、导航组件成熟HTTP 客户端Axios便于统一封装 REST API 调用后端框架Spring Boot 3.3.1适合快速构建 RESTful 服务数据访问Spring Data JPA降低 CRUD 与对象关系映射成本数据库H2便于本地演示和初始化样例数据AI 工具华为云码道 CodeArts用自然语言驱动需求拆解、代码生成和问题修复三、码道搭台:需求分析与系统设计3.1 向码道描述初始需求案例开发的第一步是将业务目标转化为清晰的自然语言提示。向码道输入如下需求:请帮我创建一个电脑销售管理系统,技术栈使用 Vue 3 + Spring Boot 前后端分离架构。系统需要以下功能模块:仪表盘:展示产品总数、配件总数、客户总数、订单总数等统计数据;产品管理:管理品牌机(笔记本、台式机、一体机)的增删改查;配件管理:管理内存、硬盘、机箱、键盘、鼠标、显示器等配件;兼容机组装:客户可自选配件组装兼容机,实时计算总价;客户管理:客户信息的增删改查;订单管理:支持品牌机购买和兼容机组装两种订单类型;智能推荐:基于客户历史消费数据生成个性化推荐方案。码道根据需求拆解出前后端分离架构、六类核心实体、REST API、页面路由、初始化数据和核心业务流程。这个过程类似 AssetMgmt 示例中的“设计筑基”阶段:先形成清晰规格,再进入代码实现。3.2 功能模块划分模块主要功能对应页面/接口仪表盘统计产品、配件、客户、订单、销售额Dashboard.vue、/api/dashboard/stats产品管理品牌机增删改查、库存维护Products.vue、/api/products配件管理配件增删改查、分类与兼容性维护Components.vue、/api/components兼容机组装分类选配件、实时计价、一键下单Assembly.vue、/api/orders客户管理客户资料维护、客户订单查询Customers.vue、/api/customers订单管理订单列表、订单项、状态流转Orders.vue、/api/orders智能推荐按客户消费生成推荐方案/api/recommendations/*3.3 系统架构设计系统采用前后端分离 B/S 架构,前端负责页面交互、数据展示和实时计价,后端负责业务校验、事务处理、库存扣减和数据持久化。下图由系统设计说明书中的 Mermaid 源图导出,便于在案例文档和报告中直接展示。3.4 数据模型设计系统核心实体包括 Product、PcComponent、Customer、Order、OrderItem 和 Recommendation。其中 OrderItem 通过 itemType 区分品牌机产品项和配件项,使品牌机购买和兼容机组装两类业务能够共用订单模型。核心实体说明如下:实体表名作用Productproducts存储品牌机信息PcComponentcomponents存储配件信息Customercustomers存储客户资料Orderorders存储订单主表OrderItemorder_items存储订单明细Recommendationrecommendations存储客户推荐方案3.5 接口设计模块接口方法说明健康检查/api/healthGET检查后端服务状态仪表盘/api/dashboard/statsGET获取统计数据产品/api/productsGET/POST查询或新增产品产品/api/products/{id}GET/PUT/DELETE查看、更新或删除产品配件/api/componentsGET/POST查询或新增配件配件/api/components/{id}GET/PUT/DELETE查看、更新或删除配件客户/api/customersGET/POST查询或新增客户客户/api/customers/{id}GET/PUT/DELETE查看、更新或删除客户订单/api/ordersGET/POST查询或创建订单订单/api/orders/{id}/itemsGET查询订单项订单/api/orders/{id}/statusPUT更新订单状态推荐/api/recommendations/generate/{customerId}POST生成客户推荐四、码道领航:代码落地与功能实现4.1 后端项目生成向码道输入后端开发提示:请帮我搭建 Spring Boot 3.3 后端项目,使用 Spring Data JPA 和 H2 数据库,创建完整的实体类、DTO、Repository、Service 和 Controller,并配置 CORS、全局异常处理和初始化数据。码道生成的后端任务规划包括:创建 pom.xml 与 application.yml;创建 Product、PcComponent、Customer、Order、OrderItem、Recommendation 实体;创建请求 DTO;创建 Repository 数据访问层;创建 Service 业务层及实现类;创建 Controller REST API;配置 WebConfig、GlobalExceptionHandler 和 DataInitializer。关键实体示例:@Entity @Table(name = "orders") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Long customerId; private String orderType; // BRANDED / ASSEMBLY private BigDecimal totalAmount; private String status; // PENDING / PROCESSING / COMPLETED / CANCELLED private String remark; private LocalDateTime createdAt; private LocalDateTime updatedAt; } 后端实现重点是订单创建逻辑。创建订单时,系统需要校验客户、产品或配件是否存在,检查库存是否充足,保存订单项,计算订单总额并扣减库存。这一逻辑放在 Service 层并使用事务保证一致性。4.2 前端项目生成向码道输入前端开发提示:请帮我搭建 Vue 3 前端项目,使用 Element Plus、Vue Router、Axios 和 Vite,创建后台管理布局、业务页面、API 调用模块和路由配置。码道生成的前端结构包括:文件/目录作用src/main.jsVue 应用入口src/router/index.js路由配置src/api/index.jsAxios 实例src/api/modules.js产品、配件、客户、订单等 API 函数src/views/Layout.vue后台管理布局src/views/Dashboard.vue仪表盘页面src/views/Products.vue产品管理页面src/views/Components.vue配件管理页面src/views/Assembly.vue兼容机组装页面src/views/Customers.vue客户管理页面src/views/Orders.vue订单管理页面前端 API 封装示例:export const getProducts = (params) => api.get('/products', { params }) export const createProduct = (data) => api.post('/products', data) export const updateProduct = (id, data) => api.put(`/products/${id}`, data) export const deleteProduct = (id) => api.delete(`/products/${id}`) export const createOrder = (data) => api.post('/orders', data) export const updateOrderStatus = (id, status) => api.put(`/orders/${id}/status`, null, { params: { status } }) 4.3 核心功能:兼容机组装兼容机组装是本项目区别于普通 CRUD 管理系统的核心功能。页面左侧按内存、硬盘、机箱、键盘、鼠标、显示器六类配件展示可选项,右侧实时显示组装清单和总价。用户确认后选择客户并提交组装订单。关键实现思路:前端加载全部配件,并按 category 分组;每个分类使用单选控件选择一项配件;使用 Vue computed 汇总已选配件和总价;提交时构造 OrderRequest,订单类型为 ASSEMBLY;后端逐项校验配件库存,并在事务中保存订单与订单项。4.4 智能推荐功能智能推荐模块基于客户历史消费金额生成规则型推荐方案。当前实现分为三类:客户类型判断依据推荐策略VIP 客户累计消费较高推荐高端升级方案办公客户中等消费水平推荐办公效率套装新客户历史消费较少或无订单推荐入门级组装方案该模块虽然不是复杂机器学习模型,但能体现系统从“业务记录”向“销售辅助”延伸的能力,也为后续接入大模型或协同过滤算法预留了扩展空间。4.5 UI 美化在基础功能完成后,继续对前端界面进行美化:侧边栏采用深色渐变背景,突出后台系统风格;仪表盘统计卡片使用渐变色与图标增强识别度;表格操作按钮统一为查看、编辑、删除等常见交互;兼容机组装页面采用左右分栏结构,降低用户认知成本;表单弹窗使用 Element Plus Dialog,保持交互一致。五、关键技术难点与解决思路参考 AssetMgmt 落地案例的写法,本节将开发中遇到的问题整理为“问题 - 原因 - 修复方式 - 结果”的闭环。问题原因解决方式结果CORS 跨域访问失败前端 5173 端口访问后端 8080 端口,被浏览器跨域策略拦截前端配置 Vite proxy,后端新增 WebConfig 配置允许来源前端可正常调用后端 APIComponent 命名冲突配件实体名与 Spring @Component 注解容易混淆将实体命名为 PcComponent代码语义更清晰,避免导入错误Lombok 注解处理失败Maven 编译器未显式配置注解处理器在 maven-compiler-plugin 中配置 Lombok annotationProcessorPathsGetter/Setter/Builder 等正常生成订单金额为空订单初次保存时 totalAmount 尚未计算,触发非空约束保存前设置 BigDecimal.ZERO,订单项计算完成后更新总金额订单创建流程正常库存一致性风险订单创建涉及订单、订单项、产品/配件库存多表更新在 Service 层使用 @Transactional,异常时回滚库存不足时不会产生脏数据六、系统启动与验证6.1 启动后端cd backend set JAVA_HOME=D:\JAVA\jdk-21.0.4.7-hotspot mvn spring-boot:run后端默认运行在:http://localhost:8080健康检查:curl http://localhost:8080/api/health预期返回:{"status":"UP","service":"Computer Sales System"} 6.2 启动前端cd frontend npm install npm run dev前端默认运行在:http://localhost:51736.3 页面功能验证6.3.1 仪表盘仪表盘展示产品总数、配件总数、客户总数、订单总数等统计数据,并提供快捷操作入口。6.3.2 产品管理产品管理页面支持品牌机的新增、编辑、删除和查询,字段包括产品名称、品牌、类型、价格和库存。6.3.3 配件管理配件管理页面支持内存、硬盘、机箱、键盘、鼠标、显示器等配件维护。6.3.4 兼容机组装兼容机组装页面左侧展示配件分类,右侧实时展示组装清单和总价,是系统最具业务特色的功能。6.3.5 客户管理客户管理页面维护客户姓名、手机号、邮箱和地址等基础信息。6.3.6 订单管理订单管理页面展示品牌机订单和兼容机组装订单,并支持订单状态流转和订单详情查看。6.4 API 验证# 获取仪表盘统计 curl http://localhost:8080/api/dashboard/stats # 获取产品列表 curl http://localhost:8080/api/products # 创建客户 curl -X POST http://localhost:8080/api/customers ^ -H "Content-Type: application/json" ^ -d "{\"name\":\"张三\",\"phone\":\"13800138000\",\"email\":\"zhangsan@test.com\",\"address\":\"北京\"}" # 创建品牌机订单 curl -X POST http://localhost:8080/api/orders ^ -H "Content-Type: application/json" ^ -d "{\"customerId\":1,\"orderType\":\"BRANDED\",\"remark\":\"购买ThinkPad\",\"items\":[{\"productId\":1,\"itemType\":\"PRODUCT\",\"quantity\":1}]}" # 生成客户推荐 curl -X POST http://localhost:8080/api/recommendations/generate/1七、项目结构与成果文件7.1 项目目录computer-sales-system/ ├── backend/ │ ├── pom.xml │ └── src/main/java/com/computersales/ │ ├── ComputerSalesApplication.java │ ├── config/ │ │ ├── WebConfig.java │ │ ├── DataInitializer.java │ │ └── GlobalExceptionHandler.java │ ├── controller/ │ ├── dto/ │ ├── entity/ │ ├── repository/ │ └── service/ ├── frontend/ │ ├── package.json │ ├── vite.config.js │ └── src/ │ ├── api/ │ ├── router/ │ ├── style.css │ └── views/ ├── docs/ │ ├── demo/ └── README.md7.2 成果文件文件说明docs/应用构建案例文档.md本案例文档docs/系统设计说明书.md系统架构、数据模型、接口、部署与验收说明docs/mermaid_exports/*.png从 Mermaid 导出的架构图、ER 图和流程图docs/screenshots/*.png系统运行截图docs/专业集中实习报告-模板重构版-含架构图和截图.docx集中实习报告推荐提交版docs/实习日记本-模板重构版.docx实习日记本推荐提交版八、总结与展望8.1 项目成果总结本案例完成了一套可运行的电脑销售管理系统,实现了从产品资料维护、配件资料维护、客户管理到订单结算的完整流程。其中,兼容机组装功能体现了电脑销售门店的实际业务特色,智能推荐模块则为后续销售辅助提供了扩展方向。与普通手写项目相比,华为云码道 CodeArts 在本案例中主要发挥了四方面价值:需求拆解更快:通过自然语言快速形成模块划分、实体设计和接口规划;代码生成更快:后端分层结构和前端页面组件可快速生成;问题修复更快:跨域、Lombok、命名冲突、订单金额等问题能快速定位;文档整理更完整:能够辅助形成案例说明、系统设计、运行验证和成果总结。8.2 后续优化方向将 H2 数据库迁移至 MySQL 或 PostgreSQL,实现数据持久化;部署至华为云 ECS 或开发者空间,提供公网演示链接;增加用户登录、角色权限和操作日志;接入 ECharts 展示销售趋势、品类占比和客户消费分层;将规则型智能推荐升级为大模型辅助推荐或协同过滤推荐。本项目由华为云码道(CodeArts)代码智能体辅助开发
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的校园充电宝共享管理系统
    gitcode仓库链接:https://gitcode.com/gcw_uJeoZsol/campus-power-bank-management-system1、概述1.1 案例介绍校园内的图书馆、教学楼、食堂和体育馆等区域通常存在临时充电需求。若仅依靠人工登记,容易出现设备状态不清、借还记录缺失、故障处理不及时以及无法快速查询当前持有人等问题。本案例使用华为云码道(CodeArts Agent)辅助完成需求分析、方案设计、任务拆分、代码生成和问题排查,构建了一套前后端分离的校园充电宝共享管理系统。系统面向管理员和学生两类角色,实现用户管理、充电宝管理、存放点管理、借还记录查询、充电宝借用与归还、当前持有查询、历史记录查询和故障报修处理等功能。项目采用以下技术栈:层次技术前端Vue 3、Element Plus、Axios、Vue Router、Pinia、Vite后端Spring Boot 3、MyBatis Plus、JWT、Lombok数据库MySQL 8开发工具IntelliJ IDEA、华为云码道 CodeArts Agent代码仓库AtomGit / GitCode1.2 适用对象希望了解华为云码道规范开发流程的开发者;需要完成 Java Web 或前后端分离课程设计的高校学生;希望快速搭建校园设备共享类管理系统的个人开发者;希望学习 Vue 3、Spring Boot 3 与 MySQL 综合应用的初学者。1.3 案例时间建议预留约 2~3 小时完成完整体验,不包含 JDK、Node.js、MySQL 和依赖包的首次下载时间。实际耗时会受到本地环境、网络速度和功能调整范围影响。1.4 案例流程开通华为云码道使用权限 ↓ 在 IntelliJ IDEA 中安装并登录 CodeArts Agent ↓ 输入结构化需求,生成 spec.md、design.md、tasks.md ↓ 审核需求与技术方案 ↓ 按照任务清单生成数据库、后端与前端代码 ↓ 运行调试并修复接口、权限和页面问题 ↓ 完成系统测试、仓库提交和案例文章整理1.5 资源总览本案例使用本地开发环境完成,不需要额外购买 ECS、OBS 等云资源。资源名称规格或版本用途华为云码道 CodeArts Agent以账号当前可用套餐为准需求分析、设计、编码和调试IntelliJ IDEA兼容 CodeArts Agent 的版本项目开发JDK17 及以上运行 Spring BootMaven3.8 及以上后端依赖管理Node.js16 及以上运行 Vue 前端MySQL8.0 及以上业务数据存储Git2.x版本管理与仓库推送2、环境和资源准备2.1 领取华为云码道使用权限登录华为开发者空间或华为云码道产品页面,根据账号提示领取体验权限或开通对应服务。完成后,在支持的 IntelliJ IDEA 中安装 CodeArts Agent 插件,并使用华为云账号登录。2.2 本地开发环境本项目的后端默认端口为 8080,统一接口前缀为 /api;前端开发服务器端口为 3001,通过 Vite 代理访问后端。建议提前确认以下命令能够正常执行:java -version mvn -version node -v npm -v mysql --version git --version 2.3 创建项目仓库在 AtomGit / GitCode 创建公开仓库:campus-power-bank-management-system项目地址:https://gitcode.com/gcw_uJeoZsol/campus-power-bank-management-system仓库用于保存源代码、数据库脚本、README 和开发提交记录。项目中不应上传 node_modules、target、.idea、数据库真实密码或 JWT 私钥。3、构建校园充电宝共享管理系统3.1 项目需求构建3.1.1 核心需求梳理系统设置管理员和学生两类角色。管理员端主要功能:用户管理:查询、编辑和删除学生信息;充电宝管理:新增、编辑、删除设备并维护设备状态;存放点管理:维护存放点编号、名称、位置和容量;借还记录:按学号、充电宝编号和状态查询借还记录;故障报修:查看报修信息并填写处理结果。学生端主要功能:使用学号和密码登录;按存放点查看可借充电宝;借用充电宝;查询当前持有设备并办理归还;查看个人历史借还记录;提交充电宝故障报修。业务边界:本案例不接入收费支付;不直接控制充电宝硬件;不实现实时定位,仅维护逻辑存放点;一个学生同一时间只能持有一个未归还充电宝。3.1.2 编写结构化提示词在 CodeArts Agent 中输入以下提示词,让智能体先完成规范设计,而不是一次性生成全部代码:请为我设计一个校园充电宝共享管理系统。 技术栈: 前端使用 Vue 3、Element Plus、Axios; 后端使用 Spring Boot 3、MyBatis Plus; 数据库使用 MySQL 8; 采用前后端分离架构。 系统角色包括管理员和学生。 管理员功能: 1. 用户管理; 2. 充电宝信息管理; 3. 存放点管理; 4. 借还记录管理; 5. 故障报修管理。 学生功能: 1. 登录; 2. 查询可借充电宝; 3. 借用和归还充电宝; 4. 查看当前持有情况; 5. 查看历史借还记录; 6. 提交故障报修。 请先生成 spec.md、design.md 和 tasks.md, 明确业务规则、数据库设计、接口设计、页面结构和验收标准, 暂时不要直接生成全部项目代码。华为云码道会根据需求识别可使用的规范开发能力,并开始梳理角色、边界、核心业务和异常场景。3.1.3 生成需求、设计与任务文档规范开发阶段生成了三类核心文档:spec.md:描述系统角色、领域术语、业务规则、异常场景和验收标准;design.md:描述前后端架构、数据库表、接口和模块设计;tasks.md:按照环境准备、数据库、后端、前端、测试和文档等阶段拆分任务。这些文档位于:.codeartsdoer/specs/power_bank/ ├── spec.md ├── design.md └── tasks.md在继续生成代码前,需要重点检查:角色和功能是否与选题要求一致;数据库表之间的外键关系是否合理;借用和归还是否具有状态闭环;管理员与学生接口是否分离;删除、归还和故障处理等关键操作是否有业务校验;技术版本是否与本地环境兼容。3.2 项目代码实现3.2.1 系统架构系统采用前后端分离架构:浏览器 │ ├── 管理员端 / 学生端 │ Vue 3 + Element Plus │ └── Axios 请求 /api ↓ Spring Boot 3 ↓ Service 业务层 ↓ MyBatis Plus ↓ MySQL 8登录成功后,后端返回 JWT 和用户信息。前端保存登录状态,并由路由守卫判断是否已登录以及角色是否匹配。3.2.2 项目结构campus-power-bank-management-system/ ├── .codeartsdoer/ │ └── specs/power_bank/ │ ├── spec.md │ ├── design.md │ └── tasks.md ├── database/ │ ├── init.sql │ ├── init_complete.sql │ ├── reset.sql │ └── sample_data.sql ├── backend/ │ ├── pom.xml │ └── src/main/ │ ├── java/com/campus/powerbank/ │ │ ├── controller/ │ │ ├── service/ │ │ ├── mapper/ │ │ ├── entity/ │ │ ├── dto/ │ │ ├── vo/ │ │ ├── common/ │ │ ├── config/ │ │ ├── exception/ │ │ └── util/ │ └── resources/application.yml ├── frontend/ │ ├── src/ │ │ ├── api/ │ │ ├── router/ │ │ ├── utils/ │ │ └── views/ │ │ ├── admin/ │ │ └── student/ │ ├── package.json │ └── vite.config.js ├── .gitignore └── README.md这种结构将数据库脚本、后端服务和前端页面分开管理,便于调试、提交和后续扩展。3.2.3 数据库设计系统包含 5 张核心业务表:数据表主要用途user保存管理员和学生账号、姓名、学号、联系方式和角色location保存存放点编号、名称、位置描述和容量power_bank保存充电宝编号、品牌型号、状态和所属存放点borrow_record保存借用人、设备、借用时间、归还时间和借用状态fault_report保存故障设备、报修人、故障描述、处理状态和结果主要关系:user 1 ───── N borrow_record power_bank 1 ───── N borrow_record location 1 ───── N power_bank location 1 ───── N borrow_record(归还存放点) user 1 ───── N fault_report power_bank 1 ───── N fault_report数据库初始化可以直接执行:mysql -u root -p < database/init_complete.sqlinit_complete.sql 会重建数据库并导入完整测试数据,适合首次体验。正式环境应改用迁移脚本,避免直接删除已有数据。3.2.4 借用与归还核心逻辑借用操作需要同时写入借用记录并修改充电宝状态,因此使用事务保证一致性。核心规则包括:学生存在未归还记录时不能再次借用;只有“可用”状态的充电宝可以借出;借用成功后设备状态改为“已借出”;归还成功后记录状态改为“已归还”;归还时更新设备的新存放点和“可用”状态。关键代码如下:@Transactional public BorrowRecordVO borrowPowerBank(Long userId, Long powerBankId) { long currentCount = count( new LambdaQueryWrapper<BorrowRecord>() .eq(BorrowRecord::getUserId, userId) .eq(BorrowRecord::getStatus, "借用中") ); if (currentCount > 0) { throw new BusinessException("您已借用充电宝,请先归还后再借用"); } PowerBank powerBank = powerBankService.getById(powerBankId); if (powerBank == null || !"可用".equals(powerBank.getStatus())) { throw new BusinessException("充电宝不可用,请选择其他充电宝"); } BorrowRecord record = new BorrowRecord(); record.setUserId(userId); record.setPowerBankId(powerBankId); record.setBorrowTime(LocalDateTime.now()); record.setStatus("借用中"); save(record); powerBank.setStatus("已借出"); powerBankService.updateById(powerBank); return convertToVO(record); } 3.2.5 前端登录与权限控制前端路由分为管理员和学生两组。路由守卫会读取 Token 和用户角色,阻止未登录用户或角色不匹配的用户访问受限页面。router.beforeEach((to, from, next) => { if (to.meta.requiresAuth) { const token = getToken() const userInfo = getUserInfo() if (!token) { next('/login') return } if (to.meta.role && userInfo.role !== to.meta.role) { next('/login') return } } next() }) 管理员页面采用左侧导航布局,学生端采用顶部导航和卡片式设备展示,使两类角色的操作路径更加清晰。3.3 运行与调试3.3.1 修改本地配置后端配置文件中的数据库密码和 JWT 密钥不要直接提交真实值。发布仓库时建议改为环境变量:spring: datasource: url: jdbc:mysql://localhost:3306/campus_power_bank username: ${DB_USERNAME:root} password: ${DB_PASSWORD:your_password} jwt: secret: ${JWT_SECRET:replace_with_a_long_random_secret} expiration: 86400 3.3.2 启动后端cd backend mvn spring-boot:run后端地址:http://localhost:8080/api3.3.3 启动前端cd frontend npm install npm run dev前端地址:http://localhost:3001本地测试账号:管理员:admin / admin123 学生:20210001 / 123456测试账号仅用于本地案例演示,部署或公开使用前应修改默认密码。4、系统功能展示4.1 管理员用户管理用户管理页面展示学生学号、姓名、联系方式、借用状态和注册时间。管理员可以根据姓名、学号或手机号查询用户,并根据借用状态进行筛选。系统对删除操作进行业务限制:存在未归还充电宝的学生不能直接删除,避免产生无归属的借用记录。4.2 管理员充电宝管理充电宝管理页面用于维护设备编号、品牌型号、状态、存放点和位置描述。管理员可以新增设备、编辑信息、切换状态或删除设备。设备状态包括:可用;已借出;维护中;已报废。正在借用的设备不能被直接删除或改为可用状态,相关操作必须遵守借还业务流程。4.3 存放点管理存放点管理页面展示存放点编号、名称、位置、容量和当前设备数量。示例存放点包括图书馆一楼、教学楼 A 区、食堂一楼和体育馆。系统禁止删除仍然存有充电宝的存放点,防止设备与位置关系丢失。4.4 借还记录管理管理员可以按学生学号、充电宝编号、借用状态和时间范围查询记录。记录中包含借用人、设备、借用时间、归还时间、当前状态和归还存放点。通过借还记录可以追踪每台设备的使用过程,也可以快速定位当前未归还设备的持有人。4.5 故障报修管理学生提交故障后,管理员可以查看设备编号、故障描述、报修人、报修时间和处理状态。待处理记录可以填写处理结果,完成后系统保存处理时间。4.6 学生查询并借用充电宝学生登录后可以查看所有可借设备,也可以按存放点筛选。每张卡片展示设备编号、品牌型号、所在位置和可借状态。点击“立即借用”后,后端再次校验学生是否已有未归还设备以及目标充电宝是否可用,避免前端页面状态滞后造成重复借用。4.7 学生归还、历史记录和故障报修学生端还包括以下功能:当前持有:展示当前借用设备、借用时间和原存放点;归还设备:选择归还存放点后完成归还;历史记录:查看本人全部借用与归还记录;故障报修:选择设备并填写故障描述;退出登录:清除本地 Token 和用户信息。归还成功后,借用记录与充电宝状态在同一事务中同步更新,设备会重新进入可借列表。5、项目仓库与提交记录项目源码已经提交到 AtomGit / GitCode:https://gitcode.com/gcw_uJeoZsol/campus-power-bank-management-system仓库建议至少包含:backend/ frontend/ database/ README.md .gitignore.gitignore 建议配置:.idea/ **/.idea/ *.iml .codeartsdoer/ **/node_modules/ **/dist/ **/target/ *.log .env .env.* 每完成一个阶段进行一次提交,可以保留更清晰的开发过程,例如:git add . git commit -m "完成用户与充电宝管理功能" git push origin main6、资源释放本案例在本地运行,没有创建 ECS、RDS、OBS 等云资源,因此体验结束后只需:停止前端和后端进程;不再使用时删除本地项目目录;根据需要保留或删除本地 MySQL 数据库;将公开仓库中的真实密码、密钥和本地配置及时清理;在华为云码道中删除不再需要的对话记录或项目上下文。删除数据库命令如下,执行前请确认数据不再需要:DROP DATABASE campus_power_bank; 7、案例总结本案例通过华为云码道 CodeArts Agent 完成了从需求描述到可运行系统的完整开发流程。与直接要求智能体一次性生成代码相比,先生成 spec.md、design.md 和 tasks.md,再按任务阶段逐步实现,更容易控制项目范围,也方便发现数据库关系、接口路径和业务状态方面的问题。在实际开发过程中,码道主要发挥了以下作用:将自然语言需求转换为结构化业务规则;生成前后端分离的技术方案和目录结构;拆分数据库、后端、前端和测试任务;辅助生成 Controller、Service、实体类和 Vue 页面;根据运行结果继续补充测试数据并修复问题;协助完善 README、仓库结构和案例文档。最终系统实现了校园充电宝从入库、存放、借用、归还到故障处理的基本业务闭环。后续还可以继续扩展二维码扫码借用、逾期提醒、设备统计看板、校园统一身份认证和移动端适配等功能。通过本次实践可以看出,CodeArts Agent 不只是代码补全工具,更适合配合规范文档、任务拆分和多轮调试完成完整应用构建。
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的校园二手设备交易平台
    一、案例介绍1.1 概述随着高校学生群体中二手物品交易需求的日益增长,传统的线下交易方式存在信息不对称、交易效率低、缺乏信任保障等问题。校园内大量闲置设备(如暖壶、电水壶、电扇、微波炉、移动硬盘等)在毕业季被丢弃或低价处理,造成了资源浪费。为解决这一痛点,本项目构建了一个面向校园场景的二手设备在线交易平台(AssetMgmt),实现设备信息的高效发布与精准匹配,保障交易流程的安全可靠。本项目采用前后端分离架构,后端基于FastAPI异步框架配合PostgreSQL数据库,前端基于Vue3 + Element Plus + Pinia,生产环境部署在华为云ECS上。全程使用华为云码道(CodeArts)代码智能体辅助开发,采用SDD(Specification-Driven Development)文档驱动方法论,探索云原生部署与AI辅助开发的高效实践路径。项目已经部署在华为云服务器上并且公网可访问(预计运行开放到7月31日结营之前),地址为:http://123.60.220.56/视频演示demo:https://github.com/Erictongtian/huaweishixi/blob/main/视频演示demo.mp4项目源代码仓库:https://github.com/Erictongtian/huaweishixi系统涵盖7大功能模块:功能模块核心功能用户认证注册(邮箱验证码)、登录、Token刷新、密码修改设备管理发布、编辑、上下架、图片上传排序、搜索筛选交易管理下单、确认/拒绝、交付、取消、并发控制评价管理交易完成后星级评价和文字评论分类管理管理员增删改查,展示分类在售设备数量个人中心修改昵称、头像上传、联系方式、密码修改用户管理管理员封禁/解封/注销/重置密码1.2 案例时间本次案例实践周期为2026年7月18日至7月24日,共计7天,分为三个阶段:阶段时间工作内容第一阶段:环境与开发7月18日-20日开发环境搭建,SDD文档生成,项目架构初始化,7大功能模块前后端开发第二阶段:完善与测试7月21日-22日个人中心、用户管理、邮箱验证码注册、UI美化,单元/集成/E2E测试第三阶段:部署与总结7月23日-24日华为云ECS生产部署,调试优化,文档整理1.3 案例流程本次案例遵循SDD文档驱动开发方法论,从需求描述到生产部署形成完整闭环,核心流程如下:需求描述:以自然语言描述项目需求,包括功能范围、业务规则、约束条件等;文档生成:通过CodeArts代码智能体的SDD技能,自动生成spec.md(需求规格)、design/*.md(详细设计)、tasks.md(任务分解)等完整文档体系;代码实现:根据设计文档,在CodeArts辅助下完成数据模型、业务逻辑、API接口、前端页面的开发与迭代;测试验证:编写单元测试、集成测试、E2E联调测试,确保功能正确性和系统稳定性;生产部署:通过CodeArts远程SSH能力,自动化完成华为云ECS环境配置、数据库初始化、服务部署与Nginx配置;验收交付:公网访问验证,代码推送GitHub,文档整理归档。1.4 资源总览本次案例涉及的核心资源如下:资源类别资源项规格/说明开发环境操作系统Windows 11 (x86_64)开发环境Python / Node.js3.13.13 / 22.21.1开发环境PostgreSQL18.4开发环境IDE华为云码道(CodeArts)代码智能体生产环境华为云ECS2vCPU / 2GiB / EulerOS生产环境Python3.12.8(源码编译)生产环境Nginx + systemd反向代理 + 进程守护第三方服务QQ邮箱SMTP验证码邮件发送(SSL:465)第三方服务GitHub代码版本管理第三方服务清华PyPI镜像依赖加速下载二、资源与环境准备2.1 开发环境资源项规格/版本用途说明操作系统Windows 11 (x86_64)本地开发环境Python3.13.13后端开发语言Node.js22.21.1前端运行时与构建工具PostgreSQL18.4本地数据库Git2.52.0版本控制IDE华为云码道(CodeArts)代码智能体AI辅助开发工具2.2 生产环境(华为云ECS)资源项规格/版本用途说明云服务商华为云基础设施提供方实例规格ECS 2vCPU / 2GiB应用服务器操作系统EulerOS (x86_64)服务器操作系统Python3.12.8(源码编译安装)后端运行环境PostgreSQL系统自带版本生产数据库Nginx系统自带版本反向代理 + 静态文件服务进程管理systemd后端服务守护与自动重启2.3 网络与安全配置华为云ECS实例需开放以下安全组端口:端口协议用途80HTTPNginx对外Web服务443HTTPS(预留)SSL加密访问22SSH远程运维管理5432PostgreSQL数据库访问(仅内网)8000HTTPFastAPI后端服务(仅Nginx内部代理)生产环境中PostgreSQL和FastAPI端口不对外暴露,所有外部请求通过Nginx反向代理转发,确保系统安全。2.4 第三方服务服务提供商用途SMTP邮件服务QQ邮箱(SSL:465)发送注册验证码Git仓库GitHub代码版本管理与协作PyPI镜像清华大学开源镜像站Python依赖加速下载三、系统架构设计3.1 总体架构系统采用前后端分离的B/S架构,分为表现层、应用层、数据层三个层次:表现层:Vue3 + Element Plus + Pinia,负责页面渲染、用户交互和前端状态管理;应用层:FastAPI异步框架,提供RESTful API服务,包含认证、业务逻辑、文件上传等模块;数据层:PostgreSQL数据库,存储用户、设备、订单、评价、分类、验证码等核心数据。3.2 技术选型层次技术选型理由后端框架FastAPI原生async/await支持,自动OpenAPI文档生成ORMSQLAlchemy 2.0异步ORM支持,与FastAPI完美配合数据库驱动asyncpg纯Python异步驱动,性能优于psycopg2异步模式数据库PostgreSQL支持部分唯一索引,并发控制方案的关键依赖前端框架Vue3组合式API,更好的代码复用和类型推导UI组件库Element Plus丰富的企业级UI组件状态管理PiniaAPI简洁,TypeScript支持优于Vuex构建工具Vite极速HMR,开发体验优秀3.3 数据模型设计系统核心数据模型包括6个实体,关系如下:User(用户):1对多→Device、Order、Review;Device(设备):多对1→Category、User;1对多→Order;Order(订单):多对1→Device、User(买家);1对1→Review;Review(评价):1对1→Order;Category(分类):1对多→Device;EmailCode(验证码):独立表,关联email字段。3.4 API接口设计系统遵循RESTful规范,所有接口统一前缀 /api/v1,返回格式为 {code, message, data}。核心接口如下:模块方法路径说明认证POST/api/v1/auth/register注册(含邮箱验证码)认证POST/api/v1/auth/login登录认证POST/api/v1/auth/send-register-code发送验证码设备GET/POST/api/v1/devices设备列表/发布设备GET/PUT/api/v1/devices/{id}设备详情/更新订单POST/api/v1/orders下单订单PUT/api/v1/orders/{id}/confirm确认订单评价POST/api/v1/reviews提交评价分类GET/api/v1/categories分类列表用户GET/PUT/api/v1/users/me当前用户信息/更新3.5 部署架构生产环境部署在华为云ECS实例上,Nginx作为反向代理和静态文件服务器,Uvicorn运行FastAPI应用,systemd负责进程守护:客户端 → Nginx(:80) → FastAPI(:8000) → PostgreSQL(:5432) Nginx将 /api/* 请求代理至后端,/uploads/* 代理至后端静态文件,其余请求返回前端打包后的dist文件。后端通过systemd服务管理,开机自启、崩溃自动重启。四、使用华为云码道(CodeArts)代码智能体辅助开发4.1 开发流程概述本项目全程使用华为云码道(CodeArts)代码智能体作为核心开发工具,采用SDD(Specification-Driven Development)文档驱动开发方法论,从需求规格说明到代码实现、测试验证、生产部署,实现了AI辅助的全流程闭环开发。4.2 需求细化与文档生成在项目启动阶段,通过CodeArts代码智能体的SDD技能,从用户需求描述自动生成了完整的文档体系:首先让ai生成系统设计文档:设计文档产出:之后使用skill优化文档:然后根据系统设计文档生成SDD文档:SDD文档产出:spec.md:需求规格说明书,定义"做什么"(What to Build);design/01~10.md:10份详细设计文档,涵盖认证、设备、交易、评价、分类、个人中心、数据模型、API接口、前端设计、用户管理等;tasks.md:任务分解文档(v1.2),4大部分24个任务,每个任务有明确的验收标准。CodeArts代码智能体根据自然语言需求描述,自动拆解为EARS格式的需求条目,并生成对应的技术设计文档,极大减少了需求遗漏和设计偏差。4.3 代码生成与迭代在代码实现阶段,CodeArts代码智能体发挥了以下核心作用:(1)模型与Schema自动生成:根据数据模型设计文档,自动生成SQLAlchemy模型类、Pydantic Schema类,包含字段校验、类型注解、关联关系等。(2)业务逻辑实现:根据API接口设计文档,自动生成Service层和API路由代码,包括参数校验、权限检查、异常处理、数据库事务等。(3)前端页面开发:根据前端设计文档,自动生成Vue3组件代码,包括模板结构、响应式数据、API调用、路由配置等。(4)实时调试与修复:在开发过程中遇到的问题(如asyncpg时区问题、MissingGreenlet异常、Element Plus样式覆盖等),CodeArts代码智能体能够快速定位根因并提供修复方案。4.4 测试与调试CodeArts代码智能体在测试环节提供了以下支持:后端单元测试:自动生成Service层测试用例,覆盖核心业务逻辑;后端集成测试:自动生成API端到端测试,覆盖认证、分类、评价、用户等模块;前端单元测试:自动生成工具函数和Store逻辑的测试用例;E2E联调测试:自动生成前后端完整交互流程的验证脚本。CodeArts代码智能体能够根据代码变更自动生成对应的测试用例,并在测试失败时分析错误日志、定位问题代码、提供修复建议,显著提升了测试效率。4.5 部署与运维在部署阶段,CodeArts代码智能体通过paramiko库实现远程SSH连接华为云ECS服务器,自动化完成以下操作:安装PostgreSQL、Nginx、Python 3.12(从源码编译);配置数据库(创建库、设置密码、pg_hba.conf认证方式调整);创建Python虚拟环境并安装全部依赖(配置清华镜像源加速);初始化数据库表结构并导入种子数据;配置systemd服务实现进程守护和开机自启;配置Nginx反向代理(/api/→后端,其余→前端静态文件);通过SFTP上传前端构建产物。整个部署过程无需手动登录服务器操作,CodeArts代码智能体通过脚本化方式一键完成,大幅降低了部署门槛和出错概率。五、解决方案5.1 用户认证与权限管理采用JWT双Token机制(Access Token + Refresh Token),Access Token有效期1小时,Refresh Token有效期7天。通过FastAPI的Depends依赖注入实现权限校验,区分普通用户和管理员角色。密码使用bcrypt加密存储,登录失败5次自动锁定30分钟。注册流程采用邮箱验证码机制:用户输入邮箱后点击"获取验证码",后端生成6位随机数字验证码,通过QQ邮箱SMTP服务发送,验证码5分钟内有效,错误5次后自动失效,60秒内不可重复发送。5.2 设备信息管理设备管理支持完整的CRUD操作,设备状态机包含3个状态:on_sale(在售)、off_shelf(已下架)、sold(已售出)。设备发布时支持多图上传,图片可设置封面、拖拽排序。搜索支持关键词模糊匹配、分类筛选、成色筛选、价格范围筛选,结果支持按价格和时间排序。关键约束:设备存在pending或confirmed状态的订单时禁止下架,确保交易安全。分类设备数量仅统计on_sale状态的设备,避免数据误导。5.3 交易流程管理交易流程通过订单状态机驱动,包含5个状态:pending(待确认)→ confirmed(已确认)→ delivered(已交付)或 cancelled(已取消)。卖家确认订单后设备自动标记为sold,拒绝或取消订单后设备恢复on_sale。并发购买问题通过PostgreSQL部分唯一索引解决:在orders表上创建 idx_order_device_active 索引,确保同一设备同一时间只能有一个活跃订单(pending或confirmed状态),从数据库层面保证数据一致性。5.4 邮箱验证码注册注册流程采用"先验证后注册"模式,确保邮箱真实有效。技术实现要点:新建email_codes表存储验证码记录,包含email、code、used、fail_count、expires_at字段;发送验证码前检查:邮箱是否已注册、60秒内是否已发送(防刷);验证码校验时检查:是否已使用、是否过期、错误次数是否超限(5次);验证通过后标记used=True,用户is_verified=True,注册即可登录;邮件内容采用HTML模板,包含品牌视觉元素和6位数字验证码。5.5 用户管理模块管理员可对普通用户执行封禁、解封、注销、重置密码操作。关键设计:封禁/注销不可操作自己和其他管理员;注销用户时自动下架其所有在售设备、取消其所有活跃订单;封禁用户无法登录(在dependencies.py和auth_service.py中区分管理员封禁与登录失败临时锁定);locked_until=None表示管理员封禁(永久),locked_until>now表示临时锁定。六、核心技术难点与解决思路6.1 并发购买竞态条件【问题】 多个用户同时对同一设备下单,可能导致同一设备被多人购买。【分析】 传统方案是在应用层加锁(如Redis分布式锁),但增加了系统复杂度和外部依赖。更优雅的方式是利用数据库的约束机制。【解决】 在PostgreSQL的orders表上创建部分唯一索引:CREATE UNIQUE INDEX idx_order_device_active ON orders(device_id) WHERE status IN ('pending', 'confirmed'); 该索引确保同一设备在pending或confirmed状态下只能有一条订单记录。当并发请求尝试插入第二条订单时,数据库会抛出唯一约束冲突异常,应用层捕获该异常后返回友好提示。这种方案零外部依赖、性能优异、数据一致性由数据库保证。6.2 asyncpg时区与MissingGreenlet问题【问题】 使用asyncpg驱动时,SQLAlchemy的server_default=func.now()会触发MissingGreenlet异常;datetime.now(timezone.utc)返回的带时区时间戳与PostgreSQL的timestamp without time zone字段不兼容。【解决】 将所有模型的默认时间戳从数据库端生成改为Python端生成:移除server_default=func.now(),改用default=_utcnow(Python端函数);使用datetime.utcnow()替代datetime.now(timezone.utc),避免时区后缀问题;_utcnow函数返回naive datetime(无时区信息),与PostgreSQL的timestamp字段兼容。6.3 Python 3.9兼容性与服务器Python版本升级【问题】 华为云ECS EulerOS默认Python版本为3.9.9,不支持Python 3.10+的str | None语法。初始尝试添加from __future__ import annotations,但与SQLAlchemy的Mapped类型注解存在冲突。【解决】 从CPython源码编译安装Python 3.12.8,配置清华PyPI镜像源加速依赖安装。编译命令:./configure --enable-optimizations --prefix=/usr/local/python312 && make -j2 && make install 安装后创建虚拟环境、安装项目依赖,彻底解决语法兼容性问题,同时获得Python 3.12的性能提升。6.4 邮箱验证码的防刷与安全【问题】 验证码接口可能被恶意刷量,导致邮件服务被封禁或资源浪费。【解决】 采用多层防护策略:60秒冷却期:同一邮箱60秒内不可重复发送验证码;验证码5分钟过期:过期后自动失效,需重新获取;错误次数限制:同一验证码错误5次后标记为已使用,需重新获取;邮箱唯一性检查:发送验证码前检查邮箱是否已注册;SMTP SSL加密:使用465端口SSL连接,防止邮件内容被窃取。6.5 用户封禁与临时锁定的区分【问题】 系统存在两种"锁定"场景:管理员手动封禁(永久)和登录失败自动锁定(30分钟临时),需要区分处理。【解决】 通过locked_until字段区分:场景locked_until值解锁条件管理员封禁None管理员手动解封登录失败临时锁定具体时间(now+30min)超过锁定时间自动解锁正常状态过去的时间或None(初始)无需解锁6.6 前后端跨域与生产环境代理【问题】 开发环境前端(5173端口)访问后端(8000端口)存在跨域问题;生产环境前端为静态文件,API请求需要正确路由。【解决】 采用不同策略处理:开发环境:Vite配置proxy,将/api和/uploads代理至后端,同时配置CORS中间件;生产环境:Nginx反向代理,/api/→后端8000端口,/uploads/→后端静态文件,其余→前端dist;前端API请求统一使用相对路径(/api/v1/...),无需硬编码后端地址。七、总结与展望本项目成功构建了一个功能完善的校园二手设备交易平台,实现了从需求分析、架构设计、代码开发、测试验证到生产部署的全流程闭环。项目的主要成果和经验总结如下:(1)AI辅助开发效率显著提升:通过华为云码道(CodeArts)代码智能体,从需求文档到可运行代码的转化效率大幅提升。SDD文档驱动方法论确保了需求的完整性和可追溯性,AI自动生成的代码质量和规范性达到了生产级标准。(2)技术架构合理可靠:FastAPI异步框架配合PostgreSQL和Vue3的组合,在2vCPU/2GiB的低配云服务器上运行流畅,证明了架构选型的合理性。(3)安全性设计完善:邮箱验证码注册、JWT双Token认证、并发购买防护、用户封禁机制等多层安全措施,有效保障了系统和用户数据安全。(4)部署运维自动化:通过CodeArts代码智能体的远程SSH能力,实现了从代码推送到生产部署的全自动化流程,降低了运维门槛。未来展望:引入实时消息通知(WebSocket),支持订单状态变更即时推送;增加设备收藏和关注功能,提升用户粘性;接入华为云OBS对象存储,替代本地文件存储方案;添加数据统计和可视化看板,辅助运营决策;支持微信/支付宝模拟支付,完善交易闭环。
  • [高校训练营] 基于华为云码道的酒店管理系统
    1、概述1.1 案例介绍本案例基于华为云码道(CodeArts 代码智能体),通过自然语言需求驱动与多轮迭代优化,快速构建一套完整的济云酒店管理Web应用。系统覆盖房间管理、价格管理、客人管理、房费结算四大核心业务模块,实现从入住登记到在住消费,从退房结算到房态更新的酒店全业务闭环,采用纯前端技术栈实现,数据通过浏览器本地存储持久化,开箱即用。1.2 适用对象企业开发者个人开发者高校学生1.3 案例时间本案例总时长预计90分钟。1.4 案例流程说明:开通华为开发者空间,领取华为云码道代码智能体通用体验权限;梳理酒店业务需求,编写结构化提示词,提交码道生成初始单页应用;运行验证核心功能,针对业务闭环、交互体验进行多轮迭代优化;执行工程化拆分,将单文件重构为模块化多目录架构;完成全功能测试验收与品牌定制适配,交付最终项目成果。1.5 资源总览本案例预计花费139元。体验完成后请及时释放资源,避免产生多余的费用。资源名称规格单价(元)华为云码道(CodeArts)代码智能体专业版139/月2、环境和资源准备2.1 领取华为云码道代码智能体使用权限登录华为开发者空间,进入码道 CodeArts产品页,领取通用体验版权限,开通代码智能体(专业版)服务,获取在线代码生成与迭代能力。2.2 IDE安装与部署参考案例《AI IDE华为云码道(CodeArts)代码智能体安装部署》,完成Windows版华为云码道代码智能体安装部署。打开CodeArts软件,等待初始化,然后开始通过描述需求来生成项目代码。3、构建酒店管理应用3.1 项目需求构建3.1.1 核心需求梳理系统需实现酒店住宿全流程管理,核心包含四大业务模块:1.房间管理:房间信息增删改查、房间状态管理、多条件筛选搜索2.价格管理:基础房价配置、周末价格系数、长住优惠规则、特殊日期定价3.客人管理:客人信息档案管理、历史入住记录查询4.房费结算:自动核算房费、额外消费登记、押金抵扣、账单生成打印3.1.2 编写结构化提示词按照从功能目标到技术路径,从核心模块到优化补充、异常修复的结构编写生成提示词,明确纯前端技术栈、localStorage 持久化、左侧导航管理后台布局等要求,精准描述业务规则与字段定义。详细提示词见下:在HotelManagement文件夹下从零开始生成一套完整的酒店住宿管理Web应用,采用纯前端HTML+CSS+原生JavaScript技术栈,无需后端服务与构建工具,直接在浏览器打开index.html即可运行,所有业务数据通过localStorage持久化保存,刷新页面不丢失;项目定位:面向酒店前台工作人员的办公级管理系统,以信息清晰易识别、长时间操作低疲劳、业务流程全闭环、代码结构工程化为核心原则。请严格按照以下所有要求完整实现:一、项目架构与文件拆分规范采用工程化多目录结构,按职责分层拆分文件,禁止单文件堆砌代码,拆分后功能完整可用。最终目录结构如下:(此处目录结构详见下面的目录结构,略去)JS采用 HotelApp 全局命名空间挂载各模块方法,避免全局变量污染;index.html按依赖顺序正确引入所有文件,基础文件在前、业务文件在后。二、视觉风格规范(浅色商务办公风)不采用暗色主题,采用清爽专业的浅色商务风格,降低前台长时间操作视觉疲劳,强化关键信息辨识度。1. 色彩体系- 主色调:商务蓝 #165DFF,用于主按钮、选中态、重点数据高亮- 页面背景:浅灰色 #F5F7FA;卡片/表格/弹窗底色:纯白色 #FFFFFF- 状态色统一:空闲/成功 #00B42A,已入住/错误 #F53F3F,清洁中/警告 #FF7D00,维修中/禁用 #86909C;状态标签采用浅色背景+深色文字- 文字三级灰度:一级标题/关键数据 #1D2129,二级正文 #4E5969,三级辅助/备注 #86909C- 移除所有玻璃拟态、渐变光晕、深色特效,采用极简扁平化设计,减少视觉干扰2. 组件样式- 左侧导航栏:浅灰底色,选中项蓝色背景+白色文字,hover极浅蓝高亮,图标文字垂直居中- 卡片:统一8px圆角,带柔和阴影,内边距充足- 按钮:主按钮蓝色实心底+白字,次要按钮白底+灰边+深灰字,危险按钮红色底+白字;文字居中,左右内边距均衡- 输入框/下拉框:白底+浅灰边框,聚焦时边框变主色调+淡蓝色外发光- 表格:表头浅灰底色,行高充足,隔行极淡底色区分三、排版与对齐规范针对不同控件、不同字段类型采用差异化对齐,兼顾美观与信息读取效率。1. 表格类- 所有表头文字居中对齐- 文本类字段(房间号、客人姓名、房型、备注)左对齐- 数值类字段(房价、金额、入住天数、押金)右对齐- 状态标签列、操作按钮列居中对齐- 所有单元格内容垂直居中2. 表单类- 表单标签统一放在输入框顶部(顶部对齐),不左置- 输入框内文字左对齐,placeholder浅灰色- 表单底部提交/取消按钮组右对齐- 多列表单栅格布局,字段间距均匀3. 统计卡片/数据看板- 指标标签居上、浅灰色弱化,核心数值放大居中展示,辅助数据居下- 卡片标题左对齐,内容区按数据类型灵活对齐4. 通用规则- 所有按钮文字居中- 弹窗标题左对齐,底部按钮组右对齐- 空状态提示文字+图标整体居中四、核心业务功能模块完整实现酒店住宿全流程闭环,默认初始化8间示例房间与对应价格规则。1. 数据看板- 统计卡片:空闲房间、已入住、清洁中、维修中、今日入住、在住客人、今日收入、本月收入- 快捷操作入口:快速入住、快速退房、房间管理、账单管理- 今日在住房间列表展示2. 房间管理- 房间字段:房间号、楼层、房型(单人间/双人间/豪华间/套房)、床位数、基础日房价、状态、备注- 房间状态:空闲、已入住、清洁中、维修中,支持状态流转;清洁中房间可手动标记为空闲- 支持按房间号搜索、按状态/房型/楼层筛选,支持增删改查- 房间号全局唯一校验,已入住房间不可直接删除3. 价格管理- 基础房价:按房型配置基础日房价、周末价格系数- 长住优惠:可视化表单配置多条「连住天数+折扣比例」规则,无需字符串输入- 特殊日期价格:按日期区间配置特殊房价,支持备注说明- 房费结算时自动匹配规则,按天精准计费4. 客人管理- 客人字段:姓名、身份证号、联系电话、备注- 支持增删改查、关键词搜索,可查看客人历史入住与消费记录5. 快速入住- 支持选择空闲房间,填写客人信息、入住人数、押金、入住/退房日期、备注- 支持选择已有客人档案,一键填充信息,无需重复录入- 入住成功后自动更新房间状态为已入住,生成入住订单6. 快速退房- 选择在住房间自动加载入住信息- 支持添加额外消费,预设早餐、加床、洗衣、迷你吧等快捷选项,也可自定义- 支持半天房费规则(默认12点前退房按半天计费,可手动调整)- 实时预览账单明细,包含房费、消费、押金抵扣、应收总额- 支持选择支付方式(现金/微信/支付宝/银行卡)- 退房成功后房间状态自动变为清洁中,生成结算记录7. 房费结算- 结算记录列表,支持按日期区间筛选- 可查看账单详情,包含每日房费明细、额外消费明细- 支持账单打印功能,打印样式专门优化8. 历史记录- 入住记录、结算记录双标签页切换- 支持查看订单详情、账单详情9. 数据管理- 全量数据JSON导出、导入、清空- 不可逆操作均有二次确认五、交互体验与健壮性要求1. 交互优化- 移除所有原生alert/confirm,统一替换为Toast轻提示(成功/错误/警告三类,3秒自动消失)和自定义确认弹窗- 所有表单实时校验,错误提示显示在输入框下方- 所有模态框支持点击遮罩层关闭、按ESC键关闭,表单弹窗支持回车提交- 所有数据列表支持分页,默认每页10条,可切换10/20/50条/页- 侧边栏支持折叠/展开,桌面端可收起为纯图标模式- 所有提交按钮点击后立即禁用,防止重复提交2. 健壮性要求- 所有数值字段禁止输入负数,入住日期必须早于退房日期- localStorage数据损坏时自动初始化默认数据,杜绝白屏- 所有对象、数组操作前做非空判断,避免undefined类报错- 所有删除、结账等不可逆操作增加二次确认六、最终交付要求1. 直接打开 index.html 即可完整运行,无任何控制台报错、无资源4042. 全业务流程可正常跑通,数据联动正确,状态流转闭环3. 视觉风格、排版对齐严格符合上述规范4. 代码结构清晰,每个文件头部添加职责注释,关键逻辑添加说明注释5. 项目为纯静态,无需任何依赖、构建工具与后端服务3.1.3 提交生成需规划文档码道根据我们提示词的需求描述,创建好项目目录,并生成需求文档、实现方案、编码规划三个文档:3.1.4 审核设计文档3.2 项目代码实现3.2.1 项目结构说明HotelManagement/├── index.html # 主页面入口,仅保留 DOM 结构,无内联 CSS 和 JS├── css/ # 样式文件目录│ ├── base/│ │ ├── reset.css # 全局样式重置、CSS 变量(颜色 / 字号 / 圆角 / 间距 token)│ │ └── common.css # 通用工具类、统一间距规范│ ├── layout/│ │ └── global.css # 整体页面布局、左侧导航栏、右侧主内容区样式│ ├── components/│ │ ├── button.css # 全类型按钮组件样式│ │ ├── form.css # 输入框、下拉框、文本域、校验提示样式│ │ ├── table.css # 表格容器、表头、单元格样式│ │ ├── modal.css # 模态框遮罩、弹窗容器样式│ │ ├── badge.css # 状态标签、统计卡片、标签页样式│ │ └── pagination.css # 分页器组件样式│ └── pages/│ ├── dashboard.css # 数据看板页面专属样式│ ├── rooms.css # 房间管理页面专属样式│ ├── pricing.css # 价格管理页面专属样式│ ├── guests.css # 客人管理页面专属样式│ ├── settlement.css # 房费结算页面专属样式│ ├── checkin.css # 快速入住页面专属样式│ ├── checkout.css # 快速退房页面专属样式│ ├── history.css # 历史记录页面专属样式│ └── settings.css # 数据管理页面专属样式└── js/ # 脚本文件目录├── utils/│ ├── storage.js # localStorage 读写封装、数据初始化、异常兜底│ ├── validator.js # 表单格式校验工具(身份证 / 手机号 / 金额 / 日期)│ ├── date.js # 日期计算、入住天数核算、日期格式化│ └── ui.js # Toast 提示、确认弹窗、加载状态通用方法├── modules/│ ├── roomModule.js # 房间管理增删改查、筛选、状态流转│ ├── guestModule.js # 客人档案管理、历史记录、增删改查│ ├── priceModule.js # 基础价格、特殊价格、优惠规则、房费核算│ ├── checkinModule.js # 入住登记、订单生成、状态联动│ ├── checkoutModule.js # 退房核算、额外消费、结算提交│ ├── settlementModule.js # 结算记录、账单详情、打印│ ├── dashboardModule.js # 数据看板统计、指标计算、渲染│ ├── historyModule.js # 入住 / 结算历史记录查询、详情│ └── settingsModule.js # 数据导入、导出、清空└── app.js # 项目主入口、导航路由、全局事件绑定、模块注册3.2.2 关键源码讲解本项目代码已开源至cid:link_0,欢迎访问。3.2.2.1 storage.js 本地持久化工具(核心数据层)统一封装浏览器 localStorage 读写、异常捕获、系统初始化逻辑,是整个项目的数据底层支撑。所有房间、客人、订单、价格数据全部通过该文件存取,数据损坏时自动加载默认 8 间客房示例数据,避免页面白屏。统一存储前缀隔离项目数据,防止和其他网站缓存冲突;读写失败捕获异常并控制台打印错误;系统首次打开自动初始化全套基础业务数据;提供单条删除、全量清空、全量读取标准化接口,所有业务模块共用这套存储方法。3.2.2.2 calculator.js 房费计算引擎(业务核心算法)整套系统计费核心,自动按入住日期逐日核算房价,叠加基础价、周末溢价、节假日特殊价、长住折扣,自动计算应收总额、押金抵扣。自动计算入住自然天数,区分跨月 / 跨年日期;自动识别周六周日叠加价格系数;匹配自定义节假日特殊房价;按最长连住规则自动应用折扣;支持半天退房计费、额外消费累加、押金抵扣核算。本文件完全隔离复杂数学计算逻辑,页面交互层只需要传入房间和日期,直接拿到最终账单金额,避免前台手动算价出错。3.2.2.3 roomModule.js 房间业务模块(房态流转核心)封装房间增删改查、多条件筛选、房态状态合法流转校验,管控房间全生命周期。新增房间自动校验房间号唯一,重复直接拦截;限制非法房态切换:已入住房间不能直接改为维修、清洁房只能切空闲 / 维修;删除房间前置校验:正在入住的房间禁止删除;支持按楼层、房型、房号、状态多维度筛选房间列表。能够做到约束酒店真实业务规则,杜绝不符合运营逻辑的操作,保证房态数据自洽。3.2.2.4 app.js 项目入口 & 全局 UI 调度(页面中枢)系统唯一入口 JS,控制侧边栏导航切换、页面显示隐藏、全局 Toast 弹窗、页面自动渲染、时钟展示。页面 DOM 加载完成自动初始化存储、加载首页看板数据;侧边栏点击切换对应业务页面,自动高亮当前菜单;封装统一轻提示 Toast,替代原生 alert,风格和系统 UI 统一;封装通用确认弹窗,所有删除、清空高危操作复用;各页面渲染函数统一调度,看板、房间、客人列表自动刷新。主要负责串联所有业务模块,统一全局交互,分离页面渲染和底层数据逻辑。3.2.2.5 index.html 项目主入口页面(整体骨架)项目唯一 HTML 载体,定义整套系统页面 DOM 结构、导航菜单、9 大业务页面容器、弹窗模板、所有表单结构,统一引入拆分后的 CSS/JS 资源文件。采用侧边导航 + 右侧内容经典后台布局;分页面容器:看板、房间、客人、入住、退房、价格、结算、历史、数据管理;内置新增房间、新增客人、账单弹窗 DOM 模板;规范资源引入顺序:先基础 CSS、组件 CSS,再工具 JS、业务模块 JS,最后入口 app.js;内置打印专用页面布局,账单打印自动隐藏操作按钮。3.2.3 运行调试本项目基于原生HTML、CSS、JavaScript 开发,不用部署服务器,双击打开即可使用,所有业务数据都保存在浏览器本地。3.2.3.1 数据看板模块打开系统首先看到的是数据看板,这里汇总了酒店最核心的运营指标,前台上班第一眼就能掌握整体房态和营收情况。可以看到当前的空闲房、在住房、清洁房、维修房数量,还有今日入住数、在住客人数,以及今日和本月的营收统计。下方是今日在住客人列表,能快速看到每个房间的客人姓名和入住退房时间。左侧导航栏支持折叠收起,给内容区留出更多空间,设计上也兼顾了不同使用习惯:3.2.3.2 房间管理模块房间状态用四种颜色区分:绿色空闲、红色已入住、橙色清洁中、灰色维修中,辨识度很高,前台扫一眼就能掌握房态。支持新增和编辑房间信息,房间号会自动校验唯一性,不会重复;房态流转是受控的,比如已入住的房间不能直接删除,也不能随意改状态,必须按业务流程来,避免误操作。清洁完成的房间可以手动标记为空闲,回到可用状态;表格的排版也做了优化:表头居中对齐,房间号、房型这类文本左对齐,房价这类数值右对齐,操作按钮居中,符合财务类数据的阅读习惯,核对金额的时候更直观: 3.2.3.3 价格管理模块价格管理模块用来配置酒店的计费规则,支持多层定价逻辑。首先是各房型的基础日房价,然后可以设置周末价格上浮系数,比如周末房价是平时的 1.2 倍;所有规则配置好之后,退房结算时系统会自动算价,不用前台手动核算,既提高效率也避免算错账:3.2.3.4 客人管理模块客人管理模块用来维护客人档案;同时每个客人都有对应的历史入住和消费记录,方便酒店了解客史,提供更好的服务。新增客人时会自动校验身份证和手机号格式,填错了会实时提示: 3.2.3.5 快速入住模块快速入住页面是前台最高频使用的功能。首先选择空闲房间,这里只显示空闲状态的房间,已入住的不会出现,避免选错。填好客人信息、入住退房日期、押金和备注,点击确认入住就完成了。系统会自动生成入住订单,同时把房间状态改成已入住,整个流程联动起来,不用手动去改房态:切回房间管理看一下,302 已经变成红色的已入住状态,数据是实时同步的:3.2.3.6 快速退房 + 结算客人退房的时候,我们用快速退房功能。选择在住房间,系统会自动带出客人信息和入住时长,不用重复填写;右边是实时账单预览,房费是系统自动算的,已经叠加了周末价这些规则,加上额外消费,再抵扣押金,最后就是客人实际要付的金额,每一笔都清清楚楚;选择支付方式,确认退房就完成结算了。退房之后房间自动变成清洁中状态,等待保洁打扫完成后再放回空闲房态,形成完整的业务闭环:3.2.3.7 数据管理模块最后是数据管理模块,支持把所有业务数据导出成 JSON 文件备份,换电脑或者清缓存之后,可以再导入恢复,不用担心数据丢失。也可以一键清空所有数据,重置系统:整体来看,这套系统覆盖了酒店前台的全部核心业务,操作简单直观,不用复杂培训就能上手。如需要进一步了解功能,参见3.2.2节的仓库中视频。4、释放资源无云服务实例需要删除释放;若不再需要本济酒店管理系统项目,直接删除本地HotelManagement完整项目文件夹,即可释放本地磁盘存储空间;关闭华为开发者空间网页标签页,退出登录账号即可;如需彻底清空对话历史,进入码道对话页面删除本次项目全部提示词与代码对话记录。5、扩展资料说明想了解更多原生HTML/CSS/JS静态开发、本地存储相关技术可查阅 MDN 官方文档。
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的校园场馆预约系统
    基于华为云码道代码智能体的运动场馆管理系统1、案例介绍1.1 案例介绍校园运动场馆资源分散、借用流程混乱、时间冲突频发?本案例基于 Vue3 + Express 全栈架构,借助华为云码道代码智能体,从零到一构建一套运动场馆智能管理系统。系统支持课表固定占用与临时借用双模式,提供基于时间段的可用场馆智能推荐,实现场馆资源的高效调度与零冲突管理。1.2 适用对象高校学生个人开发者企业开发者1.3 案例时间本案例总时长预计60分钟。1.4 案例流程┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ │ 1 本地环 │───▶│ 2.CodeArts智能体 │───▶│ 3.依赖安装与 │───▶│ 4.运行调试 │ │ 境准备 │ │ 生成代码 │ │ 环境适配 │ │ 与验证 │ └──────────────┘ └──────────────────┘ └──────────────────┘ └──────────────┘说明:准备本地开发环境,安装 Node.js,创建项目目录;在 CodeArts 代码智能体中输入需求,智能体自动生成前后端完整代码;安装项目依赖,遇到原生模块编译问题时由智能体自动适配解决;启动前后端服务,验证系统核心功能。1.5 资源总览本案例预计花费0元。资源名称规格单价(元)华为云码道代码智能体通用体验版免费Node.jsv20+免费2、环境和资源准备2.1 安装 Node.js本案例前端和后端均基于 Node.js 运行,需提前安装 Node.js v20 及以上版本。下载地址:https://nodejs.org/安装完成后,在终端验证:node --version npm --version 2.2 开通华为云码道代码智能体登录华为云控制台,搜索"CodeArts",进入 CodeArts 服务页面,开通代码智能体通用体验版(免费)。开通后即可在 CodeArts IDE 中使用 AI 辅助编程功能。3、构建运动场馆管理系统3.1 创建项目目录在终端中创建项目目录:mkdir yundongchangguan cd yundongchangguan3.2 使用 CodeArts 代码智能体生成项目代码在 CodeArts IDE 中打开代码智能体对话窗口,输入需求:实现这个运动场馆管理系统:某学校有各类运动场馆若干,包括足球场、篮球场、羽毛球场等。运动场馆可以按照课表设置为一段时间固定时间占用,非固定占用时间可以临时借用。借运动场馆时可根据时间段需求系统提供可用场地推荐,也可通过场馆列表挑选借用;实现借用情况查询、取消借用功能。CodeArts 代码智能体将自动完成以下工作:识别任务复杂度,创建多步骤 Todo 清单进行任务管理一次性生成完整项目结构,包括 package.json、vite.config.js、index.html、路由配置、API封装自动选择技术栈:Vue3 + Element Plus + Express + SQLite,无需人工指定生成数据库模型与种子数据,预置10个场馆和12条课表,开箱即用实现所有 API 接口,含时间冲突检测与智能推荐逻辑生成前端页面组件,包括登录页、数据看板、场馆管理、课表管理、借用场馆、借用查询6个页面1)项目结构说明yundongchangguan/ ├── package.json # 项目依赖与脚本配置 ├── vite.config.js # Vite构建配置(含API代理) ├── index.html # 前端入口HTML ├── server/ # 后端服务 │ ├── index.js # Express服务入口 │ ├── database.js # 数据库初始化、工具函数、种子数据 │ ├── utils.js # 错误码定义、参数校验工具函数 │ ├── routes/ │ │ ├── auth.js # 登录认证与权限中间件 │ │ ├── dashboard.js # 数据看板API │ │ ├── venues.js # 场馆CRUD API │ │ ├── schedules.js # 课表管理API(含冲突检测) │ │ └── borrowings.js # 借用管理API(含推荐、取消、时间限制) │ └── tests/ │ ├── test.js # 工具函数与数据库单元测试 │ └── api-test.js # API集成测试 ├── src/ # 前端源码 │ ├── main.js # Vue应用入口 │ ├── App.vue # 主布局(侧边导航+用户信息) │ ├── router/ │ │ └── index.js # 路由配置(6个页面+登录守卫) │ ├── api/ │ │ └── index.js # Axios API封装层(含token拦截器) │ └── views/ │ ├── Login.vue # 登录页面 │ ├── Dashboard.vue # 数据看板页面 │ ├── VenueList.vue # 场馆管理页面 │ ├── ScheduleManage.vue # 课表管理页面 │ ├── BorrowVenue.vue # 借用场馆页面(推荐+列表双模式) │ └── BorrowingQuery.vue # 借用查询与取消页面 └── dist/ # 构建产物(部署用)2)关键代码讲解(一)用户登录与权限控制系统采用 Token 认证机制,登录后返回 token,后续请求携带 token 进行身份验证。管理员可增删改场馆和课表,普通用户只能借用和查询。// server/routes/auth.js const tokens = new Map() router.post('/login', async (req, res) => { const { username, password } = req.body const user = queryGet(db, 'SELECT * FROM users WHERE username = ? AND password = ?', [username, password]) if (!user) return res.json(fail(ERROR_CODES.AUTH_FAILED)) const token = `tk_${user.id}_${Date.now()}_${Math.random().toString(36).slice(2)}` tokens.set(token, { id: user.id, username: user.username, role: user.role, display_name: user.display_name }) res.json(success({ token, user: { id: user.id, username: user.username, role: user.role, display_name: user.display_name } })) }) function authMiddleware(req, res, next) { const token = req.headers.authorization?.replace('Bearer ', '') if (!token || !tokens.has(token)) return res.json(fail(ERROR_CODES.AUTH_TOKEN_EXPIRED)) req.user = tokens.get(token) next() } function adminMiddleware(req, res, next) { if (!req.user || req.user.role !== 'admin') return res.json(fail(ERROR_CODES.AUTH_FORBIDDEN)) next() } (二)时间冲突检测 — 系统核心业务逻辑场馆占用涉及课表(按星期循环)和借用(按具体日期)两种时间维度。系统采用区间重叠判定法统一处理:// server/routes/borrowings.js // 两个时间段重叠的充要条件:A_start < B_end AND A_end > B_start // 检测与课表的冲突(将借用日期转为星期几后比对) const date = new Date(borrow_date) const dayOfWeek = date.getDay() === 0 ? 7 : date.getDay() const scheduleConflict = queryGet(db, 'SELECT * FROM schedules WHERE venue_id = ? AND day_of_week = ? AND (start_time < ? AND end_time > ?)', [venue_id, dayOfWeek, end_time, start_time] ) // 检测与已有借用的冲突 const borrowConflict = queryGet(db, "SELECT * FROM borrowings WHERE venue_id = ? AND borrow_date = ? AND status = 'active' AND (start_time < ? AND end_time > ?)", [venue_id, borrow_date, end_time, start_time] ) (三)借用时间限制校验后端统一校验单次借用不超过2小时、不能借用过去日期:// server/utils.js function validateTimeRange(start_time, end_time, maxMinutes = 120) { const [sh, sm] = start_time.split(':').map(Number) const [eh, em] = end_time.split(':').map(Number) const startMin = sh * 60 + sm const endMin = eh * 60 + em if (endMin <= startMin) return { valid: false, message: '结束时间必须晚于开始时间' } if (endMin - startMin > maxMinutes) return { valid: false, message: `单次借用时长不能超过${maxMinutes / 60}小时` } return { valid: true } } function validateDateNotPast(dateStr) { const today = new Date(); today.setHours(0, 0, 0, 0) if (new Date(dateStr) < today) return { valid: false, message: '不能借用过去的日期' } return { valid: true } } (四)API错误码规范化// server/utils.js const ERROR_CODES = { SUCCESS: 0, PARAM_MISSING: 10001, // 缺少必要参数 PARAM_INVALID: 10002, // 参数格式不正确 AUTH_FAILED: 20001, // 用户名或密码错误 AUTH_TOKEN_EXPIRED: 20002, // 登录已过期 AUTH_FORBIDDEN: 20003, // 无权限 NOT_FOUND: 30001, // 资源不存在 CONFLICT: 40001, // 资源冲突 TIME_LIMIT_EXCEEDED: 40002, // 超出时间限制 SERVER_ERROR: 50001 // 服务器内部错误 } (五)数据库事务保护// server/database.js function runTransaction(db, fn) { db.run('BEGIN TRANSACTION') try { fn(db) db.run('COMMIT') saveDB() } catch (e) { db.run('ROLLBACK') throw e } } // 删除场馆时事务性删除关联数据 router.delete('/:id', authMiddleware, adminMiddleware, async (req, res) => { runTransaction(db, (db) => { db.run('DELETE FROM borrowings WHERE venue_id = ?', [id]) db.run('DELETE FROM schedules WHERE venue_id = ?', [id]) db.run('DELETE FROM venues WHERE id = ?', [id]) }) }) (六)前端表单校验与时间限制提示<!-- src/views/BorrowVenue.vue --> <el-alert type="info" :closable="false">单次借用时长不超过2小时,需提前1天预约</el-alert> <el-form ref="borrowFormRef" :model="borrowForm" :rules="borrowRules"> <el-form-item label="借用人" prop="borrower_name"> <el-input v-model="borrowForm.borrower_name" /> </el-form-item> </el-form> <script> const borrowRules = { borrower_name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], borrower_dept: [{ required: true, message: '请输入部门/班级', trigger: 'blur' }], end_time: [{ required: true, message: '请选择结束时间', trigger: 'change' }, { validator: validateTimeLimit, trigger: 'change' }] } </script> 3.3 安装依赖与环境适配1)安装项目依赖npm install 2)遇到的问题:原生模块编译失败安装过程中 better-sqlite3 因需要原生编译而失败,报错信息:npm error command failed npm error command C:\WINDOWS\system32\cmd.exe /d /s /c prebuild-install || node-gyp rebuild --release npm error 'node' 不是内部或外部命令CodeArts 代码智能体自动处理过程:识别根因为 node-gyp 子进程找不到 node 命令,属于原生模块编译依赖问题自主将 package.json 中的 better-sqlite3 替换为 sql.js(纯JS实现,无需原生编译)重写 server/database.js,适配 sql.js 的异步初始化模式(initSqlJs())增加 saveDB() 函数,在每次写操作后手动持久化到文件(sql.js 默认在内存中运行)同步更新所有路由文件(venues.js、schedules.js、borrowings.js)为 async/await 模式重新执行 npm install 成功这一过程体现了 CodeArts 代码智能体的问题诊断与自主修复能力,无需人工介入即可完成技术方案切换。3.4 运行调试与功能验证1)启动后端服务新开一个终端窗口,执行:cd yundongchangguan node server/index.js看到以下输出表示后端启动成功:服务端运行在 http://localhost:30002)启动前端开发服务器再开一个终端窗口,执行:cd yundongchangguan npx vite看到以下输出表示前端启动成功: VITE v5.x.x ready in xxx ms ➜ Local: http://localhost:5173/3)登录系统浏览器访问 http://localhost:5173,进入登录页面。使用预置账号登录:角色用户名密码管理员adminadmin123普通用户user11234564)数据看板登录后进入数据看板页面,展示场馆总数、可用场馆数、今日借用数、有效借用数等统计信息,以及场馆利用率排行和最近借用记录。5)场馆管理在场馆管理页面查看10个预置场馆的卡片展示,管理员可新增、编辑、删除场馆。6)课表管理在课表管理页面查看12条预置课表,管理员可新增课表(含冲突检测)、编辑、删除。7)智能推荐借用在借用场馆页面,切换到"智能推荐"标签,选择日期和时间段后点击"查找可用场馆",系统自动排除有课表占用和已有借用的场馆。8)场馆列表借用切换到"场馆列表借用"标签,直接从列表中选择场馆,填写借用信息提交。表单校验会检查必填项和2小时时间限制。9)借用查询与取消在借用查询页面,按场馆/姓名/日期/状态筛选借用记录,可取消有效借用。10)单元测试运行单元测试和API集成测试:npm test 测试覆盖内容:测试类型测试项数量工具函数success/fail/validateRequired/validateTimeRange/validateDateNotPast10数据库预置数据/管理员用户/事务回滚5API集成登录/看板/分页/时间限制/过去日期/未登录拒绝/权限控制811)构建前端产物npx vite build4、核心技术难点与解决思路难点一:时间段冲突检测的准确性问题: 场馆占用涉及课表(按星期循环)和借用(按具体日期)两种不同维度的时间表示,需准确判定冲突。解决思路:课表以 day_of_week(1-7)表示周期性占用,借用以 borrow_date(具体日期)表示一次性占用检测借用冲突时,先将借用日期转换为星期几(new Date(borrow_date).getDay()),再与课表比对统一使用区间重叠公式 start_time < end AND end_time > start 进行冲突判定,避免边界条件遗漏难点二:原生模块编译失败的环境适配问题: 初始选用 better-sqlite3 作为SQLite驱动,但在Windows环境下因 node 不在系统PATH中,导致 node-gyp 编译失败。解决思路:CodeArts 代码智能体自动识别根因为原生模块编译依赖问题,而非代码逻辑错误自主将 better-sqlite3(需原生编译)替换为 sql.js(纯JS实现,WASM运行)重写数据库操作层,适配 sql.js 的异步初始化模式(initSqlJs())增加 saveDB() 函数,在每次写操作后手动持久化到文件(sql.js 默认在内存中运行)所有路由处理函数改为 async/await 模式以适配异步数据库初始化难点三:用户权限与接口安全问题: 系统需区分管理员和普通用户角色,管理员可管理场馆和课表,普通用户只能借用和查询,所有接口需鉴权保护。解决思路:登录成功后生成内存级 Token,前端存储在 localStorage 并通过 Axios 拦截器自动携带后端通过 authMiddleware 校验 Token 有效性,adminMiddleware 校验管理员权限前端路由守卫拦截未登录访问,自动跳转登录页Token 过期时后端返回 20002 错误码,前端自动清除本地存储并跳转登录难点四:前后端数据一致性保障问题: 借用操作涉及冲突检测和数据写入两步,若写入过程中断可能导致数据不一致。解决思路:引入 runTransaction() 函数,在删除场馆等涉及多表操作的场景使用事务保护删除场馆时事务性删除关联的借用记录和课表记录,保证数据完整性事务失败时自动 ROLLBACK,避免脏数据项目代码及演示视频
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的酒店房间管理系统开发
    用码道(CodeArts)从零搭建酒店住宿管理系统——AI编程实战案例一、前言本项目体验了华为云的码道(CodeArts)代码智能体,用它从零开始搭建了一个酒店住宿管理系统。整个开发过程中,从需求分析、数据库设计、后端API开发到前端界面实现,全程与AI对话完成。本文将以我和码道的交互对话为主线,完整记录这个开发过程,分享给对AI辅助编程感兴趣的开发者。最终技术栈:后端:Python Flask + SQLAlchemy + PyMySQL前端:Vue3 + Element Plus + Vite数据库:MySQL 8.0项目地址:https://github.com/Monday23333333/HotelManagementDemo二、第一阶段:需求描述与数据库设计我:帮我设计一个酒店住宿管理系统的数据库我向码道描述了酒店管理系统的基本需求:需要管理房间、客人、入住记录和账单。码道很快给出了完整的数据库设计方案。码道:生成了5张核心表 + 1张会员等级表-- 码道设计的6张表 room_type -- 房型(支持工作日/周末/节假日差异化定价) room -- 房间(状态:空闲/入住/维护/预订) vip_level -- 会员等级(经验门槛+折扣率) guest -- 客人(关联会员等级,经验自动累计) check_in -- 入住记录(状态:在住/已退房) billing -- 账单(房费+额外费用-折扣=总额) 我:会员等级由消费经验自动决定,创建客人时不需要手动选择VIP等级我补充了一个重要的业务规则:会员等级不应该手动选择,而是根据消费经验自动升级。码道理解后,在Guest模型中加入了exp字段和vip_level_id外键,并设计了自动升级逻辑。码道:修改了Guest模型,增加经验自动累计机制class Guest(db.Model): __tablename__ = 'guest' # ... vip_level_id = db.Column(db.BigInteger, db.ForeignKey('vip_level.id'), default=1) exp = db.Column(db.Integer, default=0) # 经验值,消费1元=1点 vip = db.relationship('VipLevel', lazy='joined') 三、第二阶段:后端API开发(从Spring Boot到Flask的转折)我:用Spring Boot实现后端API一开始我选择的是Spring Boot + MyBatis,码道也按照这个方案生成了代码。遇到问题:JDK环境不支持运行时发现本地只有JDK 1.7/1.8的JRE(非JDK),无法编译Java项目。Maven中央仓库还有SSL证书问题,依赖下载失败。我:本地JDK环境有问题,能换成Python方案吗?码道:建议切换到Flask + SQLAlchemy码道快速分析了环境问题,建议改用Python Flask + SQLAlchemy方案,并立即重新生成了全部后端代码。几分钟后后端就跑通了!# backend/app/__init__.py - 应用工厂 def create_app(): app = Flask(__name__) app.config.from_object(Config) CORS(app, supports_credentials=True) db.init_app(app) register_routes(app) return app # backend/app/config.py - 数据库配置 class Config: SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root@localhost:3306/hotel_db?charset=utf8mb4' SQLALCHEMY_TRACK_MODIFICATIONS = False JSON_AS_ASCII = False # backend/run.py - 启动入口 if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True) 我:房费要按工作日和周末差异化计算码道:实现了_calc_room_charge函数,逐天判断工作日/周末def _calc_room_charge(checkin): room = Room.query.filter_by(id=checkin.room_id, deleted=0).first() rt = RoomType.query.filter_by(id=room.room_type_id, deleted=0).first() start = checkin.check_in_time end = checkin.actual_checkout_time or datetime.now() days = (end.date() - start.date()).days if days <= 0: days = 1 total = Decimal('0') for i in range(days): day = start + timedelta(days=i) if day.weekday() >= 5: # 周末 total += rt.weekend_price if rt.weekend_price else rt.base_price else: # 工作日 total += rt.base_price return total我:退房时如果房费未结算,要提示用户码道:新增了/api/check-in/settled/<id>接口和退房检查逻辑后端新增结算检查接口:@app.route('/api/check-in/settled/<int:id>') def checkin_settled(id): billing = Billing.query.filter_by(check_in_id=id, deleted=0, status='PAID').first() return success({'settled': billing is not None}) 支付时自动累加经验并升级会员等级:def _add_exp_and_upgrade(guest_id, amount): guest = Guest.query.filter_by(id=guest_id, deleted=0).first() if not guest: return exp_gain = int(float(amount)) # 消费1元=1点经验 if exp_gain <= 0: return guest.exp = (guest.exp or 0) + exp_gain # 从高到低匹配等级,自动升级 best_level = VipLevel.query.filter_by(deleted=0).order_by(VipLevel.min_exp.desc()).all() for vl in best_level: if guest.exp >= vl.min_exp: guest.vip_level_id = vl.id break 四、第三阶段:前端页面开发我:用Vue3实现前端页面,现代卡片式界面风格码道:生成了完整的7个页面 + 主布局 + API封装4.1 主布局:深色侧边栏 + 浅色内容区<!-- frontend/src/App.vue --> <template> <div class="app-container"> <aside class="sidebar"> <div class="logo"> <el-icon :size="28"><House /></el-icon> <span class="logo-text">酒店管理系统</span> </div> <nav class="nav-menu"> <router-link v-for="item in menuItems" :key="item.path" :to="item.path" class="nav-item" :class="{ active: $route.path === item.path }"> <el-icon :size="20"><component :is="item.icon" /></el-icon> <span>{{ item.label }}</span> </router-link> </nav> </aside> <main class="main-content"> <header class="top-bar"> <h2 class="page-title">{{ $route.meta.title }}</h2> </header> <div class="content-area"><router-view /></div> </main> </div> </template> 侧边栏采用深紫色渐变(#1e1b4b → #312e81),激活项带发光阴影。4.2 首页概览:客房可视化看板我:可视化面板的占用率要把预订和维护也算进去,不只是入住码道:修改了占用率计算逻辑,status !== 'AVAILABLE'都算占用<!-- frontend/src/views/Dashboard.vue --> const floorData = computed(() => { const map = {} for (const r of rooms.value) { const f = r.floor if (!map[f]) map[f] = { floor: f, rooms: [], occupied: 0, total: 0 } map[f].rooms.push(r) map[f].total++ // 占用率包含预订和维护(不只是入住) if (r.status !== 'AVAILABLE') map[f].occupied++ } return Object.values(map).sort((a, b) => b.floor - a.floor).map(f => ({ ...f, rate: f.total > 0 ? Math.round(f.occupied / f.total * 100) : 0 })) }) const floorBgColor = (floor) => { const r = floor.rate if (r === 0) return 'linear-gradient(90deg, #f0fdf4 0%, #ecfdf5 100%)' if (r <= 30) return 'linear-gradient(90deg, #fefce8 0%, #fef9c3 100%)' if (r <= 60) return 'linear-gradient(90deg, #fff7ed 0%, #fed7aa 100%)' if (r <= 90) return 'linear-gradient(90deg, #fef2f2 0%, #fecaca 100%)' return 'linear-gradient(90deg, #fef2f2 0%, #fca5a5 100%)' } 每层楼一行,房间用色块表示状态(绿=空闲、黄=入住、红=维护、蓝=预订),悬停显示详情弹窗。4.3 房间管理:卡片式展示房间以卡片形式展示,顶部色条标识状态,支持下拉快速切换房间状态。4.4 入住管理:退房未结算警示我:退房时如果房费没结算,提示"该客人房费还未结算,直接退房后将不可再结算。是否确认退房?"码道:在退房流程中加入了checkSettled检查和二次确认弹窗<!-- frontend/src/views/CheckIn.vue --> const handleCheckOut = async (row) => { try { const res = await checkSettled(row.id) if (!res.data.settled) { await ElMessageBox.confirm( '该客人房费还未结算,直接退房后将不可再结算。是否确认退房?', '房费未结算提醒', { confirmButtonText: '确认退房', cancelButtonText: '取消', type: 'warning' } ) } else { await ElMessageBox.confirm('确定办理退房?', '提示', { type: 'warning' }) } } catch (e) { if (e === 'cancel') { router.push('/billing') // 取消则跳转结算页 return } return } await doCheckOut(row.id) ElMessage.success('退房成功') loadCheckIns() } 4.5 入住管理:入住人数联动房型上限我:选择房间后,入住人数要跟房型的最大入住人数联动码道:用computed属性动态计算maxGuestCount,切换房间时自动修正const maxGuestCount = computed(() => { if (!checkInForm.value.roomId) return 10 const room = availableRooms.value.find(r => r.id === checkInForm.value.roomId) if (!room) return 10 const rt = roomTypes.value.find(t => t.id === room.roomTypeId) return rt ? rt.maxOccupancy : 10 }) const onRoomChange = () => { if (checkInForm.value.guestCount > maxGuestCount.value) { checkInForm.value.guestCount = maxGuestCount.value } } 4.6 会员体系:等级卡片与经验条<!-- frontend/src/views/VipLevel.vue --> <div class="vip-card" v-for="(vl, idx) in vipLevels" :key="vl.id" :style="{ borderLeftColor: levelColors[idx % levelColors.length] }"> <div class="vip-name" :style="{ color: levelColors[idx % levelColors.length] }"> {{ vl.name }} </div> <div class="vip-row"> <span class="vip-label">折扣率</span> <span class="vip-value discount"> {{ vl.discountRate < 1 ? (vl.discountRate * 10).toFixed(1) + '折' : '无折扣' }} </span> </div> <div class="vip-exp-bar"> <div class="vip-exp-fill" :style="{ width: Math.min(vl.minExp / maxExp * 100, 100) + '%', background: levelColors[idx % levelColors.length] }"> </div> <span class="vip-exp-text">{{ vl.minExp }} exp</span> </div> </div> 4.7 房费结算账单表格展示房费、额外费用、折扣和总额,支持支付、编辑和删除操作。五、完整项目结构hotel-management/ ├── backend/ # Flask后端 │ ├── app/ │ │ ├── __init__.py # 应用工厂:创建Flask实例、初始化DB和CORS │ │ ├── config.py # 数据库连接配置 │ │ ├── models.py # SQLAlchemy数据模型(6个) │ │ ├── routes.py # REST API路由(20+接口) │ │ └── response.py # 统一响应格式封装 │ ├── run.py # 启动入口(0.0.0.0:8080) │ └── requirements.txt # Python依赖 ├── frontend/ # Vue3前端 │ ├── src/ │ │ ├── App.vue # 主布局:侧边栏+顶栏+内容区 │ │ ├── main.js # Vue3入口 │ │ ├── router/ │ │ │ └── index.js # 路由配置(7个页面+路由守卫) │ │ ├── api/ │ │ │ ├── request.js # Axios封装(baseURL+拦截器) │ │ │ └── hotel.js # 全部API调用函数 │ │ └── views/ │ │ ├── Dashboard.vue # 首页概览+客房可视化 │ │ ├── Room.vue # 房间管理(卡片式) │ │ ├── RoomType.vue # 房型价格管理 │ │ ├── Guest.vue # 客人管理 │ │ ├── CheckIn.vue # 入住管理 │ │ ├── Billing.vue # 房费结算 │ │ └── VipLevel.vue # 会员体系管理 │ ├── index.html │ ├── package.json │ └── vite.config.js # Vite配置(代理8080)六、交互过程总结:我和码道的完整对话链路回顾整个开发过程,我和码道的交互可以概括为以下几个阶段:阶段我的输入码道的输出需求分析“帮我设计酒店住宿管理系统的数据库”6张表的完整设计业务规则“会员等级由消费经验自动决定”修改Guest模型,增加exp字段和自动升级逻辑技术选型“本地JDK有问题,换成Python”从Spring Boot切换到Flask,重新生成全部后端业务逻辑“房费按工作日/周末差异化计算”_calc_room_charge函数,逐天判断计价业务逻辑“退房时房费未结算要提示”新增settled接口 + 前端二次确认弹窗前端开发“用Vue3实现,现代卡片式风格”7个页面组件 + 主布局 + API封装需求修正“占用率要把预订和维护也算进去”修改Dashboard计算逻辑需求修正“入住人数要联动房型上限”computed动态计算maxGuestCount关键体会:自然语言即需求文档:我不需要写PRD,直接用对话描述需求,码道就能理解并实现遇到阻塞能快速转向:JDK环境出问题时,一句话就切换到Flask方案增量迭代非常自然:先搭骨架,再逐步补充业务规则,每次只需描述差异上下文记忆很关键:码道能记住之前的对话,修改时保持一致性,不会"失忆"七、运行方式# 后端 cd hotel-management/backend pip install -r requirements.txt python run.py # 启动在 http://localhost:8080 # 前端 cd hotel-management/frontend npm install npm run dev # 启动在 http://localhost:5173,代理API到8080 # 数据库 # 需要先创建 hotel_db 数据库,并执行初始化SQL 八、总结通过这次实战,我深刻感受到AI辅助编程带来的效率提升。码道(CodeArts)不仅能快速生成代码,更重要的是——它能理解我的业务需求,和我进行有意义的对话。当我说"退房时房费没结算要提示",它不仅加了提示,还考虑了取消后跳转结算页的交互细节。当然,AI生成的代码不是万能的,复杂的业务规则、性能优化、安全加固等仍需要开发者的专业判断。AI是工具,人是核心——善用工具,让开发更高效!
  • [训练营] 汽车销售管理系统
    汽车销售管理系统仓库地址:汽车销售管理系统 - AtomGit一、题目选择与分析选择题目:汽车销售管理能够实现4S店的车辆种类、价格等进行管理,能够对客户进行管理,实现客户购买车辆的流程管理,费用结算等功能。分析该题目,需要实现的功能:1.车辆管理功能说明添加车辆录入品牌、型号、价格、库存数量删除车辆移除不再销售的车辆信息修改车辆更新车辆的品牌、型号、价格或库存查询车辆查看所有车辆列表,支持按品牌或型号搜索 2.客户管理功能说明添加客户录入客户姓名、联系方式删除客户移除客户信息修改客户更新客户姓名或联系方式查询客户查看所有客户列表 3.销售管理功能说明生成订单选择一个客户和一辆车,创建销售订单更新订单状态订单状态流转:下单 → 已完成自动扣减库存订单完成后,对应车辆的库存自动减1库存校验库存为0的车辆无法被选择下单销售记录所有订单自动保存,可查看历史销售列表             二、利用码道执行任务根据上面的功能需求,我们组织自然语言发送给码道:请帮助我构建一个汽车销售管理的Web应用,要求如下:在当前工作空间目录下创建项目,生成代码; 要求页面符合后台管理系统简洁、美观的风格; 车辆管理、客户管理、销售管理三项基本功能齐全; 具体功能包括: 车辆管理:车辆的增删改查(品牌、型号、价格、库存); 客户管理:客户信息的增删改查(姓名、联系方式); 销售管理:选择客户和车辆生成订单,更新订单状态; 车辆售出后自动扣减库存,库存为0时不可销售; 销售记录自动保存,便于查看历史。 接下来进行规范编码的四个步骤1.需求规格设计需求规格文档保存在 .codeartsdoer/specs/car_sales_mgmt/spec.md。核心要点:车辆管理:增删改查(品牌、型号、价格、库存),库存仅通过销售自动扣减,已关联订单的车辆禁止删除客户管理:增删改查(姓名、联系方式),联系方式11位手机号全局唯一,已关联订单的客户禁止删除销售管理:选择客户和车辆创建订单,状态单向流转(待确认→已确认→已完成),支持取消;售出自动扣减库存、取消自动回退库存;库存为0禁止销售DFX约束:页面响应≤2秒、接口响应≤1秒、数据一致性保障、敏感操作二次确认2.实现方案创建实现方案设计保存在 .codeartsdoer/specs/car_sales_mgmt/design.md。核心要点:技术架构:前后端分离,React + Ant Design(前端) / Node.js + Express(后端) / SQLite(数据库)后端三层架构:路由层 → 服务层 → DAO层订单状态机:待确认 → 已确认 → 已完成(单向流转),可从待确认/已确认 → 已取消核心流程:订单创建/取消均使用事务保证库存扣减/回退的原子性接口设计:16个RESTful API(车辆5个、客户5个、销售6个)数据模型:3个核心对象(Vehicle、Customer、Order),订单冗余存储客户/车辆关键信息确保历史可追溯    3.编码任务规划需求规格文档保存在 .codeartsdoer/specs/car_sales_mgmt/spec.md。核心要点:车辆管理:增删改查(品牌、型号、价格、库存),库存仅通过销售自动扣减,已关联订单的车辆禁止删除客户管理:增删改查(姓名、联系方式),联系方式11位手机号全局唯一,已关联订单的客户禁止删除销售管理:选择客户和车辆创建订单,状态单向流转(待确认→已确认→已完成),支持取消;售出自动扣减库存、取消自动回退库存;库存为0禁止销售DFX约束:页面响应≤2秒、接口响应≤1秒、数据一致性保障、敏感操作二次确认        4.任务执行spec-design-agent SubAgent: 汽车销售管理系统实现方案设计实现方案设计文档保存在 .codeartsdoer/specs/car_sales_mgmt/design.md。核心要点:技术架构:前后端分离,React + Ant Design(前端) / Node.js + Express(后端) / SQLite(数据库)后端三层架构:路由层 → 服务层 → DAO层订单状态机:待确认 → 已确认 → 已完成(单向流转),可从待确认/已确认 → 已取消核心流程:订单创建/取消均使用事务保证库存扣减/回退的原子性接口设计:16个RESTful API(车辆5个、客户5个、销售6个)数据模型:3个核心对象(Vehicle、Customer、Order),订单冗余存储客户/车辆关键信息确保历史可追溯是否需要修改文档?如无需修改,请告知进入下一阶段。spec-task-agent SubAgent: 汽车销售管理系统编码任务规划编码任务规划文档已生成,保存在 .codeartsdoer/specs/car_sales_mgmt/tasks.md。共 6个主任务、24个子任务:主任务子任务数覆盖需求1. 项目初始化与基础架构搭建5工程结构、后端框架、前端框架、数据库表2. 实现车辆管理功能4车辆CRUD、唯一性校验、删除保护、库存只读3. 实现客户管理功能4客户CRUD、唯一性校验、删除保护、手机号格式4. 实现销售管理功能4订单创建/状态流转/取消、库存扣减回退、历史快照5. 集成联调与功能验证3后端接口验证、前端页面验证、端到端业务流程6. 部署配置与收尾2启动脚本、最终验收任务结束,在内置浏览器上可以看到成品  三、关键代码实现汽车销售管理系统关键实现1、整体架构项目采用前后端分离架构。后端基于 Node.js + Express,遵循经典三层架构(路由层→服务层→数据访问层),数据库使用 SQLite(better-sqlite3 驱动)。前端基于 React + Vite + Ant Design,通过 Axios 调用后端 RESTful API。三层架构的核心价值在于职责分离:路由层只负责参数校验和请求分发,服务层承载业务逻辑,DAO 层只做数据持久化操作。2、数据库初始化与事务保障数据库初始化模块 server/db/init.js 负责建表和索引创建。三张核心表为 vehicles、customers、orders,其中订单表冗余存储了客户姓名、联系方式、车辆品牌、型号等快照字段,确保客户或车辆被删除后订单仍可展示历史信息。// server/db/init.jsdb.exec(`  CREATE TABLE IF NOT EXISTS orders (    id INTEGER PRIMARY KEY AUTOINCREMENT,    orderNo TEXT NOT NULL UNIQUE,    customerId INTEGER NOT NULL,    customerName TEXT NOT NULL,    customerPhone TEXT NOT NULL,    vehicleId INTEGER NOT NULL,    vehicleBrand TEXT NOT NULL,    vehicleModel TEXT NOT NULL,    amount REAL NOT NULL,    status TEXT NOT NULL DEFAULT 'PENDING',    createdAt TEXT NOT NULL DEFAULT (datetime('now', 'localtime')),    updatedAt TEXT NOT NULL DEFAULT (datetime('now', 'localtime'))  );`); 系统开启了 WAL 模式提升并发读性能,并启用外键约束。订单编号采用 ORD + YYYYMMDD + 4位顺序号 格式,在事务内生成以保证唯一性。3、订单创建——库存一致性的核心订单创建是系统最关键的流程,必须保证"订单创建"与"库存扣减"的原子性。实现上使用 better-sqlite3 的同步事务 API,采用 db.transaction() 包裹整个操作:// server/services/OrderService.js - createOrdercreateOrder({ customerId, vehicleId }) {  const customer = customerDAO.findById(customerId);  if (!customer) throw new BusinessError(404, '客户不存在', 404);  const vehicle = vehicleDAO.findById(vehicleId);  if (!vehicle) throw new BusinessError(404, '车辆不存在', 404);  const db = getDb();  const order = db.transaction(() => {    // 事务内重新查询库存,防止并发超卖    const v = db.prepare('SELECT * FROM vehicles WHERE id = ?').get(vehicleId);    if (v.stock <= 0) throw new BusinessError(422, '该车辆库存不足,无法销售');    const orderNo = orderDAO.generateOrderNo();    const newOrder = orderDAO.create({      orderNo, customerId: customer.id, customerName: customer.name,      customerPhone: customer.phone, vehicleId: vehicle.id,      vehicleBrand: vehicle.brand, vehicleModel: vehicle.model,      amount: vehicle.price, status: 'PENDING',    });    // 库存扣减通过 WHERE stock > 0 双重保障    const changes = vehicleDAO.decrementStock(vehicleId);    if (changes === 0) throw new BusinessError(422, '该车辆库存不足,无法销售');    return newOrder;  })();  return order;} 关键设计点:①事务内重新查询库存,避免事务外的脏读;②decrementStock 使用 WHERE stock > 0 作为乐观锁,即使并发请求也能保证不超卖;③订单编号生成在事务内完成,确保编号连续且唯一。4、订单状态机与取消回退订单状态流转采用状态机模式,通过 STATUS_FLOW 映射表定义合法流转路径: const STATUS_FLOW = {  PENDING: ['CONFIRMED', 'CANCELLED'],  CONFIRMED: ['COMPLETED', 'CANCELLED'],  COMPLETED: [],  CANCELLED: [],}; 状态更新时校验目标状态是否在允许列表中,非法流转返回 422 错误。取消订单时同样使用事务保证"状态变更"与"库存回退"的原子性:cancelOrder(id) {  const order = orderDAO.findById(id);  if (order.status === 'COMPLETED') throw new BusinessError(422, '已完成订单不可取消');  if (order.status === 'CANCELLED') throw new BusinessError(422, '订单已取消');  const db = getDb();  db.transaction(() => {    orderDAO.updateStatus(id, 'CANCELLED');    vehicleDAO.incrementStock(order.vehicleId);  })();  return orderDAO.findById(id);}5、删除保护与业务校验车辆和客户的删除都有关联订单保护。服务层在删除前查询 orders 表是否存在关联记录:// server/services/VehicleService.js - deleteVehicledeleteVehicle(id) {  const vehicle = vehicleDAO.findById(id);  if (!vehicle) throw new BusinessError(404, '车辆不存在', 404);  if (orderDAO.existsByVehicleId(id))    throw new BusinessError(409, '该车辆存在关联销售订单,无法删除');  vehicleDAO.deleteById(id);} 同理,库存字段不可通过编辑接口修改——路由层的 Joi 校验 schema 中 updateSchema 不包含 stock 字段,从接口层面杜绝了手动修改库存的可能。6、统一响应与错误处理后端通过 server/utils/response.js 封装了三种响应格式(成功、分页、错误),所有接口返回统一的 JSON 结构 { code, data, message }。错误处理中间件捕获 BusinessError(业务异常)和 Joi 校验错误,自动转换为标准响应格式:// server/middleware/errorHandler.jsfunction errorHandler(err, req, res, _next) {  if (err.isBusiness) {    return res.status(err.httpStatus || 400).json(resp.error(err.code, err.message));  }  if (err.isJoi) {    return res.status(400).json(resp.error(400, err.details.map(d => d.message).join('; ')));  }  res.status(500).json(resp.error(500, '服务器内部错误'));} 前端 Axios 拦截器统一处理响应,code !== 0 时自动弹出 message.error 提示,开发者无需在每个 API 调用处重复编写错误处理逻辑。7、前端管理布局与页面交互前端使用 Ant Design 的 Layout 组件实现侧边栏+内容区的后台管理布局,Sider 支持折叠,Menu 根据当前路由高亮。三个页面(车辆、客户、销售)均采用 Table + Modal 模式:列表页展示数据和分页,点击"新增/编辑"弹出 Modal 表单,删除使用 Popconfirm 二次确认。销售管理页面最为复杂,创建订单时通过下拉选择器加载客户和车辆列表,选择车辆后自动填充金额(只读),库存为0的车辆标注"库存不足"并禁用选择。订单状态标签通过颜色区分(橙色待确认、蓝色已确认、绿色已完成、灰色已取消),更新状态时调用 getNextStatuses 接口获取合法目标状态列表,仅展示可流转的选项。  四、成品展示我们在浏览器中打开:打开两个终端(命令行窗口)终端1 - 启动后端:cd D:\md2\demo6node server/app.js终端2 - 启动前端:cd D:\md2\demo6\clientnpx vite在浏览器地址栏输入 http://localhost:3000 回车即可  五、总结与体会(一)项目总结本次专业实习以华为云码道为开发平台,完成了汽车销售管理系统的完整开发流程。从需求分析、方案设计、任务规划到编码实现,系统性地实践了企业级Web应用的全生命周期开发方法。在技术层面,项目采用前后端分离架构,后端基于Node.js + Express构建三层架构(路由层→服务层→DAO层),前端使用React + Vite + Ant Design搭建响应式后台管理界面,SQLite作为数据存储引擎。通过16个RESTful API接口实现了车辆管理、客户管理、销售管理三大核心功能模块。在工程实践层面,本次开发严格遵循了规范化的软件开发流程。码道平台的需求规格设计、实现方案创建、编码任务规划和任务执行四个阶段,让我深刻体会到结构化开发方法论在实际项目中的价值。特别是在订单创建与库存扣减的原子性保障、订单状态机的流转控制、删除保护等关键业务场景中,通过事务机制、乐观锁、状态校验等手段确保了数据的一致性和系统的健壮性。(二)核心收获1. 系统设计能力的提升通过对汽车销售管理系统的完整建模,我掌握了从业务需求到技术实现的转化方法。三层架构的职责划分、接口契约的设计、数据库表结构的规划,都让我对软件工程中的“高内聚、低耦合”原则有了更直观的认识。特别是订单表中冗余存储客户和车辆快照字段的设计决策,理解了“以空间换时间”在确保历史数据可追溯性方面的重要意义。2. 数据一致性保障的工程实践订单创建与库存扣减的并发控制是本次开发中最具挑战性的环节。通过使用数据库事务包裹整个操作流程,配合WHERE stock > 0条件作为乐观锁,有效防止了超卖问题。这一实践让我深刻理解了在并发场景下,单纯依靠应用层逻辑是不够的,必须借助数据库层面的原子性保证才能实现真正的数据一致性。 3. 全栈开发的综合能力从后端的接口开发、数据库操作,到前端的组件构建、状态管理,再到前后端的联调测试,我完整地经历了一个全栈项目的开发闭环。对Axios拦截器的统一错误处理、Ant Design组件的灵活运用、Vite构建工具的开发体验,都极大地拓宽了我的技术视野。4. 规范开发流程的认知码道平台引导的四个开发阶段让我认识到,优秀的代码不仅仅是写出来的,更是设计出来的。需求规格文档明确了“做什么”,实现方案文档回答了“怎么做”,任务规划则把大目标拆解为可执行的子任务,这种“文档驱动开发”的模式有效降低了项目的返工率和不确定性。(三)存在的不足与改进方向1. 功能层面的局限当前系统仅支持单机部署,缺乏多用户角色与权限管理机制。在实际4S店场景中,销售顾问、库存管理员、财务人员等不同角色应有不同的操作权限和数据可见范围。未来可引入基于角色的访问控制(RBAC),实现更细粒度的权限管理。2. 技术栈的深化空间数据库层面:SQLite适用于轻量级场景,生产环境可迁移至PostgreSQL或MySQL,并引入ORM框架(如Prisma或TypeORM)提升数据访问层的可维护性。缓存与性能优化:车辆列表、客户列表等高频查询接口可引入Redis缓存,降低数据库压力,进一步提升响应速度。前端状态管理:随着业务复杂度增加,可引入Zustand或Redux Toolkit管理全局状态,替代组件间层层传递props的方式。测试体系:当前项目缺少自动化测试覆盖,后续可补充单元测试(Jest)、集成测试(Supertest)和端到端测试(Playwright),保障系统迭代质量。3. 部署与运维目前系统仅在开发环境运行,未来可容器化部署(Docker + Docker Compose),并配置CI/CD流水线实现自动化构建与发布。同时可接入日志收集与监控告警系统,提升系统的可观测性。(四)未来展望本次实习项目是我从课堂知识走向工程实践的重要桥梁。通过亲手构建一个功能完整的业务系统,我不仅巩固了数据结构、数据库原理、网络编程等理论基础,更积累了宝贵的项目经验。面向未来,我希望在以下方向持续深耕:深入后端架构:学习微服务架构、消息队列、分布式事务等进阶技术,提升大规模系统的设计能力;拓展前端视野:研究Next.js服务端渲染、WebAssembly等前沿技术,探索更优的Web应用交付方案关注云原生生态:结合华为云等云服务平台,学习函数计算、容器编排、Serverless等云上开发模式,为未来职业发展做好准备。最后,衷心感谢学院提供的实习机会,感谢华为云码道平台提供的开发环境与规范指导,也感谢指导老师在项目过程中给予的宝贵建议。本次实习不仅让我完成了一个可运行的软件系统,更重要的是建立了一套科学的工程化开发思维,这将使我终身受益。 
  • 汽车销售管理系统
    汽车销售管理系统仓库地址:汽车销售管理系统 - AtomGit一、题目选择与分析选择题目:汽车销售管理能够实现4S店的车辆种类、价格等进行管理,能够对客户进行管理,实现客户购买车辆的流程管理,费用结算等功能。分析该题目,需要实现的功能:1.车辆管理功能说明添加车辆录入品牌、型号、价格、库存数量删除车辆移除不再销售的车辆信息修改车辆更新车辆的品牌、型号、价格或库存查询车辆查看所有车辆列表,支持按品牌或型号搜索 2.客户管理功能说明添加客户录入客户姓名、联系方式删除客户移除客户信息修改客户更新客户姓名或联系方式查询客户查看所有客户列表 3.销售管理功能说明生成订单选择一个客户和一辆车,创建销售订单更新订单状态订单状态流转:下单 → 已完成自动扣减库存订单完成后,对应车辆的库存自动减1库存校验库存为0的车辆无法被选择下单销售记录所有订单自动保存,可查看历史销售列表            二、利用码道执行任务根据上面的功能需求,我们组织自然语言发送给码道:请帮助我构建一个汽车销售管理的Web应用,要求如下:在当前工作空间目录下创建项目,生成代码; 要求页面符合后台管理系统简洁、美观的风格; 车辆管理、客户管理、销售管理三项基本功能齐全; 具体功能包括: 车辆管理:车辆的增删改查(品牌、型号、价格、库存); 客户管理:客户信息的增删改查(姓名、联系方式); 销售管理:选择客户和车辆生成订单,更新订单状态; 车辆售出后自动扣减库存,库存为0时不可销售; 销售记录自动保存,便于查看历史。 接下来进行规范编码的四个步骤1.需求规格设计需求规格文档保存在 .codeartsdoer/specs/car_sales_mgmt/spec.md。核心要点:车辆管理:增删改查(品牌、型号、价格、库存),库存仅通过销售自动扣减,已关联订单的车辆禁止删除客户管理:增删改查(姓名、联系方式),联系方式11位手机号全局唯一,已关联订单的客户禁止删除销售管理:选择客户和车辆创建订单,状态单向流转(待确认→已确认→已完成),支持取消;售出自动扣减库存、取消自动回退库存;库存为0禁止销售DFX约束:页面响应≤2秒、接口响应≤1秒、数据一致性保障、敏感操作二次确认2.实现方案创建实现方案设计保存在 .codeartsdoer/specs/car_sales_mgmt/design.md。核心要点:技术架构:前后端分离,React + Ant Design(前端) / Node.js + Express(后端) / SQLite(数据库)后端三层架构:路由层 → 服务层 → DAO层订单状态机:待确认 → 已确认 → 已完成(单向流转),可从待确认/已确认 → 已取消核心流程:订单创建/取消均使用事务保证库存扣减/回退的原子性接口设计:16个RESTful API(车辆5个、客户5个、销售6个)数据模型:3个核心对象(Vehicle、Customer、Order),订单冗余存储客户/车辆关键信息确保历史可追溯    3.编码任务规划需求规格文档保存在 .codeartsdoer/specs/car_sales_mgmt/spec.md。核心要点:车辆管理:增删改查(品牌、型号、价格、库存),库存仅通过销售自动扣减,已关联订单的车辆禁止删除客户管理:增删改查(姓名、联系方式),联系方式11位手机号全局唯一,已关联订单的客户禁止删除销售管理:选择客户和车辆创建订单,状态单向流转(待确认→已确认→已完成),支持取消;售出自动扣减库存、取消自动回退库存;库存为0禁止销售DFX约束:页面响应≤2秒、接口响应≤1秒、数据一致性保障、敏感操作二次确认        4.任务执行spec-design-agent SubAgent: 汽车销售管理系统实现方案设计实现方案设计文档保存在 .codeartsdoer/specs/car_sales_mgmt/design.md。核心要点:技术架构:前后端分离,React + Ant Design(前端) / Node.js + Express(后端) / SQLite(数据库)后端三层架构:路由层 → 服务层 → DAO层订单状态机:待确认 → 已确认 → 已完成(单向流转),可从待确认/已确认 → 已取消核心流程:订单创建/取消均使用事务保证库存扣减/回退的原子性接口设计:16个RESTful API(车辆5个、客户5个、销售6个)数据模型:3个核心对象(Vehicle、Customer、Order),订单冗余存储客户/车辆关键信息确保历史可追溯是否需要修改文档?如无需修改,请告知进入下一阶段。spec-task-agent SubAgent: 汽车销售管理系统编码任务规划编码任务规划文档已生成,保存在 .codeartsdoer/specs/car_sales_mgmt/tasks.md。共 6个主任务、24个子任务:主任务子任务数覆盖需求1. 项目初始化与基础架构搭建5工程结构、后端框架、前端框架、数据库表2. 实现车辆管理功能4车辆CRUD、唯一性校验、删除保护、库存只读3. 实现客户管理功能4客户CRUD、唯一性校验、删除保护、手机号格式4. 实现销售管理功能4订单创建/状态流转/取消、库存扣减回退、历史快照5. 集成联调与功能验证3后端接口验证、前端页面验证、端到端业务流程6. 部署配置与收尾2启动脚本、最终验收任务结束,在内置浏览器上可以看到成品  三、关键代码实现汽车销售管理系统关键实现1、整体架构项目采用前后端分离架构。后端基于 Node.js + Express,遵循经典三层架构(路由层→服务层→数据访问层),数据库使用 SQLite(better-sqlite3 驱动)。前端基于 React + Vite + Ant Design,通过 Axios 调用后端 RESTful API。三层架构的核心价值在于职责分离:路由层只负责参数校验和请求分发,服务层承载业务逻辑,DAO 层只做数据持久化操作。2、数据库初始化与事务保障数据库初始化模块 server/db/init.js 负责建表和索引创建。三张核心表为 vehicles、customers、orders,其中订单表冗余存储了客户姓名、联系方式、车辆品牌、型号等快照字段,确保客户或车辆被删除后订单仍可展示历史信息。// server/db/init.jsdb.exec(`  CREATE TABLE IF NOT EXISTS orders (    id INTEGER PRIMARY KEY AUTOINCREMENT,    orderNo TEXT NOT NULL UNIQUE,    customerId INTEGER NOT NULL,    customerName TEXT NOT NULL,    customerPhone TEXT NOT NULL,    vehicleId INTEGER NOT NULL,    vehicleBrand TEXT NOT NULL,    vehicleModel TEXT NOT NULL,    amount REAL NOT NULL,    status TEXT NOT NULL DEFAULT 'PENDING',    createdAt TEXT NOT NULL DEFAULT (datetime('now', 'localtime')),    updatedAt TEXT NOT NULL DEFAULT (datetime('now', 'localtime'))  );`); 系统开启了 WAL 模式提升并发读性能,并启用外键约束。订单编号采用 ORD + YYYYMMDD + 4位顺序号 格式,在事务内生成以保证唯一性。3、订单创建——库存一致性的核心订单创建是系统最关键的流程,必须保证"订单创建"与"库存扣减"的原子性。实现上使用 better-sqlite3 的同步事务 API,采用 db.transaction() 包裹整个操作:// server/services/OrderService.js - createOrdercreateOrder({ customerId, vehicleId }) {  const customer = customerDAO.findById(customerId);  if (!customer) throw new BusinessError(404, '客户不存在', 404);  const vehicle = vehicleDAO.findById(vehicleId);  if (!vehicle) throw new BusinessError(404, '车辆不存在', 404);  const db = getDb();  const order = db.transaction(() => {    // 事务内重新查询库存,防止并发超卖    const v = db.prepare('SELECT * FROM vehicles WHERE id = ?').get(vehicleId);    if (v.stock <= 0) throw new BusinessError(422, '该车辆库存不足,无法销售');    const orderNo = orderDAO.generateOrderNo();    const newOrder = orderDAO.create({      orderNo, customerId: customer.id, customerName: customer.name,      customerPhone: customer.phone, vehicleId: vehicle.id,      vehicleBrand: vehicle.brand, vehicleModel: vehicle.model,      amount: vehicle.price, status: 'PENDING',    });    // 库存扣减通过 WHERE stock > 0 双重保障    const changes = vehicleDAO.decrementStock(vehicleId);    if (changes === 0) throw new BusinessError(422, '该车辆库存不足,无法销售');    return newOrder;  })();  return order;} 关键设计点:①事务内重新查询库存,避免事务外的脏读;②decrementStock 使用 WHERE stock > 0 作为乐观锁,即使并发请求也能保证不超卖;③订单编号生成在事务内完成,确保编号连续且唯一。4、订单状态机与取消回退订单状态流转采用状态机模式,通过 STATUS_FLOW 映射表定义合法流转路径: const STATUS_FLOW = {  PENDING: ['CONFIRMED', 'CANCELLED'],  CONFIRMED: ['COMPLETED', 'CANCELLED'],  COMPLETED: [],  CANCELLED: [],}; 状态更新时校验目标状态是否在允许列表中,非法流转返回 422 错误。取消订单时同样使用事务保证"状态变更"与"库存回退"的原子性:cancelOrder(id) {  const order = orderDAO.findById(id);  if (order.status === 'COMPLETED') throw new BusinessError(422, '已完成订单不可取消');  if (order.status === 'CANCELLED') throw new BusinessError(422, '订单已取消');  const db = getDb();  db.transaction(() => {    orderDAO.updateStatus(id, 'CANCELLED');    vehicleDAO.incrementStock(order.vehicleId);  })();  return orderDAO.findById(id);}5、删除保护与业务校验车辆和客户的删除都有关联订单保护。服务层在删除前查询 orders 表是否存在关联记录:// server/services/VehicleService.js - deleteVehicledeleteVehicle(id) {  const vehicle = vehicleDAO.findById(id);  if (!vehicle) throw new BusinessError(404, '车辆不存在', 404);  if (orderDAO.existsByVehicleId(id))    throw new BusinessError(409, '该车辆存在关联销售订单,无法删除');  vehicleDAO.deleteById(id);} 同理,库存字段不可通过编辑接口修改——路由层的 Joi 校验 schema 中 updateSchema 不包含 stock 字段,从接口层面杜绝了手动修改库存的可能。6、统一响应与错误处理后端通过 server/utils/response.js 封装了三种响应格式(成功、分页、错误),所有接口返回统一的 JSON 结构 { code, data, message }。错误处理中间件捕获 BusinessError(业务异常)和 Joi 校验错误,自动转换为标准响应格式:// server/middleware/errorHandler.jsfunction errorHandler(err, req, res, _next) {  if (err.isBusiness) {    return res.status(err.httpStatus || 400).json(resp.error(err.code, err.message));  }  if (err.isJoi) {    return res.status(400).json(resp.error(400, err.details.map(d => d.message).join('; ')));  }  res.status(500).json(resp.error(500, '服务器内部错误'));} 前端 Axios 拦截器统一处理响应,code !== 0 时自动弹出 message.error 提示,开发者无需在每个 API 调用处重复编写错误处理逻辑。7、前端管理布局与页面交互前端使用 Ant Design 的 Layout 组件实现侧边栏+内容区的后台管理布局,Sider 支持折叠,Menu 根据当前路由高亮。三个页面(车辆、客户、销售)均采用 Table + Modal 模式:列表页展示数据和分页,点击"新增/编辑"弹出 Modal 表单,删除使用 Popconfirm 二次确认。销售管理页面最为复杂,创建订单时通过下拉选择器加载客户和车辆列表,选择车辆后自动填充金额(只读),库存为0的车辆标注"库存不足"并禁用选择。订单状态标签通过颜色区分(橙色待确认、蓝色已确认、绿色已完成、灰色已取消),更新状态时调用 getNextStatuses 接口获取合法目标状态列表,仅展示可流转的选项。  四、成品展示我们在浏览器中打开:打开两个终端(命令行窗口)终端1 - 启动后端:cd D:\md2\demo6node server/app.js终端2 - 启动前端:cd D:\md2\demo6\clientnpx vite在浏览器地址栏输入 http://localhost:3000 回车即可 五、总结与体会(一)项目总结本次专业实习以华为云码道为开发平台,完成了汽车销售管理系统的完整开发流程。从需求分析、方案设计、任务规划到编码实现,系统性地实践了企业级Web应用的全生命周期开发方法。在技术层面,项目采用前后端分离架构,后端基于Node.js + Express构建三层架构(路由层→服务层→DAO层),前端使用React + Vite + Ant Design搭建响应式后台管理界面,SQLite作为数据存储引擎。通过16个RESTful API接口实现了车辆管理、客户管理、销售管理三大核心功能模块。在工程实践层面,本次开发严格遵循了规范化的软件开发流程。码道平台的需求规格设计、实现方案创建、编码任务规划和任务执行四个阶段,让我深刻体会到结构化开发方法论在实际项目中的价值。特别是在订单创建与库存扣减的原子性保障、订单状态机的流转控制、删除保护等关键业务场景中,通过事务机制、乐观锁、状态校验等手段确保了数据的一致性和系统的健壮性。(二)核心收获1. 系统设计能力的提升通过对汽车销售管理系统的完整建模,我掌握了从业务需求到技术实现的转化方法。三层架构的职责划分、接口契约的设计、数据库表结构的规划,都让我对软件工程中的“高内聚、低耦合”原则有了更直观的认识。特别是订单表中冗余存储客户和车辆快照字段的设计决策,理解了“以空间换时间”在确保历史数据可追溯性方面的重要意义。2. 数据一致性保障的工程实践订单创建与库存扣减的并发控制是本次开发中最具挑战性的环节。通过使用数据库事务包裹整个操作流程,配合WHERE stock > 0条件作为乐观锁,有效防止了超卖问题。这一实践让我深刻理解了在并发场景下,单纯依靠应用层逻辑是不够的,必须借助数据库层面的原子性保证才能实现真正的数据一致性。 3. 全栈开发的综合能力从后端的接口开发、数据库操作,到前端的组件构建、状态管理,再到前后端的联调测试,我完整地经历了一个全栈项目的开发闭环。对Axios拦截器的统一错误处理、Ant Design组件的灵活运用、Vite构建工具的开发体验,都极大地拓宽了我的技术视野。4. 规范开发流程的认知码道平台引导的四个开发阶段让我认识到,优秀的代码不仅仅是写出来的,更是设计出来的。需求规格文档明确了“做什么”,实现方案文档回答了“怎么做”,任务规划则把大目标拆解为可执行的子任务,这种“文档驱动开发”的模式有效降低了项目的返工率和不确定性。(三)存在的不足与改进方向1. 功能层面的局限当前系统仅支持单机部署,缺乏多用户角色与权限管理机制。在实际4S店场景中,销售顾问、库存管理员、财务人员等不同角色应有不同的操作权限和数据可见范围。未来可引入基于角色的访问控制(RBAC),实现更细粒度的权限管理。2. 技术栈的深化空间数据库层面:SQLite适用于轻量级场景,生产环境可迁移至PostgreSQL或MySQL,并引入ORM框架(如Prisma或TypeORM)提升数据访问层的可维护性。缓存与性能优化:车辆列表、客户列表等高频查询接口可引入Redis缓存,降低数据库压力,进一步提升响应速度。前端状态管理:随着业务复杂度增加,可引入Zustand或Redux Toolkit管理全局状态,替代组件间层层传递props的方式。测试体系:当前项目缺少自动化测试覆盖,后续可补充单元测试(Jest)、集成测试(Supertest)和端到端测试(Playwright),保障系统迭代质量。3. 部署与运维目前系统仅在开发环境运行,未来可容器化部署(Docker + Docker Compose),并配置CI/CD流水线实现自动化构建与发布。同时可接入日志收集与监控告警系统,提升系统的可观测性。(四)未来展望本次实习项目是我从课堂知识走向工程实践的重要桥梁。通过亲手构建一个功能完整的业务系统,我不仅巩固了数据结构、数据库原理、网络编程等理论基础,更积累了宝贵的项目经验。面向未来,我希望在以下方向持续深耕:深入后端架构:学习微服务架构、消息队列、分布式事务等进阶技术,提升大规模系统的设计能力;拓展前端视野:研究Next.js服务端渲染、WebAssembly等前沿技术,探索更优的Web应用交付方案关注云原生生态:结合华为云等云服务平台,学习函数计算、容器编排、Serverless等云上开发模式,为未来职业发展做好准备。最后,衷心感谢学院提供的实习机会,感谢华为云码道平台提供的开发环境与规范指导,也感谢指导老师在项目过程中给予的宝贵建议。本次实习不仅让我完成了一个可运行的软件系统,更重要的是建立了一套科学的工程化开发思维,这将使我终身受益。 
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体的幼儿园管理系统开发与 ECS 部署
    基于华为云码道(CodeArts)代码智能体的幼儿园管理系统开发与 ECS 部署一、概述1.1 案例介绍本案例使用华为云码道(CodeArts)代码智能体,完成一个幼儿园管理系统的需求分析、方案设计、编码、测试和华为云 ECS 部署。系统面向幼儿园日常管理场景,实现了儿童学籍、班级、兴趣课程、食谱和调班记录管理,并提供“按班级查询儿童”和“按儿童查询班级及课程”两种查询方式。演示地址:http://121.36.40.212/演示环境中的儿童姓名、监护人和电话均为自动生成的测试数据,不包含真实儿童信息。管理账号和服务器密码不公开。1.2 核心业务要求幼儿园设大班、中班、小班三个年级;每个年级包含 3 个班,共 9 个班;每班包含 10 名儿童,共 90 名儿童;每名儿童学习舞蹈、跆拳道、钢琴、美术 4 门兴趣课程;支持儿童学籍、班级、课程和每日食谱管理;支持儿童调班,并保留可追溯的调班记录;支持根据班级查找儿童;支持根据儿童查找所在班级和所学课程。1.3 案例流程使用华为云码道梳理需求并生成解决方案;完成 Django 数据模型和 RESTful API;完成 Bootstrap 单页管理界面;初始化 3 个年级、9 个班级、90 名儿童和 4 门课程;编写自动化测试并修复课程数量、班级容量和调班一致性问题;购买华为云 ECS,完成系统部署;通过公网地址和健康检查验证部署结果。1.4 资源总览资源实际配置用途华为云码道(CodeArts)代码智能体训练营开发环境需求、设计、编码和问题修复弹性云服务器 ECS华北-北京四,1 vCPU、1 GiB运行 Django 应用操作系统Ubuntu 24.04 Server 64 位服务器运行环境云硬盘 EVS通用型 SSD,40 GiB系统与应用数据弹性公网 IP5 Mbit/s公网访问VPC 与安全组kindergarten-web网络隔离及端口访问控制费用采用按需计费,实际价格以华为云控制台为准。二、系统设计2.1 技术栈层次技术说明后端Python、Django 5.2ORM、业务 API 和管理后台前端Bootstrap 5、原生 JavaScript无需额外构建的单页管理界面数据库SQLite适合训练营单机演示,可切换 PostgreSQLWeb 服务Gunicorn生产环境 WSGI 服务静态文件WhiteNoiseDjango 生产环境静态文件服务进程管理systemd开机自启、异常重启和日志管理云资源华为云 ECS、EVS、EIP、VPC、安全组应用部署及公网访问2.2 部署架构2.3 核心数据模型系统包含 6 个核心模型:模型作用主要关系Grade大班、中班、小班年级信息一个年级包含多个班级Klass班级、班号和容量一个班级包含多名儿童Child儿童学籍及监护人信息属于一个班级,与课程多对多关联Course兴趣课程和课程容量与儿童多对多关联Recipe日期、餐次、菜名、食材和营养说明同日同餐次可管理不同菜品ClassTransferLog儿童调班历史记录原班级、新班级、原因和时间三、使用华为云码道辅助开发本项目按照规范驱动开发思路推进:需求描述 → 需求规格设计(spec) → 实现方案设计(design) → 编码任务规划(tasks) → 任务执行与测试 → 部署方案设计初始需求输入后,代码智能体将业务拆分为学籍、班级、课程、食谱、调班和综合查询等模块,并生成数据模型、接口设计、项目结构及实施任务。在开发过程中,码道还辅助完成了以下修复:将课程规则明确为“恰好选择 4 门不同的兴趣课程”;新增班级容量校验,班级达到 10 人后禁止继续加入;使用数据库事务保护调班操作;增加调班日志,保证操作可追溯;增加生产环境配置、Gunicorn、WhiteNoise 和健康检查;增加覆盖关键业务规则的自动化测试。四、系统功能展示4.1 首页概览首页显示在园儿童、班级、兴趣课程和年级数量。初始化完成后共有 90 名儿童、9 个班级、4 门兴趣课程和 3 个年级,每个年级均为 3 个班、30 名儿童。4.2 儿童学籍管理儿童学籍页面展示姓名、性别、出生日期、所在班级、兴趣课程和在园状态,并支持搜索、按年级筛选、新增、编辑和删除。新增儿童时需要录入监护人和班级信息,并且必须选择 4 门不同的兴趣课程。前端与后端都会校验该规则。4.3 班级管理系统初始化大班、中班、小班各 3 个班。班级列表实时显示容量、当前人数和是否已满,避免超额分班。4.4 课程管理系统提供舞蹈、跆拳道、钢琴、美术 4 门兴趣课程。每门课程可查看课程说明、容量和已选人数。4.5 食谱管理食谱按照日期和餐次管理,记录菜名、主要食材和营养说明,可按日期筛选。4.6 调班管理调班页面可选择儿童、查看当前班级、选择目标班级并填写调班原因。后端会锁定相关数据、检查目标班级容量,并在成功后生成调班记录。4.7 综合查询综合查询同时支持两种业务场景:选择班级后,显示本班全部儿童及其兴趣课程;选择儿童后,显示儿童基本信息、所在班级和所学课程。五、关键实现5.1 四门兴趣课程约束后端要求课程 ID 数量必须为 4,并且不能重复:def _validate_four_courses(course_ids): """每个儿童必须选择四门互不重复的兴趣课程。""" return len(course_ids) == 4 and len(set(course_ids)) == 4 创建或修改儿童时,如果不满足规则,API 返回 400,防止仅依赖前端校验而产生不一致数据。5.2 班级容量控制新增儿童和调班都会检查目标班级当前在园人数:def _klass_has_space(klass_id, *, exclude_child_id=None): students = Child.objects.filter(klass_id=klass_id, is_active=True) if exclude_child_id: students = students.exclude(pk=exclude_child_id) klass = Klass.objects.get(pk=klass_id) return students.count() < klass.max_students5.3 调班事务与日志调班操作使用 transaction.atomic(),同时通过 select_for_update() 锁定儿童和目标班级。只有容量校验通过后才记录日志并更新儿童班级:with transaction.atomic(): child = Child.objects.select_for_update().select_related('klass').get(pk=child_id) to_klass = Klass.objects.select_for_update().get(pk=to_klass_id) if not _klass_has_space(to_klass.id, exclude_child_id=child.id): return error('目标班级已满,无法调入') ClassTransferLog.objects.create( child=child, from_klass=child.klass, to_klass=to_klass, reason=reason, ) child.klass = to_klass child.save() 5.4 查询优化查询儿童信息时使用 select_related 和 prefetch_related 一次加载班级、年级和课程,减少重复数据库访问:children = Child.objects.select_related( 'klass', 'klass__grade' ).prefetch_related('courses') 六、自动化测试项目包含 6 项自动化测试,覆盖:每名儿童必须选择 4 门不同课程;满员班级拒绝新增儿童;调班成功后生成日志;满员目标班级拒绝调班;按班级、按儿童查询结果正确;初始化命令可重复执行,并始终生成 3 个年级、9 个班、90 名儿童和 4 门课程;公网健康检查返回正常状态。执行结果:Found 6 test(s). Ran 6 tests in 0.126s OK System check identified no issues (0 silenced).七、部署至华为云 ECS7.1 云服务器配置本项目部署在华北-北京四区域,实例名为 kindergarten-demo,使用 Ubuntu 24.04 Server、1 vCPU、1 GiB 内存、40 GiB 系统盘和 5 Mbit/s 公网带宽。7.2 上传并准备运行环境应用上传至 /opt/kindergarten/app,并在服务器创建独立 Python 虚拟环境:apt-get update apt-get install -y python3-venv python3 -m venv /opt/kindergarten/venv /opt/kindergarten/venv/bin/pip install \ -i https://pypi.tuna.tsinghua.edu.cn/simple \ -r /opt/kindergarten/app/requirements.txt7.3 初始化生产环境生产环境将随机生成的 DJANGO_SECRET_KEY、允许访问的主机和数据库路径保存在权限为 600 的 /etc/kindergarten.env 中,不写入源码。set -a . /etc/kindergarten.env set +a cd /opt/kindergarten/app /opt/kindergarten/venv/bin/python manage.py collectstatic --noinput /opt/kindergarten/venv/bin/python manage.py migrate --noinput /opt/kindergarten/venv/bin/python manage.py init_data7.4 systemd 服务Gunicorn 由 systemd 管理,以 www-data 用户运行,并配置开机自启和异常自动重启:[Service] User=www-data Group=www-data WorkingDirectory=/opt/kindergarten/app EnvironmentFile=/etc/kindergarten.env ExecStart=/opt/kindergarten/venv/bin/gunicorn \ kindergarten.wsgi:application \ --bind 0.0.0.0:80 \ --workers 2 \ --timeout 120 Restart=always RestartSec=3 启动服务:systemctl daemon-reload systemctl enable --now kindergarten systemctl status kindergarten --no-pager7.5 部署验证公网首页请求返回 HTTP 200,响应服务器为 Gunicorn。健康检查结果如下:GET http://121.36.40.212/health/ {"status":"ok"}八、部署问题与解决方案8.1 Docker Hub 基础镜像下载超时最初计划使用 Docker 部署,但 ECS 拉取 python:3.12-slim 时访问 Docker Hub 超时:failed to resolve reference "docker.io/library/python:3.12-slim" dial tcp ...:443: i/o timeout项目源码和部署文件均未受影响。考虑到训练营演示环境只有 1 GiB 内存,最终改用:主机 Python + venv + Gunicorn + systemd + SQLite这种方案依赖更少、资源占用较低,同时具备开机自启和异常恢复能力。项目仍保留 Dockerfile 和 Kubernetes 部署清单,后续可以将基础镜像同步到华为云 SWR 后恢复容器化部署。8.2 生产环境安全配置部署时进行了以下处理:DEBUG=False;SECRET_KEY 仅保存在服务器环境变量文件中;使用 ALLOWED_HOSTS 限制请求主机;使用 WhiteNoise 提供静态文件;Gunicorn 以非 root 用户运行;安全组开放 Web 访问端口,SSH 仅用于服务器管理;/health/ 只返回服务状态,不暴露业务数据;管理员密码不写入源码和帖子。九、总结通过华为云码道(CodeArts)代码智能体,本项目完成了从自然语言需求到可部署系统的完整闭环:业务需求被拆分为清晰的数据模型和 API;核心规则在前后端和自动化测试中得到多重保障;90 名儿童、9 个班级和 4 门课程的数据能够正确初始化;学籍、食谱、课程、调班和双向查询均可在统一界面中完成;系统已经部署到华为云 ECS,并通过公网访问和健康检查验证。本案例不仅展示了 AI 辅助编码,也记录了测试、部署失败恢复和生产配置过程。对于高校课程设计和中小型管理系统,华为云码道可以显著缩短从需求到上线的路径。
总条数:617 到第
上滑加载中