OUC26夏移动软件开发-实验3 OUC26夏移动软件开发-实验3姓名马一诺 学号项目内容姓名和学号马一诺所属课程中国海洋大学26夏《移动软件开发》实验名称实验3高校新闻网博客地址本文代码仓库地址https://github.com/1-qaz-2-wsx/ouc26-mobile-dev/tree/main/lab3/code3一、实验内容1. 实验目标与开发环境本实验根据课程网页和实验手册使用微信小程序原生框架开发一个以中国海洋大学为主题的高校新闻网。项目使用本地模拟新闻数据和微信本地缓存不接入云开发、服务器或数据库。在完成轮播图、新闻列表、详情展示、用户登录和新闻收藏等基本要求的基础上本项目进一步实现了搜索与分类、阅读历史、批量收藏管理、新闻分享、深浅色主题和正文字号设置等功能主要练习内容包括使用 WXML、WXSS 和 JavaScript 构建多页面小程序使用app.json配置页面、导航栏和tabBar使用公共模块管理新闻数据和本地状态使用生命周期函数完成跨页面数据刷新使用微信原生头像选择、登录、分享及本地缓存 API处理登录权限、重复操作和跨页面状态同步。2. 项目结构与页面功能当前小程序共注册六个页面其中首页和个人中心是tabBar页面其余页面通过navigateTo或redirectTo打开。页面路径主要功能首页pages/index/index轮播图、新闻列表、搜索、分类、收藏、分享和已读标记新闻详情pages/detail/detail新闻全文、收藏、分享、复制标题、字号调整和相关推荐个人中心pages/my/my微信头像登录、资料修改、退出登录和收藏批量管理新闻合集pages/collection/collection展示并分享批量选择的新闻阅读历史pages/history/history查看最近阅读记录并一键清空设置pages/settings/settings主题、字号、缓存信息及本地数据清理主要目录如下code3/ ├─ app.js / app.json / app.wxss ├─ images/ # tabBar 图标和本地新闻图片 ├─ utils/ │ ├─ common.js # 公共新闻数据与查询函数 │ └─ store.js # 登录、收藏、历史和设置服务 └─ pages/ ├─ index/ # 首页 ├─ detail/ # 新闻详情 ├─ my/ # 个人中心 ├─ collection/ # 新闻合集 ├─ history/ # 阅读历史 └─ settings/ # 设置3. 全局配置与海洋主题导航app.json的pages数组用于注册页面数组第一项是小程序启动页pages:[pages/index/index,pages/detail/detail,pages/my/my,pages/collection/collection,pages/history/history,pages/settings/settings]全局导航栏以海洋蓝#005a9c为背景标题为“海大新闻网”。底部tabBar提供首页和个人中心两个主要入口tabBar:{color:#64748b,selectedColor:#005a9c,backgroundColor:#ffffff,list:[{pagePath:pages/index/index,text:首页,iconPath:images/index.png,selectedIconPath:images/index_blue.png},{pagePath:pages/my/my,text:我的,iconPath:images/my.png,selectedIconPath:images/my_blue.png}]}iconPath表示未选中图标selectedIconPath表示选中图标。普通页面使用wx.navigateTo()打开而跳转到tabBar页面时使用wx.switchTab()。4. 公共新闻数据设计新闻数据统一保存在utils/common.js的news数组中。每条新闻包含唯一 ID、标题、海报、分类、摘要、正文和日期constnews[{id:ouc-20260827,title:山东省人民政府副省长闫剑波来校调研,poster:/images/newsimage1.jpg,category:海大要闻,summary:调研组参观学校校史馆、海洋科技成果展……,content:8月27日山东省人民政府副省长……,add_date:2026-08-27}]公共模块提供三个查询函数getNewsList()// 返回首页使用的新闻列表getNewsDetail(newsID)// 根据唯一 ID 返回完整新闻getNewsByIds(ids)// 根据 ID 数组恢复收藏或合集虽然已经存在news数组仍然需要getNewsList()。原因是页面不应该直接依赖模块内部数组查询函数可以只返回首页需要的字段并通过map()生成新对象避免页面意外修改原始数据。以后将本地数组替换为接口数据时也只需要调整公共模块。各页面通过 CommonJS 引入数据模块constcommonrequire(../../utils/common.js)这样首页、详情、个人中心、阅读历史和新闻合集都通过同一个新闻 ID 获取数据避免多个页面分别维护新闻造成内容不一致。5. 本地状态服务设计为了避免每个页面重复调用缓存 API项目新增utils/store.js集中处理用户会话、收藏、历史和设置。固定缓存键如下constKEYS{session:oucUserSession,favorites:favoriteNewsIds,history:readingHistory,settings:oucAppSettings}其中oucUserSession保存仿真用户 ID、头像、昵称、登录时间和登录状态favoriteNewsIds保存收藏新闻的 ID 数组readingHistory保存新闻 ID 和最近阅读时间oucAppSettings保存主题与正文字号。收藏数组通过Set去重避免快速点击产生重复 IDfunctionuniqueIds(ids){returnArray.from(newSet((Array.isArray(ids)?ids:[]).filter(Boolean)))}使用统一服务后首页、详情页和个人中心不会分别编写缓存逻辑收藏状态更容易保持同步。6. 首页设计与功能实现6.1 标题区域与自动轮播图首页顶部使用多个text标签显示英文标识、主标题和说明文字并通过渐变背景形成统一的海洋主题。轮播区域使用swiper和swiper-itemswiper indicator-dots autoplay circular interval5000 duration500 swiper-item wx:for{{swiperImg}} wx:keysrc image src{{item.src}} modeaspectFill/image view classswiper-mask/view text classswiper-title{{item.title}}/text /swiper-item /swiperindicator-dots显示轮播指示点autoplay开启自动播放circular让最后一张与第一张循环连接interval和duration分别控制停留时间与动画时长modeaspectFill保持图片比例并填满固定区域。图片全部使用项目内/images路径不依赖网络图片域名白名单。6.2 搜索与分类组合筛选搜索框通过bindinput实时保存关键词分类栏使用横向scroll-view展示“全部、海大要闻、综合新闻、校园动态”。applyFilters()同时判断分类与关键词constlistthis.data.allNews.filter(item{constcategoryMatchedcategory全部||item.categorycategoryconsttext${item.title}${item.summary}.toLowerCase()returncategoryMatched(!keyword||text.includes(keyword))})标题和摘要任意一处包含关键词即可匹配搜索与分类条件同时生效。没有结果时使用wx:else显示统一空状态。6.3 新闻列表、已读状态和快捷操作新闻列表使用wx:for渲染每一项通过data-id保存新闻 IDview classnews-item {{item.isRead ? news-read : }} wx:for{{newsList}} wx:keyid bindtapgoToDetail />7. 新闻详情页设计7.1 根据 ID 查询新闻首页只在 URL 中传递新闻 ID详情页在onLoad(options)中查询完整数据constresultcommon.getNewsDetail(options.id)if(result.code!200){this.setData({notFound:true})return}this.setData({article:result.news})页面通过数据绑定显示分类、标题、日期、图片、摘要和正文。海报使用modewidthFix高度根据原始比例计算正文保留段落换行。新闻不存在时显示异常空状态。7.2 阅读历史、相关推荐和底部工具栏打开详情时调用recordHistory(id)保存阅读时间。同一新闻会先删除旧记录再插入数组开头因此历史列表中只保留一条并反映最近阅读时间。详情页末尾展示两条相关推荐底部固定工具栏提供收藏或取消收藏使用button open-typeshare分享给好友使用wx.setClipboardData()复制新闻标题循环切换小、中、大三档正文字号。8. 微信仿真登录与个人资料8.1 登录方案说明微信现行基础库已经不能通过旧的wx.getUserProfile()一次性获得真实微信头像和昵称。开启云开发只能通过登录凭证换取openid也不能绕过用户操作直接读取头像昵称。因此本实验使用课程演示级纯前端仿真登录登录按钮本身设置open-typechooseAvatar用户点击后由微信打开原生头像选择界面获取用户选择的头像后调用wx.saveFile()保存本地文件调用wx.login()连接微信环境登录成功后生成“海大读者 四位数字”的随机昵称将会话保存到oucUserSession。button open-typechooseAvatar bindtapbeginAvatarChoice bindchooseavataronLoginAvatarChosen disabled{{isLogging || isChoosingAvatar}} 微信头像登录 /buttonconnectWechat(avatarUrl){wx.login({success:loginRes{if(!loginRes.code)returnthis.finishLogin({nickName:store.generateRandomNickname(),avatarUrl},loginRes.code)}})}该登录仅表示成功连接微信小程序运行环境不保存临时code也不伪造openid不能用于跨设备识别同一个真实微信账号。8.2 防止头像选择重复触发调试时曾出现chooseAvatar:fail another chooseAvatar is in progress。原因是第一次原生头像选择尚未结束时按钮又被重复触发。项目增加共享状态isChoosingAvatar首次点击后立即禁用登录和修改头像两个入口选择完成后解除如果开发者工具没有回调则在 5 秒后自动恢复并在页面卸载时清理定时器。8.3 资料修改与退出登录登录后显示头像、随机昵称、仿真用户 ID 和登录时间。“资料与账号”区域提供修改头像、修改昵称和退出登录修改头像继续使用微信原生chooseAvatar修改昵称使用input typenickname既可手动填写也可使用微信提供的昵称快捷输入退出登录前通过wx.showModal()确认只删除oucUserSession收藏、阅读历史和设置在退出后继续保留。9. 登录权限与收藏同步首页红心、首页操作菜单和详情页工具栏都能操作收藏。为避免未登录用户收藏项目使用页面校验与服务校验两层保护。页面在执行收藏前调用if(!store.requireLogin())return未登录时显示“请先登录”对话框用户可以跳转个人中心。收藏服务也会再次检查会话functiontoggleFavorite(id){if(!getSession())returnnull// 登录后才允许修改 favoriteNewsIds}这样即使以后新增页面遗漏了界面判断底层服务也不会写入收藏。退出登录后原收藏仍保存在本地但首页红心显示为空且无法修改重新登录后恢复原收藏状态。收藏状态同步主要依靠两个设计所有页面统一调用store.toggleFavorite()和store.isFavorite()页面在onShow()中重新读取缓存从详情页或个人中心返回后立即得到最新状态。10. 收藏批量管理与新闻合集分享个人中心读取favoriteNewsIds再通过getNewsByIds(ids)恢复新闻对象。点击“管理”后列表进入批量选择状态点击复选框逐条选择支持全选与取消全选批量取消收藏前显示新闻数量并再次确认点击单条新闻右侧实心红心可快速取消未选择新闻时禁用“分享合集”。分享合集时将新闻 ID 使用逗号连接并编码到页面参数中constidsencodeURIComponent(this.data.selectedIds.join(,))constpath/pages/collection/collection?idsids合集页解析 ID 后展示对应新闻并通过onShareAppMessage()生成一张可打开多条新闻的分享卡片。11. 阅读历史与设置功能阅读历史以如下结构保存[{id:ouc-20260827,readAt:1788160000000}]历史页面根据 ID 恢复新闻标题、图片和分类同时使用formatTime()显示最近阅读时间并提供一键清空功能。设置页面提供浅色、深色和跟随系统三种主题小、中、大三档正文字号清除阅读历史清除全部收藏显示应用版本和本地存储占用。主题和字号保存在oucAppSettings。applyAppearance()除了切换页面类名还调用wx.setNavigationBarColor()和wx.setTabBarStyle()使导航栏、底部栏与页面主题保持一致。12. 界面风格与移动端适配项目以海洋蓝#005a9c、青蓝#0086b8、浅灰蓝#f3f7fb和白色为主色。页面通过渐变标题区、圆角卡片、胶囊分类标签、弱化日期和统一空状态形成一致的视觉语言。布局主要使用flex尺寸使用rpx使界面随屏幕宽度自动缩放。列表图片使用固定宽高配合aspectFill保持版式稳定详情图片使用widthFix保留完整比例。底部工具栏和批量操作栏使用安全区变量减少全面屏设备底部遮挡。13. 最终运行效果与测试开发过程中使用模拟微信 API 对核心逻辑进行测试并检查全部 JavaScript、JSON、WXML 和 WXSS 结构。主要验证结果如下原生头像选择后能够调用wx.login()并创建会话随机昵称符合“海大读者 四位数字”的格式重复点击头像选择按钮不会再次发起操作修改头像或昵称不会改变用户 ID、收藏、历史和设置未登录时首页和详情页均无法修改收藏退出登录后收藏、历史和设置继续保留登录后首页、详情页和个人中心收藏状态保持同步搜索、分类、下拉刷新、阅读历史、主题和字号设置可正常使用。微信原生头像选择、昵称快捷输入和分享面板需要在微信开发者工具及真机中进行最终人工验证。二、问题总结与体会1. 实验中遇到的问题及解决方法1旧版微信头像昵称授权方式已经失效。最初使用wx.getUserProfile()但当前基础库不能再通过一次授权获取测试者的真实头像昵称并且失败回调曾把所有错误都提示成“用户取消授权”。解决方法是移除该接口使用微信现行的button open-typechooseAvatar用户选择头像后完成仿真登录并生成随机昵称。真实openid必须通过云函数或 HTTPS 后端使用登录凭证换取但云开发同样不能直接读取真实头像昵称。2头像选择可能被重复触发。在 Windows 开发者工具中快速点击时出现another chooseAvatar is in progress。解决方法是增加isChoosingAvatar共享锁在选择期间禁用登录和修改头像入口并设置超时恢复和页面卸载清理防止重复调用或按钮永久锁定。3未登录状态仍然能够收藏。最初首页和详情页直接调用收藏服务没有检查会话。解决方法是在所有收藏入口调用requireLogin()同时在toggleFavorite()和removeFavorites()底层再次校验。未登录操作不会改变本地收藏数组并提供跳转个人中心的提示。4多个页面的收藏状态容易不一致。如果各页面分别维护布尔值从详情页返回后首页红心可能仍是旧状态。解决方法是统一使用favoriteNewsIds并在页面onShow()中重新读取缓存公共服务还通过Set去重防止快速点击产生重复 ID。5收藏批量分享不能直接传递完整对象。URL 参数不适合携带多个复杂新闻对象。解决方法是只传递编码后的 ID 字符串合集页再调用getNewsByIds()恢复新闻实现一张卡片分享多条新闻。6网络图片在真机中可能无法显示。外部图片需要配置合法域名也可能因网络波动失效因此轮播图和新闻海报统一使用/images下的本地图片。7图片比例不同会造成变形。列表和轮播图使用固定容器与aspectFill详情大图使用widthFix。针对不同展示场景选择图片模式兼顾版式稳定和内容完整。8本机截图路径不能用于 CSDN。Typora 自动生成的C:\Users\...路径只在本机有效上传博客后无法显示。因此报告中不再保留绝对路径截图位置统一使用 TODO 注释发布到 CSDN 时应上传图片并使用平台生成的网络地址。2. 实验收获与体会通过本次实验我完成了一个包含六个页面、公共数据、本地状态和用户交互的微信小程序对小程序从配置、布局、数据组织到状态持久化的完整开发流程有了更系统的认识。在页面开发方面我进一步熟悉了swiper、scroll-view、image、button和input等组件以及wx:for、wx:if、数据绑定、事件绑定与事件冒泡。通过catchtap处理红心按钮也理解了复杂列表中父子点击事件之间的关系。在数据设计方面我认识到公共数据数组和查询函数承担不同职责。将新闻数据封装在common.js将会话、收藏、历史和设置封装在store.js可以减少页面重复代码并为跨页面同步和后续替换真实接口提供清晰边界。在生命周期方面onLoad()适合首次接收页面参数onShow()适合每次页面重新显示时刷新共享状态。收藏红心、个人中心数量和历史记录的同步使我体会到页面显示正确不仅取决于当前点击事件还取决于返回页面时是否重新读取真实数据源。在微信能力方面我了解到小程序接口会随隐私政策和基础库版本发生变化。不能继续照搬旧教程中的wx.getUserProfile()而应该根据现行能力选择chooseAvatar、input typenickname和wx.login()并明确区分“前端仿真登录”“微信环境连接”和“服务端真实身份识别”。在工程质量方面登录权限漏洞和头像选择重入错误说明仅实现正常流程还不够还需要考虑未登录、取消、重复点击、接口失败和跨页面返回等边界情况。通过统一校验、状态锁、确认弹窗和模拟 API 测试程序的交互完整性和稳定性得到明显提升。