ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于鸿蒙ArkTS的类小红书App毕设实战指南

基于鸿蒙ArkTS的类小红书App毕设实战指南 毕业设计如果继续做“XX管理系统”大概率会在开题答辩时和七八个同学撞车。相比之下以鸿蒙系统为平台、用 ArkTS 做原生开发的类小红书 App从技术栈到产品形态都有足够区分度而且它不是只做一个 demo 界面而是把社交笔记、电商商城和 Web 后台串成一条完整业务链路。这类课题既能体现对新型平台的掌握也能覆盖状态管理、网络请求、权限申请、数据持久化、接口设计和后台管理等常见工程能力非常适合作为毕设选题也可以作为简历上的完整项目。这篇文章按一个可落地的毕设项目来拆解先讲为什么选这个题、整体架构和技术栈怎么定再给数据模型和接口约定然后分别说明笔记信息流、商城模块、Web 后台的实现思路最后补充真机调试排错路径、答辩演示路径和常见坑。文中代码用于说明工程思路实际开发时要以你本地的 DevEco Studio 版本和 API 版本为准不要照抄后不做版本验证。1. 为什么这个选题值得做从撞车选题里找区分度1.1 毕设选题撞车的原因与破局思路毕业设计撞车最多的通常是“图书管理系统”“学生选课系统”“企业员工管理”这类题目。撞车的原因很简单技术栈固定、参考案例多、实现路径成熟。大家用同一个框架、同一套 CRUD最后交上去的验收点高度相似甚至答辩时被问的问题都一样。破局思路不是把界面做得更花哨而是换一个有平台属性的方向。鸿蒙系统是一个仍在快速迭代的操作系统ArkTS 作为其应用开发的推荐语言还没有被大量毕设项目覆盖。当别人还在写 Web 管理系统时你手里是一个运行在真机或模拟器上的原生 App带双列瀑布流、点赞收藏、购物车、下单流程和后台管理这种完整度更容易在开题、中期和答辩时讲出东西。这里要区分一个概念鸿蒙系统并不只是“手机上的系统”。从通俗角度看它面向手机、平板、车机、智慧屏等多设备协同场景从技术角度看应用层通过 ArkUI 声明式框架和 ArkTS 语言开发底层系统负责调度、安全和分布式能力。毕设层面不需要讲得很底层但理解这一点能帮助你在答辩时解释“为什么不用 WebView 套壳而要选原生开发”。1.2 ArkTS 原生开发在毕设中的优势ArkTS 是在 TypeScript 基础上扩展出的声明式 UI 开发语言。它和传统命令式写界面的方式不同开发者描述“界面应该长什么样”框架负责在状态变化时更新界面。这个思路与 React、Vue 有相似之处但 ArkTS 直接跑在鸿蒙应用框架上能调用相机、相册、网络、权限管理等系统能力。用 ArkTS 做原生开发毕设里有三个实际收益权限申请、相机调用、相册选择这些能力可以作为独立功能点答辩时容易展示系统级集成能力。声明式 UI 的代码量相对少页面结构和状态变化更直观适合在有限时间内完成。技术资料正在快速积累但还远没有 JavaWeb 那么泛滥写出来的项目有稀缺性。需要注意ArkTS 对类型约束比普通 JavaScript 严格组件状态管理也有自己的规则。不要直接用写“自由脚本”的习惯去写 ArkTS否则运行起来会遇到类型报错和状态不刷新问题。1.3 课题拆解社交笔记、电商商城、Web 后台三个模块的边界这个题目可以拆成三个边界清晰的模块用户端 App包含登录注册、首页双列笔记流、笔记详情、发布笔记、点赞收藏、商品列表、商品详情、购物车、订单提交、个人中心。服务端接口为 App 和 Web 后台提供 RESTful API处理用户、笔记、商品、订单、评论、点赞等数据。Web 后台管理员登录后可以查看数据看板、管理用户、审核笔记、上下架商品、处理订单。毕设的工作量主要落在 App 端。如果时间有限可以砍掉评论、搜索、支付对接等非核心功能用一个“模拟支付成功”来代替真实支付。后端接口数量控制在 20 个左右就能支撑整个演示流程不要一开始就把表设计得过于复杂。2. 项目整体架构与技术选型先画清楚模块边界2.1 客户端、服务端、Web 后台三层结构项目建议采用前后端分离结构分三部分HarmonyOS App 客户端负责用户交互通过 HTTP 请求访问服务端接口。服务端负责业务逻辑、鉴权、数据校验和数据库读写同时给 Web 后台提供接口。Web 后台一个单独的管理端项目只允许管理员登录提供内容审核和运营管理功能。数据流链路大致是App 发起登录请求服务端校验后返回 tokenApp 携带 token 获取笔记或商品列表用户发布笔记服务端写入待审核状态管理员在后台审核通过用户端才能看到笔记上线。这种三层结构的好处是职责分离。App 端可以不关心 SQL 和业务规则后台管理可以随时补充业务功能而不需要重新发版 App。答辩时也能清楚说明这是一个“完整的前后端协作项目”而不是单页面 Demo。2.2 服务端与数据库选型服务端技术栈可以根据你熟悉的方向选择。最常用的两组方案技术栈优点适合场景Java Spring Boot MySQL资料多企业微服务常用代码结构规范熟悉 Java 或后续想找 Java 后端岗位Node.js Express/Nest MySQL语言与前端一致开发迭代快熟悉 TypeScript 或希望整体一套语言Python Flask/FastAPI MySQL代码轻量适合快速原型想快速跑通但需要后期补齐工程化能力数据库层建议统一用 MySQL。毕设环境下表结构可控MySQL 的 SQL 资料也多排错成本低。如果你的电脑没有安装 MySQL也可以先用 SQLite 或 H2 数据库开发最后再迁移到 MySQL但要注意 SQL 方言差异。2.3 核心业务链路需要提前梳理在写代码之前先用文字把核心链路理清楚后面就不会乱用户注册登录注册时保存用户名和密码哈希登录成功后服务端返回 tokenApp 后续请求在 Header 中携带。笔记发布与审核用户填写标题、内容、分类并选择图片发布后状态为待审核后台审核通过后笔记在用户端可见。商品与订单用户浏览商品并加入购物车确认后提交订单服务端生成订单号状态为待支付模拟支付成功后状态变为已支付后台可以进行发货操作。后台管理管理员登录后看到统计数字对用户、笔记、商品、订单进行管理操作。这些链路是后面设计数据库表结构的基础。先想清楚链路再建表不要一边写界面一边临时改表。3. 环境准备与工程创建先跑起来再写业务3.1 DevEco Studio、SDK 和 API 版本要对齐HarmonyOS 应用开发的主力 IDE 是 DevEco Studio安装后需要下载 HarmonyOS SDK。SDK 版本会直接影响 ArkTS 语法、组件能力和权限 API所以开始项目前先确认三件事DevEco Studio 安装完成且登录账号环境正常。SDK 已下载且与工程目标 API 版本一致。有可用的模拟器或真机。如果使用真机要在设备上开启开发者模式并允许 USB 调试。API 版本是一个容易踩坑的地方。不同 API 版本中权限申请接口、路由跳转方式、WaterFlow 等新组件的支持程度不同。教程中经常看到的一些写法可能来自不同版本遇到 API 不存在或编译报错时优先在官方 API 文档中确认当前版本签名。如果实在没有真机可以用模拟器完成大部分功能演示但相机、相册、定位等系统能力在模拟器上的体验会受限。毕设演示时能准备一台鸿蒙真机效果更好。3.2 创建 ArkTS 工程并理解目录结构在 DevEco Studio 中选择“Empty Ability”模板创建工程。一个典型工程的目录结构大致如下HarmonyNotesDemo/ ├── AppScope/ │ ├── app.json5 │ └── resources/ ├── entry/ │ ├── src/main/ │ │ ├── ets/ │ │ │ ├── entryability/ │ │ │ ├── pages/ │ │ │ │ ├── Index.ets │ │ │ │ ├── NoteDetailPage.ets │ │ │ │ ├── PublishNotePage.ets │ │ │ │ ├── ProductListPage.ets │ │ │ │ ├── CartPage.ets │ │ │ │ └── MinePage.ets │ │ │ ├── model/ │ │ │ └── service/ │ │ ├── resources/ │ │ └── module.json5 │ └── build-profile.json5 └── build-profile.json5module.json5是模块配置文件里面注册 Ability、声明权限、配置页面入口。pages目录存放页面组件。model目录建议放数据模型和接口返回类型定义service目录放网络请求封装和工具方法。不要在页面文件里写大量逻辑否则后期维护会很痛苦。创建完工程后先运行一次默认 Hello World确认开发环境可以编译、安装、启动。这一步能提前暴露 SDK、签名、模拟器连接等问题不要在还没跑通基础工程时就开始写业务代码。3.3 权限申请从热门问题“arkts 权限申请”说起权限申请是鸿蒙开发中很容易忽略的环节。应用访问网络、相机、相册等能力需要先在module.json5中声明权限然后在代码中请求动态权限。基础网络权限配置如下{ module: { name: entry, requestPermissions: [ { name: ohos.permission.INTERNET }, { name: ohos.permission.CAMERA }, { name: ohos.permission.READ_IMAGEVIDEO }, { name: ohos.permission.WRITE_IMAGEVIDEO } ] } }查询用户相册、访问网络、调用相机都属于需要“解释用途”的敏感权限。即使声明了权限部分系统能力仍需要在运行时弹窗申请。常用的动态权限申请代码思路如下import { abilityAccessCtrl, Permissions } from kit.AbilityKit; async function requestPermission(permission: Permissions) { const atManager abilityAccessCtrl.createAtManager(); try { const result await atManager.requestPermissionsFromUser(permission); if (result.authResults.length 0 result.authResults[0] 0) { console.info(permission granted); } else { console.error(permission denied); } } catch (err) { console.error(request permission error: JSON.stringify(err)); } }这里要特别提醒不同 API 版本中requestPermissionsFromUser入参类型不一样有的版本接受数组有的版本接受单个权限对象还有的版本要求传入context。写代码前必须以当前工程依赖的 API 版本为准不能直接复制网上任意一段代码。权限申请常见的坑是只做了声明、没有动态请求或者声明了权限但用户拒绝后没有处理。正确做法是在进入需要权限的功能前检查授权状态未授权时弹窗说明用途并请求用户拒绝后界面要给出引导或降级处理不能直接崩溃。4. 数据库模型设计先定义业务的数据基础4.1 用户、笔记、商品、订单四张核心表数据库表设计不用太多但要能支撑完整业务链路。核心表先建四张用户表、笔记表、商品表、订单表。CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, nickname VARCHAR(50), avatar_url VARCHAR(255), role TINYINT DEFAULT 0 COMMENT 0普通用户 1管理员, status TINYINT DEFAULT 1 COMMENT 1正常 0禁用, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE note ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, title VARCHAR(100), content TEXT, cover_url VARCHAR(255), category VARCHAR(30), like_count INT DEFAULT 0, status TINYINT DEFAULT 0 COMMENT 0待审核 1已上线 2已下线, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE product ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, price DECIMAL(10, 2) NOT NULL, stock INT DEFAULT 0, cover_url VARCHAR(255), status TINYINT DEFAULT 1 COMMENT 1上架 0下架, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(64) NOT NULL UNIQUE, user_id BIGINT NOT NULL, total_amount DECIMAL(10, 2) NOT NULL, status TINYINT DEFAULT 0 COMMENT 0待支付 1已支付 2已发货 3已完成 4已取消, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );可以看到用户表加了role字段区分普通用户和管理员笔记表加了status字段支撑后台审核商品表用status控制上下架。这些字段并不复杂但它们是 Web 后台能独立管理内容的基础。如果省掉状态字段后面后台审核功能会无从下手。4.2 点赞、收藏、评论、购物车等关联表核心表确定后再补充关联表保存用户与内容之间的交互关系。CREATE TABLE favorite ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, note_id BIGINT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_note (user_id, note_id) ); CREATE TABLE comment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, note_id BIGINT NOT NULL, content VARCHAR(500) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE cart ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, product_id BIGINT NOT NULL, quantity INT DEFAULT 1, selected TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_product (user_id, product_id) );关联表看起来简单但有几处容易错favorite表要加唯一键防止重复点赞cart表要按用户和商品维度唯一这样重复加入购物车时执行的是数量累加而不是插入新记录。这些细节在接口开发时都能遇到。4.3 接口返回格式与分页约定App 端、Web 后台和服务端之间统一约定接口返回格式可以大幅减少联调成本。{ code: 0, message: ok, data: { list: [], total: 100, page: 1, size: 10 } }分页接口统一约定page和size参数返回结果带total。这样 App 端做下拉加载时可以用page 1请求下一页直到列表长度等于total时停止。图片、头像、封面地址在数据库中建议存相对路径或完整 URL服务端统一拼接域名避免前端到处改 baseUrl。5. 笔记信息流模块的 ArkTS 实现双列瀑布流与交互状态5.1 首页结构搜索栏、Tab 栏与内容列表首页是类小红书 App 的门面结构上可以分为三块顶部搜索栏、Tab 切换栏、笔记内容列表。Tab 可以切换“推荐”“穿搭”“美食”“美妆”等分类按分类请求后端接口即可。ArkTS 页面骨架如下Entry Component struct HomePage { State noteList: NoteItem[] []; State currentCategory: string 推荐; build() { Column() { Row() { TextInput({ placeholder: 搜索笔记和商品 }) .layoutWeight(1) Button(搜索) .onClick(() this.search()) } .padding(10) TabBar({ categories: [推荐, 穿搭, 美食, 美妆], current: this.currentCategory, onSelect: (category: string) this.loadNotes(category) }) NoteList({ notes: this.noteList }) .layoutWeight(1) } } search() { // 跳转到搜索结果页 } loadNotes(category: string) { // 请求后端接口并刷新 noteList } }这里把搜索、Tab、列表拆成多个组件或 Builder可以让页面结构更清晰。State装饰的变量是状态源ArkUI 会在状态变化时重新渲染界面。要特别注意的是修改数组时直接this.noteList.push(item)不会触发刷新正确做法是生成新数组重新赋值例如this.noteList [...this.noteList, ...newData]。5.2 双列瀑布流的两种实现方案瀑布流是类小红书 App 最核心的界面特征。实现上主要有两种思路。第一种是使用 ArkUI 的WaterFlow组件。如果你的目标 API 版本支持代码会简洁很多WaterFlow() { LazyForEach(this.noteList, (item: NoteItem) { FlowItem() { NoteCard({ note: item }) } }, (item: NoteItem) item.id) }LazyForEach会根据列表项在屏幕内的可见性按需创建组件适合大量图片笔记的列表。如果目标版本中WaterFlow不可用可以使用第二种方案用Scroll包裹Row左侧一个Column右侧一个Column把偶数项放进左列奇数项放进右列。Scroll(this.scroller) { Row() { this.leftColumn() this.rightColumn() } .alignItems(VerticalAlign.Top) } .scrollable(ScrollDirection.Vertical) .onReachEnd(() this.loadMore())双列手动布局的原理是左列负责偶数下标数据右列负责奇数下标数据两列各自垂直排列实现类似瀑布流的效果。这个方案的缺点是左右两列高度可能不平衡但通过不断加载新数据、保持两列数量接近可以得到比较自然的展示效果。5.3 笔记卡片、点赞收藏与详情页跳转笔记卡片组件需要展示封面图、标题、作者头像、作者昵称和点赞数。用Component定义卡片接收NoteItem对象然后点击卡片时跳转到详情页。Component export struct NoteCard { Prop note: NoteItem; build() { Column({ space: 4 }) { Image(this.note.coverUrl) .width(100%) .aspectRatio(0.85) .objectFit(ImageFit.Cover) .borderRadius(8) Text(this.note.title) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Row({ space: 4 }) { Text(this.note.authorName) .fontSize(12) Text(this.note.likeCount 赞) .fontSize(12) } .width(100%) } .padding(6) .onClick(() { router.pushUrl({ url: pages/NoteDetailPage, params: { id: this.note.id } }); }) } }Prop表示单向数据传入适合卡片展示场景。点赞按钮的状态变化通常要传递到父组件可以用Link双向绑定或者通过回调函数通知父组件更新数据。点击卡片跳转详情页时通过路由params传递笔记 id详情页再根据 id 请求完整内容。5.4 网络请求封装与图片加载兜底App 端不直接在每个页面里写http请求建议统一封装一个ApiClient服务。基本写法如下import { http } from kit.NetworkKit; export class ApiClient { static baseUrl: string http://192.168.1.100:8080/api; static getT(path: string): PromiseT { const request http.createHttp(); return request.request(this.baseUrl path, { method: http.RequestMethod.GET, connectTimeout: 10000, readTimeout: 10000, header: { Content-Type: application/json } }).then((resp) { if (resp.responseCode 200) { return JSON.parse(resp.result as string) as T; } throw new Error(request failed: resp.responseCode); }).finally(() { request.destroy(); }); } }网络请求成功不等于业务成功。服务端通常会在 HTTP 200 下返回code字段前端要先判断code 0再处理data。如果code非 0要弹出错误提示。图片加载方面Image组件的src可以设置网络 URL但是要确认三件事图片域名是否在系统网络安全配置允许的范围内URL 是http还是https明文请求可能被拦截图片加载失败时有没有兜底图。兜底写法如下Image(this.note.coverUrl) .alt($r(app.media.default_cover)) .objectFit(ImageFit.Cover).alt()参数会在图片加载失败或尚未加载完成时展示本地兜底图。生产环境中图片链接触发大量流量要考虑服务端开启 CDN 或图片压缩毕设阶段只要保证图片能正常加载、失败有兜底即可。6. 商城模块的 ArkTS 实现购物车数量逻辑和模拟下单6.1 商品列表、商品详情与加入购物车商城模块的商品列表结构和笔记列表类似只是卡片信息不同需要展示商品名称、价格和库存。商品卡片点击后进入商品详情页详情页包含大图、价格、库存、数量选择和加入购物车按钮。商品数据模型可以设计为export class ProductItem { id: string ; name: string ; price: number 0; stock: number 0; coverUrl: string ; status: number 1; }加入购物车时调用后端接口把userId、productId、quantity传给服务端。服务端做原子操作库存足够时更新购物车记录并扣减临时数量库存不足时返回错误码。不要在 App 端自行计算库存因为客户端数据不可信最终校验必须在服务端完成。6.2 购物车数量管理、选中逻辑与总价计算购物车页面是状态管理比较集中的地方需要处理数量增加、数量减少、单选、全选、删除、总价计算等操作。ArkTS 中数组元素内部的字段变化通常不会自动触发界面刷新因此更新数量后最好重新赋值整个数组。核心逻辑示例Component struct CartPage { State cartItems: CartItem[] []; updateQuantity(index: number, delta: number) { const item this.cartItems[index]; item.quantity Math.max(1, item.quantity delta); this.cartItems [...this.cartItems]; } toggleSelect(index: number) { this.cartItems[index].selected !this.cartItems[index].selected; this.cartItems [...this.cartItems]; } get totalPrice(): number { return this.cartItems .filter(item item.selected) .reduce((sum, item) sum item.price * item.quantity, 0); } }这里的totalPrice是计算属性每次界面渲染时会根据cartItems重新计算。数量最小值要限制为 1最大值不能超过商品库存。全选逻辑判断当前选中数量是否等于列表长度注意空购物车时要禁用“提交订单”按钮。6.3 下单流程与模拟支付从购物车提交订单时只把选中的商品提交给服务端。订单创建接口返回订单号前端生成一个支付确认页用户点击“确认支付”后调用模拟支付接口服务端把订单状态从待支付改为已支付。async submitOrder() { const selectedItems this.cartItems.filter(item item.selected); if (selectedItems.length 0) { return; } const order await ApiClient.postOrderResult(/order/create, { items: selectedItems.map(item ({ productId: item.productId, quantity: item.quantity })) }); // 跳转到支付确认页 router.pushUrl({ url: pages/PayPage, params: { orderNo: order.orderNo, amount: order.totalAmount } }); }模拟支付的代码量不大但演示效果很重要。支付完成后订单状态更新为已支付购物车要清空已下单商品。后台管理员看到已支付订单后可以执行发货操作订单状态变为已发货。这样一条从 App 到后台再到 App 的完整业务闭环就成立了。7. Web 后台快速搭建内容审核和订单管理是关键7.1 后台功能清单与页面拆分Web 后台是区分“一个 App Demo”和“一个完整项目”的重要加分项。后台功能不需要做得非常华丽但必须覆盖核心运营动作。后台模块核心功能依赖数据表对 App 的影响登录管理员账号登录user无数据看板今日新增用户、笔记数、订单数、销售额user/note/order无用户管理用户列表、禁用启用user被禁用用户无法登录笔记管理笔记列表、审核、下架note审核通过后用户端可见商品管理商品列表、上架、下架product下架商品用户端不可见订单管理订单列表、发货order发货后订单状态变化从这张表可以看出后台管理的每个操作几乎都会影响用户端数据。毕设答辩时最有效的演示路径是在后台把一条笔记从待审核改为通过然后在 App 端刷新看到这条笔记上线。这比单纯展示一堆静态页面更有说服力。7.2 后台技术选型前后端分离还是服务端模板Web 后台有两种常见做法。第一种是前后端分离后端提供接口前端使用 Vue3 Element Plus 或 React Ant Design 开发。这种方式结构清晰页面美观适合有前端基础的同学但需要同时维护两个工程的开发环境。第二种是服务端模板渲染后端直接提供 HTML 页面管理界面用 Bootstrap 或原生 HTML 实现。这种方式工程简单适合时间紧张、只想快速跑通后台功能的场景。对比表如下方案开发成本展示效果适合场景Vue3 Element Plus 前后端分离中等较好有前端基础希望提升项目含金量服务端模板渲染低一般时间紧只求后台可用React Ant Design中等偏高较好熟悉 React 生态7.3 后台列表页、审核操作和管理员登录后台列表页的核心是“列表 条件筛选 操作按钮”。比如笔记管理页需要展示用户昵称、笔记标题、分类、状态、创建时间并提供“通过”“下架”按钮。状态字段在数据库中是数字后台要转换成中文展示例如0转成“待审核”、1转成“已上线”。管理员登录需要单独设计不能在后台使用普通用户的注册登录接口。简单做法是初始化一条role1的管理员记录后台登录时校验角色。生产环境还要加入验证码、单点登录、操作日志等机制但毕设阶段可以先不做。如果后台使用 Vue3 开发基础登录流程是输入账号密码后端校验成功后返回 token前端把 token 存到localStorage或pinia中后续请求在Authorization头携带。这个流程和 App 端高度相似可以在答辩时作为“多端接口复用”的例子来说明整个项目设计的一致性。8. 真机调试与接口联调从日志到链路的排查顺序8.1 联调环境先确认避免在错误前提下找问题App 端和服务端联调时最常遇到的就是环境问题。这里按优先级列出检查清单真机和电脑是否处于同一局域网。服务端接口是否能从电脑浏览器直接访问。App 中配置的baseUrl是否是电脑的局域网 IP而不是localhost或127.0.0.1。真机是否能 ping 通电脑 IP电脑防火墙是否拦截了服务端端口。网络权限是否已在module.json5中声明。localhost是一个高频错误。模拟器虽然运行在电脑上但模拟器内部的网络环境和宿主机不同写死localhost经常导致无法访问本机服务真机上访问电脑服务也必须使用电脑的局域网 IP。建议把baseUrl单独放到配置文件中方便调试时切换。8.2 常见错误现象与排查路径问题现象可能原因检查方式处理建议请求后台接口一直超时真机和电脑不在同一网络或端口被防火墙拦截查看两台设备 IP做 ping 测试改用同一 WiFi开放服务端端口或临时关闭防火墙接口返回 404后端路径和前端请求路径不一致查看后端控制台日志浏览器直接访问接口统一接口路径拼接规则接口返回 JSON 解析失败返回格式不符合前端类型定义查看返回原始字符串和model中字段前后端共同维护接口文档图片加载空白图片 URL 使用 http或域名未配置浏览器打开图片地址检查网络策略使用 https配置网络安全白名单准备本地兜底权限弹窗不出现功能不可用只在配置中声明未动态申请检查requestPermissionsFromUser调用按系统要求完成动态申请流程页面状态不刷新直接修改数组内部字段检查是否重新赋值State数组使用新数组替换旧数组触发渲染排查顺序建议先看服务端有没有收到请求再看服务端返回了什么最后看前端解析结果。把问题定位到“网络不通”“服务端异常”“前端解析异常”三个分段比从界面开始盲目改代码要高效得多。8.3 日志和真机调试的关键节点鸿蒙开发中日志通过 HiLog 输出可以从 DevEco Studio 的 Log 窗口查看。页面里可以使用console.info输出关键变量。排查网络请求时重点看三个时间点请求发出前baseUrl是否正确参数是否完整。服务端收到请求时路径、Method、请求体是否与接口定义一致。响应返回后HTTP 状态码、code字段、data内容是否能被解析。如果真机连接不上 DevEco Studio先检查 USB 调试是否打开、驱动是否安装、设备是否已在开发者选项中授权电脑。部分型号的设备在首次连接时需要确认“允许 USB 调试”弹窗这是很容易忽略的一步。9. 毕设验收与答辩准备功能完整度要能自圆其说9.1 按模块整理验收清单答辩演示之前建议按模块整理一份验收清单逐项自测。模块必测功能验收标准用户端登录注册、退出使用数据库中的账号可登录错误密码有提示笔记首页瀑布流、详情、点赞、收藏、发布发布后后台可见后台审核通过后用户端可查看搜索关键词搜索笔记或商品输入关键词返回正确结果商城商品列表、详情、购物车、下单购物车选中项正确订单状态正确流转个人中心我的发布、我的收藏、订单列表数据与用户关联正确后台登录、看板、管理操作审核、上下架、发货状态能同步到用户端清单里最容易漏的是“发布笔记后走后台审核再上线”这条链路。很多毕设只做了页面展示没有把内容状态管理起来答辩时被问“谁审核内容”就答不上来。这一条链路完整跑通整个项目的业务价值会明显提升。9.2 演示路径先主链路再功能点演示不要从“登录”开始慢慢点要先给评委一条清晰的主链路。推荐演示顺序打开 App展示首页双列瀑布流截图展示界面效果。登录账号进入笔记详情演示点赞和收藏。点击发布按钮上传一张图片并填写内容提交笔记。切换到 Web 后台演示管理员登录找到待审核笔记并审核通过。回到 App刷新首页看到刚发布的笔记已经上线。进入商城模块把商品加入购物车确认下单并模拟支付。回到 Web 后台找到新订单并执行发货。回到 App查看订单状态变为已发货。这条路径把 App、服务端、Web 后台三个端都串了起来每一步都有明确的因果验证。相比“这里能点赞、那里能加购”的碎片化演示这条链路更能体现项目完整性。9.3 答辩高频问题与准备方向答辩时经常被问到四类问题为什么选择鸿蒙系统和 ArkTS而不是 Android 或 Flutter。可以从“新平台、原生能力、声明式 UI、与 TypeScript 语法相近”几个角度回答不要贬低其他技术只讲选题差异。状态管理是怎么做的。要能说出State、Prop、Link的区别以及数组更新为什么需要重新赋值。服务端接口如何保证安全。至少要说密码加密存储、登录 token、后台接口的角色校验。没有做 token 校验的项目在答辩时容易失分。如果数据量变大项目怎么优化。可以从分页、懒加载、图片缓存、服务端索引、Redis 缓存几个方向回答。前面代码里已经用了LazyForEach和分页这一点就能直接关联上。提前把这些问题的答案写成文字稿比临场组织语言要稳得多。10. 最佳实践与扩展方向从毕设项目升级成简历项目10.1 工程化上最值得做的几个改进如果时间和精力允许建议在完成基础功能后加入以下工程化改进接口统一封装所有请求都走一个ApiClient统一处理错误码、加载态和 token。配置文件外置baseUrl、图片域名放到配置文件中不要在页面里散落写死。日志规范App、服务端、Web 后台都保留运行日志至少能查清请求失败发生在哪个环节。异常分支处理用户拒绝权限、网络超时、库存不足、订单重复提交这些场景要有明确提示。密码安全用户密码在服务端使用bcrypt或PBKDF2哈希再存储不能明文入库。这些点不一定都写在答辩 PPT 里但在代码审查和系统演示中会体现出来。尤其是“库存不足”和“重复提交订单”的异常处理是很多毕设项目欠缺的地方。10.2 可以继续扩展的方向这个题目可以从两个方向继续拔高。第一个方向是多端协同。鸿蒙系统强调分布式能力可以尝试在平板、手机之间接力演示或者用分布式数据把自己的笔记同步到另一个设备。这一块不需要做很大有一个小型场景演示即可但能体现对鸿蒙平台特性的理解。第二个方向是内容推荐和数据可视化。用户端可以记录用户的浏览、点赞行为服务端做一个简单的标签推荐策略Web 后台的数据看板可以加入图表展示签到趋势、订单金额趋势。这块可以参考开源图表库或服务端统计函数实现。推荐策略不要求做成复杂算法能解释清楚“基于内容标签的简单推荐思路”就已经超过大多数选题。10.3 对做
返回列表