这是其余几篇的地址:
记《高校考勤系统》小程序(1)
记《高校考勤系统》小程序(2)
记《高校考勤系统》小程序(3)
html
- 校园通知这里主要分为两块:
1.管理员信息发布,顶部公告的设置.(主要涉及图片的上传,数据的增长)
2.用户查看.(主要涉及上拉加载,下拉刷新,点击查看详细信息)
- 这里的话须要用到上传图片这个功能,上传功能案例咱们也能够在新建一个项目中查看到,这里也有详细的代码.
(1)顶部标题,咱们能够在.json文件中加入 navigationBarTitleText 这个属性.前端
{
"navigationBarTitleText": "校园消息编辑",
"usingComponents": {}
}
复制代码
(2)页面布局搭建,校园通知须要有标题,内容,发布人,以及封面图片,固然你也能够根据你的需求添加或删除.git
page{
width: 100%;
height: 100%;
}
.title, .cont {
display: flex;
justify-content: start;
background-color: white;
border-bottom: 1px solid #f6f6f6;
}
.tit_tit, .cont_tit, .upphoto_tit {
margin-left: 20rpx;
margin-right: 30rpx;
line-height: 100rpx;
}
.tit_input {
width: 500rpx;
height: 60rpx;
line-height: 60rpx;
padding: 20rpx;
}
.cont_cont {
margin-top: 14rpx;
padding: 20rpx;
}
.upphoto {
background-color: white;
padding-bottom: 30rpx;
}
.photo {
width: 200rpx;
height: 200rpx;
}
.photo_box {
width: 200rpx;
height: 200rpx;
border: 3rpx dashed;
margin-left: 20rpx;
overflow: hidden;
}
.up {
width: 200rpx;
height: 200rpx;
}
.btn {
width: 300rpx;
margin-top: 100rpx;
background-color: #07c160;
color: white;
}
复制代码
<view class="title">
<text class="tit_tit">标题</text>
<input class="tit_input" placeholder="请输入标题" bindinput="bindKeyInput"></input>
</view>
<view class="cont">
<text class="cont_tit">内容</text>
<textarea class="cont_cont" placeholder="请输入内容" bindinput="bindKeyInput2" maxlength="-1"></textarea>
</view>
<view class="title">
<text class="tit_tit">发布人</text>
<input class="tit_input" placeholder="请输入发布人" bindinput="bindKeyInput3"></input>
</view>
<view class="upphoto">
<text class="upphoto_tit">封面图片</text>
<!-- 上传图片 -->
<view class="photo">
<view class="photo_box" bindtap="doUpload">
<image class="up" hidden="{{ upview }}" src="../../images/up.png"></image>
<image class="up" hidden="{{ upview2 }}" src="{{ filePath }}"></image>
</view>
</view>
</view>
<button class="btn" bindtap="btn">肯定</button>
复制代码
(3)功能实现,js编写.
github
- 首先咱们须要将 input 框中输入的值存储到 data 中
data: {
filePath: '', //图片路劲
title: '', //标题
article: '', // 内容
user: '', //发布人
},
bindKeyInput(e) { //标题输入
this.title = e.detail.value
console.log(this.title)
},
bindKeyInput2(e) { //内容输入
this.article = e.detail.value
},
bindKeyInput3(e) { //发布人输入
this.user = e.detail.value
},
复制代码
- 而后是上传图片功能的实现.详细的步骤写在注释中
// 上传图片
doUpload: function() {
let timestamp = (new Date()).valueOf(); //1.建立时间戳,方便后面文件命名
wx.chooseImage({
count: 1, //2.一次选择的图片数量,这里限制一张,最多九张
sizeType: ['compressed'],
sourceType: ['album', 'camera'], //3.图片来源选择,分为两个1相册选择(album),2相机拍摄(camera)
success: (res) => {
wx.showLoading({ //4.添加提示框,提高视觉效果
title: '上传中',
})
const filePath = res.tempFilePaths[0] //当前存储图片地址
const cloudPath = timestamp + '.png' //5.用时间戳命名图片名称
wx.cloud.uploadFile({ //将图片上传至云存储空间
cloudPath,// 指定上传到的云路径
filePath,// 指定要上传的文件的小程序临时文件路径
success: res => {
this.filePath = res.fileID //5.成功后回调,res.fileID就是咱们在云存储中的路径,能够直接用这个路径来获取图片并显示
this.setData({ //图片上传显示,这里由于原来有图片,因此当上传图片成功后隐藏原来图片,显示用户上传的图片
upview: true,
filePath: this.filePath,
upview2: false
})
app.globalData.fileID = res.fileID
app.globalData.cloudPath = cloudPath
app.globalData.imagePath = filePath
},
fail: e => {
wx.showToast({
icon: 'none',
title: '上传失败',
})
},
complete: () => {
wx.hideLoading()//完成后隐藏提示框
}
})
},
fail: e => {
console.error(e)
}
})
},
复制代码
到这里图片上传功能就作好啦,是否是并无想象中的复杂😄数据库
(4)提交数据到数据库中.
json
- 首先咱们肯定存入数据库中单条数据的json格式
{
"_id": "00a6cea35dca27980575500975c25248",
"_openid": "oQnNa5NJfKqSZntKFLGZWnZuXNbo",
"title": "标题",
"article": "文章内容",
"user": "发布人",
"filePath": "图片上传成功后的云路径",
"timestamp": "发布时间"
}
复制代码
btn(e) {
this.timestamp = (new Date()).valueOf(); //获取时间戳
var date = new Date(this.timestamp); //这里是想作一个发布时间存储
var Y = date.getFullYear() + '-';
var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
var D = date.getDate() + ' ';
var h = date.getHours() + ':';
var m = date.getMinutes() + ':';
var s = date.getSeconds();
this.timestamp = Y + M + D + h + m + s; //时间拼接 0000-00-00 00:00:00 格式
const db = wx.cloud.database({ //数据库新增用户注册信息
env: '***'
})
db.collection('***').add({ //向指定集合添加数据
data: {
title: this.title,
article: this.article,
user: this.user,
filePath: this.filePath,
timestamp: this.timestamp
},
success: res => {
wx.showToast({
icon: 'success',
title: '发布成功',
})
}
})
},
复制代码
- 这里主要注意的地方仍是以前提到过的云开发中的限制,也就是每次获取数据上限是 20条 ,固然你能够搭配云函数来提升每次获取到的数据条数,不过也不建议每次获取过多数据,大量的数据会使加载变慢,下降性能.
- 那么这里我是没有使用云函数的,最多展现20条数据,若是想要展现更多,后面有功能会讲到如何使用云函数开发.
首先仍是页面的布局,这里样式用了 colorUI 中的边框阴影.初始咱们只取前6条数据.小程序
page {
width: 100%;
position: relative;
}
.cont_box {
width: 90%;
height: 160rpx;
background-color: white;
padding: 20rpx;
margin: 0 auto;
margin-top: 20rpx;
margin-bottom: 10rpx;
border-radius: 16rpx;
display: flex;
justify-content: space-between;
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
position: relative;
}
.cont_box::before, .cont_box::after {
position: absolute;
content: "";
top: 20rpx;
bottom: 30rpx;
left: 20rpx;
width: 50%;
box-shadow: 0 30rpx 20rpx rgba(0, 0, 0, 0.2);
transform: rotate(-3deg);
z-index: -1;
}
.cont_box::after {
right: 20rpx;
left: auto;
transform: rotate(3deg);
}
.cont_left {
width: 75%;
height: 100%;
position: relative;
}
.cont_tit {
font-size: 28rpx;
}
.cont_time {
position: absolute;
right: 30rpx;
bottom: 20rpx;
font-size: 24rpx;
}
.cont_img {
width: 160rpx;
height: 160rpx;
}
.bottom {
width: 100%;
text-align: center;
font-size: 24rpx;
color: #ddd;
display: inline-block;
padding: 30rpx 0;
}
.bottom text {
margin-left: 20rpx;
margin-right: 20rpx;
color: #9b9b9b;
}
复制代码
<view class="cont_box" hidden="{{cont_box}}" wx:for="{{ campusNews }}" wx:key="{{index}}" data-index="{{ index }}" bindtap="contBtn">
<view class="cont_left">
<view class="cont_tit">{{ item.title }}</view>
<text class="cont_time">{{ item.timestamp }}</text>
</view>
<image class="cont_img" src="{{ item.filePath }}"></image>
</view>
<view class="bottom" hidden="{{bottom}}">
————
<text>我是有底线的</text> ————
</view>
复制代码
const db = wx.cloud.database({
env: '***'
})
db.collection('***').get().then(res => {
this.campusNews = res.data.reverse()//逆序排序,让新添加的数据排在最前面,将数据存储在data中,方便处理
for(let i = 0; i < 6 ; i++){
this.data.arr.push(this.campusNews[i]) //每次取前6条数据,添加到新数组中进行渲染
}
})
复制代码
通知详情查看:数组
- 在上面,咱们已经获取校园通知的数据,怎么查看相对应的数据呢 ?也是经过获取点击数据的下标来判断
- 咱们在 for 循环中添加 data-index="{{ index }}" 就能够赋值下标,如上代码已经写出👆👆
- 这里我是经过下标来获取数据,在经过url传参来传递数据(由于数据相对较少)
contBtn(e) {
var id = e.currentTarget.dataset.index //获取当前点击下标
wx.navigateTo({
url: "/pages/newsPage/newsPage?title=" + this.campusNews[id].title + "&&article=" + this.campusNews[id].article
})
},
复制代码
跳转页面后,咱们在跳转页面 .js 的 onLoad() 中就能够获取到数据,最后渲染就ok了. 由于样式都是统一的,因此只用一张页面就能够了,只是每次跳转url携带的参数不一样罢了微信
onLoad: function (options) {
console.log(options)
},
复制代码
例如我点击效果图中第一条信息,跳转页面得到的数据以下:网络
下拉刷新:首先须要在 .json 中开启这个功能,还有其余能够修改的属性能够查看 官方文档
- 下拉刷新的原理其实和页面加载时获取数据的原理差很少,固然你也也能够在下拉函数中直接 this.onLoad() ,即下拉时再次执行 onLoad() 函数,成功获取数据后隐藏加载框就行.
onPullDownRefresh: function() {
var arr = [] //声明一个空数组
wx.showNavigationBarLoading(); //显示导航栏加载框
const db = wx.cloud.database({
env: '****'
})
//获取校园消息数据
db.collection('***').get().then(res => {
this.campusNews = res.data.reverse()
for (let i = 0; i < 6; i++) {
arr.push(this.campusNews[i]) //每次渲染6条数据
}
this.setData({
campusNews: arr //前端渲染
})
}).then(res => { //等上一步数据获取成功,执行下面
wx.hideNavigationBarLoading();// 隐藏导航栏加载框
wx.stopPullDownRefresh();// 中止下拉动做
})
},
复制代码
上拉加载:
data: {
campusNews: [],
num: 1,//一次获取的数据
arr:[]
},
onReachBottom: function() {
wx.showLoading({
title: '加载中',
});
this.data.arr = [] //重置清空数组,由于加载页面中数组中已有数据
this.data.num ++ //上拉一次num加1
setTimeout(res=>{ //延时触发判断
if (this.campusNews.length - 6 * this.data.num > 0) { //判断 数组长度 - 6*下拉次数是否大于0,如上大于0则输出6*下拉次数条数据
for (let i = 0; i < 6 * this.data.num; i++) {
this.data.arr.push(this.campusNews[i])
}
this.setData({
campusNews: this.data.arr
})
wx.hideLoading();
} else if (this.data.campusNews.length - 6 * this.data.num <= 0) { // 小于等于0,则所有输出
this.setData({
bottom: false,
campusNews: this.campusNews
})
wx.hideLoading();
}
},1000)
},
复制代码
- 这张页面主要功能就是对已经发布的通知进行管理,能够进行查看、修改及删除. 效果图以下:
- 在此以前该页面的增删改查功能以及所有讲过了,这里就讲讲大体流程,具体实现方法能够查看以前的文章😊
1.首先是从页面结构的搭建,在从数据库中获取数据,渲染到页面.
2.编辑功能其实和课程表中的编辑一致,获取当前点击的数据,赋值到 input 中的 value 中.
3.修改功能须要用到云函数,也是由于云开发权限不足,没法修改别人上传的数据.
(这里不足的是尚未作分页功能,因此只能查看前20条数据,后续会考虑增长分页)
若是这里有疑问的能够留言或私信,一块儿交流😀
- 由于要作普通用户和管理员的区分,因此我在这里加了管理员按钮方便操做
这里就用到了以前讲的在页面加载时,判断数据库中用户的操做权限,userstatus 为 '0' 是普通用户,按钮隐藏;为 '3' 是管理员,按钮显示.
page {
width: 100%;
height: 100%;
position: relative;
}
.lodingBox {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.loding {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.cont {
width: 100%;
height: 100%;
}
.top {
width: 100%;
height: 520rpx;
position: relative;
}
.top_bg {
width: 100%;
height: 380rpx;
}
.avatarUrl {
width: 160rpx;
height: 160rpx;
border-radius: 80rpx;
background-size: 100% 100%;
position: absolute;
left: calc(50% - 80rpx);
bottom: 80rpx;
box-shadow: 4rpx 4rpx 8rpx rgba(26, 26, 26, 0.4);
z-index: 99;
}
.nickName {
margin-top: 74rpx;
text-align: center;
}
.adminBtn{
margin-top: 20rpx;
}
.kfBtn {
width: 100%;
height: 44px;
position: relative;
}
.kfBtn .kf{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.water{
width: 100%;
position: absolute;
margin: 0;
bottom: 134rpx;
}
.bg-gradual-green {
background-image: none;
color: var(--white);
}
.gif-black{
mix-blend-mode: screen;
}
复制代码
<view class="cont" hidden="{{cont}}">
<view class="top">
<image class="top_bg" src="../../images/users.png"></image>
<image class="avatarUrl" src="{{ avatarUrl }}"></image>
<view class="nickName">{{ nickName }}</view>
<view class="water">
<view class="margin radius bg-gradual-green shadow-blur">
<image src="https://user-gold-cdn.xitu.io/2019/11/29/16eb67bab5042a77?w=540&h=100&f=gif&s=978506" mode="scaleToFill" class="gif-black response" style="height:100rpx"></image>
</view>
</view>
</view>
<van-cell title="受权管理" icon="https://pic.yupoo.com/1145338926/445b711b/7cde2620.png" bindtap="openSetting" is-link />
<view class="kfBtn">
<van-cell title="在线联系" icon="https://pic.yupoo.com/1145338926/d5dd143f/4ef73555.png" bindtap="" is-link />
<button class="kf" open-type="contact"></button>
</view>
<van-cell title="项目日志" icon="https://pic.yupoo.com/1145338926/3e003634/e4313e02.png" bindtap="timeline" is-link />
<view hidden="{{ adminBtn }}" class="adminBtn">
<van-cell title="管理员" icon="https://pic.yupoo.com/1145338926/cae3dee7/0573c27b.png" is-link bindtap="openAdmin" />
</view>
</view>
复制代码
const app = getApp()
Page({
data: {
avatarUrl: '',
nickName: '',
userInfo: {},
open_id: '', //用户id
adminStatus: '', // 用户状态
adminBtn: '' //是否显示管理员按钮
},
openSetting() {
wx.openSetting()
},
openAdmin() {
wx.navigateTo({ //跳转管理员界面
url: "/pages/adminChoose/adminChoose"
})
},
timeline(){
wx.navigateTo({ //跳转管理员界面
url: "/pages/timeline/timeline"
})
},
onLoad: function(options) {
this.setData({
adminBtn: true,
cont:true,
loding:false
})
setTimeout(res => {
wx.stopPullDownRefresh(); //结束下拉刷新动画
if (this.adminStatus == '3') { //判断用户权限状态
this.setData({
adminBtn: false,
loding: true ,
cont: false,
})
} else {
this.setData({
adminBtn: true,
loding: true,
cont: false,
})
}
},1300)
wx.cloud.callFunction({
name: 'login',
data: {},
success: res => {
this.open_id = res.result.openid
const db = wx.cloud.database({ //数据库查询用户信息
env: 'env-urae8'
})
db.collection('users').where({ //数据库查询用户权限信息
_openid: this.open_id
}).get({
success: res => {
this.adminStatus = res.data[0].userStatus
}
})
},
fail: err => {
wx.showToast({
icon: 'none',
title: '用户信息获取失败,请检查网络',
})
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经受权,能够直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
this.setData({
avatarUrl: res.userInfo.avatarUrl,
nickName: res.userInfo.nickName,
userInfo: res.userInfo
})
}
})
}
}
})
}
)}
复制代码
- 在线联系功能:
1.在微信公众平台,客服中添加须要绑定的客服微信号.
2.在 button 组件中设置 open-type='contact' 便可打开客服消息.
3.而后在手机上搜索 ‘客服小助手’ ,绑定的的小程序就能够实如今线客服功能 .
这样就绑定好了客服😊