二、实验步骤
新建项目
新建一个空的微信小程序项目。
配置文件
-
在pages页面下配置index相关文件,logs相关文件以及detail相关文件;
-
在utils文件夹下配置common.js文件,在image文件夹下导入相关图片素材;
-
新建images文件夹,在文件夹下导入所需图片素材;
导航栏设计与实现
使用navigation-bar组件配置上导航栏,使用custom-tab-bar组件配置底部导航栏,使用内置的icon图标,通过onChange函数更新图标
onChange(event) { this.updateActiveTabBar(event.detail), wx.switchTab({ url: this.data.list[event.detail].pagePath, }) }
页面设计与实现
首页
设计新闻浏览页面如下:
-
使用swiper标签实现新闻轮播图的功能:
<swiper class="swiper-container" style="height: 415rpx; width: 750rpx; display: block; box-sizing: border-box" indicator-dots indicator-color="white" autoplay interval="3000" circular> <block wx:for="{{swiperList}}"> <swiper-item> <image src="{{item}}" mode="aspectFit" style="width: 750rpx; height: 415rpx; display: inline-block; box-sizing: border-box"></image> </swiper-item> </block> </swiper>
对应JavaScript函数实现功能:
data: { swiperList: [ 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage1.jpg', 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage2.jpg', 'https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/newsimage3.jpg' ], }
-
使用van-divider标签分割面板
<van-divider contentPosition="center" customStyle="color: #8b8b8b; border-color: #8b8b8b; font-size: 14px;" > 最新消息 </van-divider>
-
使用view标签、image标签和text标签实现新闻列表功能
</van-divider> <view id="news-list"> <view class='list-item' hover-class="hover-item" hover-start-time="50" hover-stay-time="200" wx:for="{{newsList}}" wx:for-item="news" wx:key="{{news.id}}"> <image src='{{news.poster}}'></image> <text bindtap='goToDetail' data-id='{{news.id}}'>◆{{news.title}}\n{{news.add_date}}</text> </view> </view>
goToDetail函数和onLoad通过读取common.js中的news接口来实现新闻列表的输出:
goToDetail: function(e) { //获取携带的data-id数据 let id = e.currentTarget.dataset.id; //携带新闻id进行页面跳转 wx.navigateTo({ url: '../detail/detail?id=' + id }) }, onLoad: function(options) { //获取新闻列表 let list = common.getNewsList() //更新列表数据 this.setData({ newsList: list }) },
对应的wxss代码,在原有的基础上对界面进行了优化。
/* 列表项目 */ .list-item { display: flex; flex-direction: row; border-bottom: 1rpx solid gray; padding: 10rpx 0; /* 上下间隔 */ margin-bottom: 10rpx; /* 底部间隔 */ border-radius: 10rpx; /* 圆角 */ background-color: #fff; /* 背景色,可选 */ transition: all 0.3s ease; /* 过渡效果 */ } /* 新闻图片 */ .list-item image { width: 230rpx; height: 150rpx; margin: 10rpx; border-radius: 14rpx; /* 圆角 */ } /* 新闻标题 */ .list-item text { flex: 1; /* 占用剩余空间 */ line-height: 60rpx; font-size: 10pt; color: #333; /* 默认颜色 */ } .hover-item { background-color: #f9f9f9; }
新闻页面
-
使用view,image标签实现新闻内容的显示。
<view class ='container'> <view class ='title'>{{article.title}}</view> <view class ='poster'> <image src='{{article.poster}}'mode ='widthFix'></image> </view> <view class ='content'>{{article.content}}</view> <view class='add_date'>时间:{{article.add_date}}</view> </view>
data: { comment: '', // 用户输入的评论 comments: [], // 存储所有提交的评论 formattedTime: '', // 用于存储格式化后的时间 nickName:'匿名用户', src:'/images/back1.png', article:{ } }, goToDetail: function(e) { //获取携带的data-id数据 let id = e.currentTarget.dataset.id; //携带新闻id进行页面跳转 wx.navigateTo({ url: '../detail/detail?id=' + id }) }, getMyInfo:function(e){ let info = e.detail.userInfo; this.setData({ nickName:info.nickName, src:info.avatorUrl }) }, onLoad:function(options) { let id = options.id var article = wx.getStorageSync(id) if(article != ''){ this.setData({article:article, isAddsc:true, }) } else{ let result = common.getNewsDetail(id) if(result.code == '200'){ this.setData({article:result.news, isAddsc:false, }) } } },
-
使用button标签实现收藏和取消收藏功能。
<view class="dzpl"> <button wx:if ='{{isAddsc}}' plain bindtap='cancelFavorites'>★已收藏</button> <button wx:else plain bindtap='addFavorites'>☆ 收藏</button> </view>
通过addFavorites和addFavorites函数,结合if判断语句和isAddsc的状态实现收藏和取消收藏功能。
addFavorites:function(options){ let article =this.data.article; wx.setStorageSync(article.id,article); this.setData({isAddsc:true }); }, addFavorites:function(){ let article = this.data.article; wx.removeStorageSync(article.id); this.setData({isAddsc:false }); },
我的主页
-
使用image、text和button标签实现用户登录功能,读取并显示用户的头像和昵称
<view id='myLogin'> <block wx:if ='{{isLogin}}'> <image id='myIcon'src='{{src}}'></image> <text id='nickName'>{{nickName}}</text> </block> <button wx:else open-type="getUserInfo" bindgetuserinfo="getMyInfo">未登录,点此登录</button> </view>
对应的JavaScript代码:
Page({ data: { nickName:'未登录', src:"/images/back1.png", newsList:[{ }], myList:[{ }], num: 0, num2: 0 }, getMyInfo:function(e){ let info = e.detail.userInfo; this.setData({ isLogin:true, src:info.avatorUrl, nickName:info.nickName }) this.getMyFavorites(); },
-
使用text、view、image标签实现我的收藏功能。
<view id="myFavorites"> <text>我的收藏</text> <text id="number"> {{num}} 条</text> <view id="news-list"> <view class = "list-item" wx:for="{{newsList}}" wx:for-item="news" wx:key="{{news.id}}"> <image src="{{news.poster}}" mode=""/> <text bindtap = 'goToDetail' data-id = '{{news.id}}'>◆ {{news.title}}\n{{news.add_date}}</text> </view> </view> </view>
JavaScript代码:
getMyFavorites:function(){ let info =wx.getStorageInfoSync(); let keys =info.keys; let num =keys.length-1; let myList =[]; for(var i = 0;i<num;i++){ let obj =wx.getStorageSync(keys[i]); myList.push(obj); //将新闻添加到数组中 } //更新收藏列表 this.setData({ newsList:myList, num:num }); }, goToDetail: function(e) { //获取携带的data-id数据 let id = e.currentTarget.dataset.id; //携带新闻id进行页面跳转 wx.navigateTo({ url: '../detail/detail?id=' + id }) },
wxss代码:
#myLogin{ background-color:#8B1A1A; height:350rpx; display:flex; flex-direction:column; align-items:center; justify-content:space-around; } #myIcon{ width:200rpx; height:200rpx; border-radius:50%; } #nickName{ color:white; font-size: 20px; font-weight: bold; /* 加粗字体 */ } #myFavorites{ padding:20rpx; background-color:#ffffff; height: 800rpx; margin-top: 20rpx; } #myWorks{ padding:20rpx; background-color:#ffffff; height: 800rpx; margin-top: 20rpx; }
-
~ 额外添加功能
在新闻详情页面实现评论功能,功能包括:
-
检测评论输入框内容为空时,进行提示“内容不能为空!”;
-
发表评论后附带时间戳;
-
并获取用户头像和昵称进行显示;
<!-- 评论功能 --> <view class="container2"> <view class="input-area"> <textarea placeholder="请输入你的评论..." bindinput="inputChange" data-key="comment" value="{{comment}}"></textarea> <button bindtap="submitComment" open-type="getUserInfo" bindgetuserinfo="getMyInfo">提交评论</button> </view> <view class="comment-list"> <van-divider contentPosition="center" customStyle="color: #8b8b8b; border-color: #8b8b8b; font-size: 14px;"> 评论区 </van-divider> <block wx:for="{{comments}}" wx:key="index"> <view class="comment-item"> <!-- {{item.content}} - {{item.formattedTime}} --> <image id="pltx" src="{{src}}" mode=""/> {{nickName}}:{{item}} <text id="pltime">\n {{formattedTime}}</text> </view> </block> </view> </view>
javaScript代码:
// 处理输入框内容变化 inputChange: function(e) { const key = e.currentTarget.dataset.key; this.setData({ [key]: e.detail.value }); }, // 提交评论 submitComment: function() { if (this.data.comment.trim() !== '') { const newComments = [...this.data.comments, this.data.comment]; this.setData({ comments: newComments, comment: '' // 清空输入框 }); const timestamp = 1609459200000; // 例如:2021年1月1日 00:00:00 UTC 的时间戳 // 调用函数处理时间戳 this.setData({ formattedTime: this.formatTime(timestamp) }); } else { wx.showToast({ title: '评论不能为空', icon: 'none' }); } }, formatTime: function(timestamp) { const date = new Date(timestamp); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); const second = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day}`; },
wxss代码:
.bindinput{ border: 2px solid rgb(105, 105, 105); padding: 8px; width: 160px; height: 12px; border-radius: 8px; } button { color: white; background-color: #920000; font-size: 16px; text-align: center; border: none; border-radius: 8px; cursor: pointer; margin-left: 8px; height: 42px; } #pltime{ color: #808080; /* 灰色 */ text-align: right; font-size: 12px; } #plp{ color: #acacac; /* 灰色 */ text-align: right; font-size: 18px; } .dzpl { display: flex; flex-direction: row; align-items: center; justify-content: space-between; padding: 0px; } .dzpl button { margin: 0px 140px; } #pltx{ width: 70rpx; height: 70rpx; border-radius: 15rpx; /* 圆角 */ margin-bottom: -20rpx; }
-
-
在我的界面添加创作者功能,可以自行定义并发表文章,使用云开发,云数据库进行存储。
<view class="container"> <picker mode="selector" value="{{stuIndex}}" range="{{stuName}}" range-key="name" bindchange="bindSchoolChange"> <view class="picker" style="color: white;"> 新闻类型:{{stuName[stuIndex].name}} </view> </picker> <picker mode="selector" value="{{schoolIndex}}" range="{{schools}}" range-key="name" bindchange="bindSchoolChange"> <view class="picker" style="color: white;"> 是否原创:{{schools[schoolIndex].name}} </view> </picker> <picker mode="selector" value="{{subjectIndex}}" range="{{subjects}}" range-key="name" bindchange="bindSubjectChange"> <view class="picker" style="color: white;"> 设置权限:{{subjects[subjectIndex].name}} </view> </picker> <view class="noUse"></view> <!-- pages/myWorks/myWorks.wxml --> <view class="container"> <view class="input-container"> <input type="text" placeholder="请输入题目" class="title-input" maxlength="100" bindinput="handleTitleInput"/> </view> <view class="input-container"> <textarea placeholder="请输入文章内容" class="content-input" bindinput="handleContentInput"></textarea> </view> <image class="uploaded-image" src="{{imageUrl}}" mode="widthFix" hidden="{{!imageUrl}}"></image> <button bindtap="uploadImage" style="color: white;">上传图片</button> <button bindtap="saveToWorks" style="color: white;">保存到我的作品</button> </view> </view>
JavaScript代码:
saveToWorks: function() { const db = wx.cloud.database(); const collection = db.collection('works'); let newData = { title: this.data.title, content: this.data.content, imageUrl: this.data.imageUrl, createTime: new Date().getTime(), }; // 保存到数据库 collection.add({ data: newData, success: res => { // 保存成功的回调 wx.showToast({ title: '保存成功', icon: 'success', duration: 2000 }); }, fail: err => { // 保存失败的回调 wx.showToast({ title: '保存失败', icon: 'none', duration: 2000 }); console.error(err); } }); },
三、程序运行结果
除原始的以下九项功能外,还添加了评论发表和创作者中心功能,可以实现自己编辑发表文章,并进一步优化了页面结构。
(1)首页需要包含幻灯片播放效果和新闻列表;
(2)幻灯片至少 要有3幅图片自动播放;
(3)点击新闻列表可以打开新闻全文;
(4)阅读新闻全文的页面需要显示新闻标题、图片、正文和日 期;
(5)允许 点击按钮将当前阅读的新闻添加到本地收藏夹中;
(6)已经收藏过的新 闻也可以点击按钮取消收藏;
(7)未登录状态下显示登录按钮,用户点击以后可以显示;
(8)登录后读取当前用户的收藏夹,展示收藏的新闻列表;
(9)收 藏夹中的新闻可以直接点击查看内容;
(10)未登录状态下收藏夹显示为空