留言板是一款能实现浏览留言,发表留言,删除留言和编辑留言的小程序,用户能够浏览当前的已留内容,并且能按照时间的升序来查看最新的留言内容;能够发表自己的留言内容,在留言发表页填写相关项后即可发表,并能查看到新留言内容;能够删除不需要的留言;能够修改留言内容。因此,简单留言板的功能主要为显示留言、发表留言、删除留言和编辑留言。
视图层设计:
根据功能需求分析,共设计4个页面:首页(显示留言页),发表留言页,编辑留言页和详情页。
数据库设计:
根据留言板功能,设计数据库表名为test,其中设计的字段有id(编号)、title(标题)、content(内容)、image(图像)、count(次数)5个字段,通过Bmob后端云设计。
代码实现:
应用配置:
小程序代码实现的第一步是设置整个应用的配置,示例代码如下:
// app.json
{
"pages": [
"pages/index/index",
"pages/detail/detail"
],
"window": {
"backgroundTextStyle":"light",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "小小留言板",
"navigationBarBackgroundColor": "#3891f8"
},
"style": "v2",
"componentFramework": "glass-easel",
"lazyCodeLoading": "requiredComponents",
"sitemapLocation": "sitemap.json"
}
// app.ts
var Bmob = require('utils/bmob.js');
Bmob.initialize("24448a34530563f1e8b73e2db1f68612","7700f543fe72f7e78c6811ffc386e54c")
App<IAppOption>({
globalData: {},
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
console.log(res.code)
// 发送 res.code 到后台换取 openId, sessionKey, unionId
},
})
},
})
示例代码如下:
<!--index.wxml-->
<image class="toWrite" bindtap="toAddDiary" src="../../images/add.jpg"></image>
<view class="page">
<scroll-view lower-threshold="800" bindscrolltolower="pullUpLoad" upper-threshold="0" scroll-y="true" style="height: {{widdowHeight}}px;">
<view class="page_bd">
<view class="weui_panel_hd">留言列表</view>
<view>
<block wx:if="{{diaryList.length > 0}}">
<navigator class="weui_media_box weui_media_box_text" wx:for="{{diaryList}}" wx:key="diaryItem" url="/pages/detail/detail?objectId={{item.objectId}}&count={{item.count}}">
<view class="title">主题:{{item.attributes.title}}</view>
<view class="content">留言内容:{{item.attributes.content}}</view>
<view class="info">
<view class="time">时间:{{item.updatedAt}}</view>
<view class="count">浏览:{{item.attributes.count}}</view>
<view class="operate">
<icon type="cancel dels" size="16"></icon>
<text class="del" catchtap="deleteDiary" data-id="{{item.objectId}}">删除</text>
<icon type="success edits" size="16"></icon>
<text catchtap="toModifyDiary" data-id="{{item.objectId}}" data-content="{{item.content}}" data-title="{{item.title}}">编辑</text>
</view>
</view>
</navigator>
</block>
</view>
</view>
</scroll-view>
</view>
<view class="js_dialog" id="androidDialog1" style="opacity: 1;" wx:if="{{writeDiary}}">
<view class="weui_mask"></view>
<view class="weui_dialog weui_skin_android">
<view class="weui_dialog_hd">
<strong class="weui_dialog_title">添加留言</strong>
</view>
<form bindsubmit="addDiary" report-submit="true">
<view class="weui_dialog_bd">
<view class="weui_cells_title">标题</view>
<view class="weui_cells weui_weui_cells_after_title">
<view class="weui_cell weui_cell_input">
<view class="weui_cell_bd">
<input class="weui_input" name="title" placeholder="请输入标题"/>
</view>
</view>
</view>
<view class="weui_cells_title">留言内容</view>
<view class="weui_cells weui_cells_after_title">
<view class="weui_cell">
<view class="weui_cell_bd">
<textarea class="weui_textarea" name="content" placeholder="请输入留言内容" style="height: 3.3em;"></textarea>
<view class="weui_textarea_counter">0/200</view>
</view>
</view>
</view>
<view class="pic">
<view class="pictext" bindtap="uppic">添加图片</view>
<block wx:if="{{isTypeof(url)}}">
<image src="../../images/plus.jpg"></image>
</block>
<block wx:else>
<image src="{{url}}"></image>
</block>
</view>
</view>
<view class="weui_dialog_ft">
<view class="weui_dialog_btn weui_dialog_btn_default" bindtap="noneWindows">取消</view>
<button loading="{{loading}}" class="weui_dialog_btn weui_dialog_btn_primary" form-type="submit">提交</button>
</view>
</form>
</view>
</view>
<view class="js_dialog" id="androidDialog2" style="opacity: 1;" wx:if="{{modifyDiarys}}">
<view class="weui_mask"></view>
<view class="weui_dialog weui_skin_android">
<view class="weui_dialog_hd">
<strong class="weui_dialog_title">修改留言</strong>
</view>
<form bindsubmit="modifyDiary">
<view class="weui_dialog_bd">
<view class="weui_cells_title">标题</view>
<input class="weui_input" name="title" value="{{nowTitle}}" placeholder="请输入标题"/>
<view class="weui_cells_title">留言内容</view>
<view class="weui_cells weui_cells_after_title">
<view class="weui_cell">
<view class="weui_cell_bd">
<textarea class="weui_textarea" name="content" value="{{nowContent}}" placeholder="请输入留言内容" style="height: 3.3em;"></textarea>
<view class="weui_textarea_counter">0/200</view>
</view>
</view>
</view>
</view>
<view class="weui_dialog_ft">
<view class="weui_dialog_btn weui_dialog_btn_default" bindtap="noneWindows">取消</view>
<button loading="{{loading}}" class="weui_dialog_btn weui_dialog_btn_primary" form-type="submit">提交</button>
</view>
</form>
</view>
</view>
/* style.wxss */
/* Global Styles */
.page {
position: relative;
}
.page .toWrite {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
width: 60px;
height: 60px;
}
.page .weui_panel_hd {
font-size: 20px;
font-weight: bold;
padding: 20px;
}
/* Diary List Styles */
.weui_media_box {
display: block;
padding: 20px;
background-color: #f9f9f9;
border-bottom: 1px solid #ccc;
text-decoration: none;
color: #333;
}
.weui_media_box:hover {
background-color: #e9e9e9;
}
.title {
font-size: 18px;
font-weight: bold;
margin-bottom: 5px;
}
.content {
font-size: 16px;
margin-bottom: 10px;
}
.info {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
}
.time,
.count {
margin-right: 10px;
}
.operate {
display: flex;
align-items: center;
}
.icon,
.text {
margin-right: 5px;
cursor: pointer;
}
/* Dialog Styles */
.js_dialog {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9998;
}
.weui_mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
}
.weui_dialog {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 5px;
width: 80%;
max-width: 400px;
}
.weui_dialog_hd {
padding: 15px;
text-align: center;
border-bottom: 1px solid #e5e5e5;
}
.weui_dialog_bd {
padding: 20px;
}
.weui_dialog_ft {
padding: 15px;
text-align: center;
border-top: 1px solid #e5e5e5;
}
.weui_dialog_btn {
display: inline-block;
padding: 10px 15px;
font-size: 16px;
cursor: pointer;
border-radius: 5px;
}
.weui_dialog_btn_default {
color: #888;
border: 1px solid #888;
}
.weui_dialog_btn_primary {
color: #fff;
background-color: #007bff;
border: 1px solid #007bff;
}
var Bmob = require('../../utils/bmob');
var common = require('../../utils/common');
var app = getApp();
var that;
var url = '';
function getList(t) {
that = t;
var Diary = Bmob.Object.extend("test");
var query = new Bmob.Query(Diary);
var query1 = new Bmob.Query(Diary);
query.descending('createdAt');
query.include("own");
query.limit(that.data.limit);
var mainQuery = Bmob.Query.or(query, query1);
mainQuery.find({
success: function (results) {
console.log("查询成功,结果为:", results);
that.setData({
diaryList: results
});
},
error: function (error) {
console.log("查询失败:" + error.code + "--" + error.message);
}
});
}
Page({
data: {
writeDiary: false,
loading: false,
windowHeight: 0,
windowWidth: 0,
limit: 10,
diaryList: [],
modifyDiarys: false
},
onShow: function () {
getList(this);
wx.getSystemInfo({
success: (res) => {
this.setData({
windowHeight: res.windowHeight,
windowWidth: res.windowWidth
});
}
});
},
toAddDiary: function () {
this.setData({
writeDiary: true
});
},
uppic: function () {
var that = this;
wx.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: function (res) {
var tempFilePaths = res.tempFilePaths;
if (tempFilePaths.length > 0) {
var newDate = new Date();
var newDateStr = newDate.toLocaleDateString();
var tempFilePath = [tempFilePaths[0]];
var extension = /\.([^.]*)$/.exec(tempFilePath[0]);
if (extension) {
extension = extension[1].toLowerCase();
}
var name = newDateStr + '.' + extension;
var file = new Bmob.File(name, tempFilePaths);
file.save().then(
function (res) {
console.log(res.url());
url = res.url();
that.setData({
url: url
});
},
function (error) {
console.log(error);
}
);
}
}
});
},
addDiary: function (event) {
var title = event.detail.value.title;
var content = event.detail.value.content;
var formId = event.detail.formId;
console.log("event", event);
if (!title) {
common.showTip("标题不能为空", "loading");
} else if (!content) {
common.showTip("内容不能为空", "loading");
} else {
this.setData({
loading: true
});
var currentUser = Bmob.User.current();
var User = Bmob.Object.extend("_User");
var UserModel = new User();
var Diary = Bmob.Object.extend("test");
var diary = new Diary();
diary.set("title", title);
diary.set("formId", formId);
diary.set("content", content);
diary.set("image", url);
diary.set("count", 1);
if (currentUser) {
UserModel.id = currentUser.id;
diary.set("own", UserModel);
}
diary.save(null, {
success: function (result) {
common.showTip("添加日记成功");
that.setData({
writeDiary: false,
loading: false
});
that.onShow();
},
error: function (result, error) {
common.showTip("添加留言失败,请重新发布", "loading");
}
});
}
},
deleteDiary: function (event) {
var that = this;
var objectId = event.target.dataset.id;
wx.showModal({
title: "操作提示",
content: "确定要删除留言?",
success: function (res) {
if (res.confirm) {
var Diary = Bmob.Object.extend("test");
var query = new Bmob.Query(Diary);
query.get(objectId, {
success: function (object) {
object.destroy({
success: function (deleteObject) {
console.log("删除留言成功");
getList(that);
},
error: function (object, error) {
console.log("删除留言失败");
}
});
},
error: function (object, error) {
console.log("查询留言失败");
}
});
}
}
});
},
toModifyDiary: function (event) {
var nowTitle = event.target.dataset.title;
var nowContent = event.target.dataset.content;
var nowId = event.target.dataset.id;
this.setData({
modifyDiarys: true,
nowTitle: nowTitle,
nowContent: nowContent,
nowId: nowId
});
},
modifyDiary: function (e) {
var t = this;
this.modify(t, e);
},
modify: function (t, e) {
var that = t;
var modyTitle = e.detail.value.title;
var modyContent = e.detail.value.content;
var objectId = e.detail.value.id;
var thatTitle = that.data.nowTitle;
var thatContent = that.data.nowContent;
if ((modyTitle != thatTitle || modyContent != thatContent)) {
if (modyTitle == "" || modyContent == "") {
common.showTip("标题或内容不能为空", "loading");
} else {
console.log(modyContent);
var Diary = Bmob.Object.extend("test");
var query = new Bmob.Query(Diary);
query.get(that.data.nowId, {
success: function (result) {
result.set("title", modyTitle);
result.set("content", modyContent);
result.save();
common.showTip("留言修改成功", "success", function () {
that.onShow();
that.setData({
modifyDiarys: false
});
});
},
error: function (object, error) { }
});
}
} else if (modyTitle == "" || modyContent == "") {
common.showTip("标题或内容不能为空", "loading");
} else {
that.setData({
modifyDiarys: false
});
common.showTip("修改成功", "loading");
}
}
});
<!--pages/detail/detail.wxml-->
<view class="page">
<view>
<view>
<view>留言主题:</view>
<view>{{rows.title}}</view>
<view>
<view>留言内容:</view>
<view>{{rows.content}}</view>
<view class="pic">
<image src="{{rows.image}}"/>
</view>
<view>浏览次数:{{rows.count}}</view>
<view>创建时间:{{rows.createAt}}</view>
</view>
</view>
</view>
<view class="footer">
<text>Copyright @2017-2019 www.smartbull.cn</text>
</view>
</view>
// pages/detail/detail.ts
var Bmob = require('../../utils/bmob');
Page({
data:{
rows:{}
},
onLoad:function(e){
console.log(e);
console.log(e.objectId);
var objectId = e.objectId;
var newCount = e.count;
var that = this;
var Diary = Bmob.Object.extend("test");
var query = new Bmob.Query(Diary)
query.get(objectId,{
success:function(result){
console.log(result);
that.setData({
rows:result
})
newCount = parseInt(newCount) + 1;
result.set("count",newCount);
result.save();
},
error:function(result,error){
console.log("查询失败")
}
})
}
})