动态发布小程序
配置ColorUI
下载ColorUI到本地解压,复制ColorUI-master\demo\colorui
目录到项目根目录中。
在app.wxss
中导入全局外部CSS
@import "./colorui/main.wxss";
@import "./colorui/icon.wxss";
自定义导航栏
在app.json中取消系统导航栏
"window":{
"navigationStyle": "custom"
}
在app.js中获取系统信息
wx.getSystemInfo({
success: (result) => {
this.globalData.StatusBar = result.statusBarHeight;
let custom = wx.getMenuButtonBoundingClientRect();
this.globalData.Custom = custom;
this.globalData.CustomBar = custom.bottom + custom.top - result.statusBarHeight;
},
})
home.wxml首页导航栏试例
<cu-custom bgColor="bg-gradual-green" isBack="{{false}}">
<view slot="content">动态</view>
</cu-custom>
自定义底部导航栏
在app.json启用custom导航栏
"tabBar": {
"custom": true,
"list": [{
"pagePath": "pages/home/home",
"text": "首页"
},{
"pagePath": "pages/addmoment/addmoment",
"text": "分享动态"
}]
}
在项目根目录新建custom-tab-bar
文件夹
custom-tab-bar
目录结构
代码部分
custom-tab-bar/index.wxml
使用自定义底部导航栏tabbar
<view class="box">
<view class="cu-bar tabbar">
<view class="action {{selected === 0 ? \'active\' : \'default\'}}" data-index="0" bindtap="switchTab">
<view class="cuIcon-home"></view> 首页
</view>
<view class="action {{selected === 1 ? \'active\' : \'default\'}}" data-index="1" bindtap="switchTab">
<view class="cuIcon-share"></view> 分享
</view>
</view>
</view>
custom-tab-bar/index.js
Component({
properties: {
},
data: {
selected:0,
tabList:[
{
"pagePath": "pages/home/home",
},
{
"pagePath": "pages/addmoment/addmoment",
}
]
},
methods: {
switchTab(e){
//console.log(this.data)
let key = Number(e.currentTarget.dataset.index);
let tabList = this.data.tabList;
let selected = this.data.selected;
if(selected !== key){
this.setData({
selected:key
});
wx.switchTab({
url: `/${tabList[key].pagePath}`,
})
}
}
}
})
custom-tab-bar/index.json
{
}
custom-tab-bar/index.wxss
样式
/*自定义Component全局样式失效,手动引入*/
@import "../colorui/main.wxss";
@import "../colorui/icon.wxss";
.tabbar{
background-color: white;
}
.active{
color: orange;
}
.default{
color:rgb(51, 24, 24);
}
需要在home.js
和addmoment.js
中设置当前选中的Tab
home.js
// pages/home/home.js
Page({
onShow: function () {
this.tabBar();
},
tabBar(){
if(typeof this.getTabBar === \'function\' && this.getTabBar()){
this.getTabBar().setData({
//当前位于选中为首页
selected:0
})
}
},
})
addmoment.js
// pages/addmoment/addmoment.js
Page({
onShow: function () {
this.tabBar();
},
tabBar(){
if(typeof this.getTabBar === \'function\' && this.getTabBar()){
this.getTabBar().setData({
//当前位于选中为分享
selected:1
})
}
},
})
云开发数据集
- comments(评论)
- moments(动态)
权限
pages/auth/auth.wxml
<!--pages/auth/auth.wxml-->
<cu-custom bgColor="bg-gradual-pink">
<view slot="content">授权</view>
</cu-custom>
<view class="cu-bar padding margin-top flex justify-center">
<view class="padding-sm">
<view>
<open-data type="userAvatarUrl"></open-data>
</view>
</view>
</view>
<view class="padding bg-white margin-lr-xs solid-bottom">
<view class="text-black">该应用将获取以下授权并登录:</view>
<view class="text-grey">获取您的公开信息(昵称,头像,性别等)</view>
</view>
<view class="flex justify-center bg-white margin-lr-xs">
<button class="cu-btn bg-red padding-sm margin-sm" bindtap="refuseAuth">拒绝</button>
<button class="cu-btn bg-green padding-sm margin-sm" wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile">允许</button>
<button wx:else class="cu-btn bg-green padding-sm margin-sm" open-type="getUserInfo" bindgetuserinfo="getUserInfo">允许</button>
</view>
pages/auth/auth.js
// pages/auth/auth.js
Page({
/**
* 页面的初始数据
*/
data: {
canIUseGetUserProfile: false,
userInfo: {}
},
refuseAuth: function() {
wx.switchTab({
url: \'../home/home\',
})
},
getUserInfo: function(e) {
if(e.detail.userInfo) {
console.log("可用");
console.log(e.detail.userInfo);
wx.cloud.callFunction({
name: "getOpenId",
}).then(res => {
wx.setStorageSync("openid", res.result.openid);
})
wx.setStorageSync("userInfo", e.detail.userInfo);
wx.showToast({
title: \'授权成功...\',
icon: \'success\',
duration: 1500
})
} else {
console.log("获取信息失败")
}
wx.navigateBack({
delta: 1,
})
},
getUserProfile: function(e) {
wx.cloud.callFunction({
name: "getOpenId",
}).then(res => {
wx.setStorageSync("openid", res.result.openid);
})
wx.getUserProfile({
desc: "用于完善资料",
success: res => {
wx.setStorageSync(\'userInfo\', res.userInfo);
wx.showToast({
title: \'授权成功...\',
icon: \'success\',
duration: 1500
})
wx.navigateBack({
delta: 1,
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
if(wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
} else {
console.log("不可用")
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
首页
pages/home/home.wxml
<!--pages/home/home.wxml-->
<cu-custom bgColor="bg-gradual-pink" isBack="{{false}}">
<view slot="content">动态</view>
</cu-custom>
<view class="myPage">
<view wx:if="{{momentsList.length}}">
<block wx:for="{{momentsList}}" wx:key="this">
<view class="cu-card case dynamic no-card margin-tb radius">
<view class="cu-item shadow" data-id="{{item._id}}" bindtap="momentClick">
<view class="cu-list menu-avatar">
<view class="cu-item">
<view class="cu-avatar round lg" style="background-image: url({{item.avatarUrl}})">
</view>
<view class="content solid-bottom">
<view class="text-grey">{{item.publisher}}</view>
<view class="text-gray sm">{{item.time}}</view>
</view>
</view>
</view>
<view class="text-content">{{item.title}}</view>
<view class="grid flex-sub padding-lr">
<image style="width: 100%" src="{{item.imgUrl[0]}}" mode="aspectFill"></image>
</view>
<view class="text-gray text-sm text-right padding">
<text class="cuIcon-attentionfill margin-lr-xs"></text>{{item.views}}
<text class="cuIcon-appreciatefill margin-lr-xs"></text>{{item.appreciates}}
<text class="cuIcon-messagefill margin-lr-xs"></text>{{item.comment}}
</view>
</view>
</view>
</block>
</view>
<view class="cu-bar margin bg-gradual-green" wx:else>
<view class="content">没有动态,等你来分享</view>
</view>
</view>
pages/home/home.wxss
消除自定义底部导航栏的高度对页面高度造成的覆盖影响。
/* pages/home/home.wxss */
.myPage {
padding-bottom: calc(120rpx + env(safe-area-inset-bottom) / 2);
}
pages/home/home.js
// pages/home/home.js
const db = wx.cloud.database();
var util = require(\'../../utils/util.js\');
Page({
/**
* 页面的初始数据
*/
data: {
momentsList: {},
openid: ""
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var userInfo = wx.getStorageSync(\'userInfo\');
this.data.openid = wx.getStorageSync(\'openid\');
if(userInfo == "") {
wx.navigateTo({
url: \'../auth/auth\',
})
} else {
this.setData({
userInfo: userInfo
})
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.tabBar();
db.collection(\'moments\').orderBy(\'istop\', \'desc\').orderBy(\'submitdate\', \'desc\').get().then(res => {
for(var index in res.data) {
res.data[index].time = util.formatTime(res.data[index].submitdate);
let length = res.data[index].time.length;
res.data[index].time = res.data[index].time.replaceAll(\'/\', \'-\').slice(0, length-9);
res.data[index].views = res.data[index].view.length;
res.data[index].appreciates = res.data[index].appreciate.length;
}
this.setData({
momentsList: res.data
})
}).catch(err => {
console.log(err);
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
momentClick: function(e) {
// console.log(e.currentTarget.dataset.id)
let openid = this.data.openid;
// console.log(openid)
wx.cloud.callFunction({
name: \'moment\',
data: {
$url: "view_inc",
id: e.currentTarget.dataset.id,
openid: openid
}
}).then((res)=>{
})
wx.navigateTo({
url: \'../momentdetail/momentdetail?id=\' + e.currentTarget.dataset.id
})
},
tabBar(){
if(typeof this.getTabBar === \'function\' && this.getTabBar()){
this.getTabBar().setData({
selected:0
})
}
},
})
添加动态
pages/addnews/addnews.wxml
<!--pages/addnews/addnews.wxml-->
<cu-custom bgColor="bg-gradual-pink">
<view slot="content">添加动态</view>
</cu-custom>
<form>
<view class="cu-form-group margin-top">
<view class="title">
<text>*标题:</text>
</view>
<input bindinput="updateValue" data-name="title" placeholder="请输入标题"></input>
</view>
<view class="cu-form-group align-start">
<view class="title">
<text>*内容</text>
</view>
<textarea maxlength="-1" bindinput="updateValue" data-name="content" placeholder="请输入内容"></textarea>
</view>
<view class="cu-form-group">
<view class="title">
<text>是否置顶</text>
</view>
<switch class="cyan sm" bindchange="switchChange"></switch>
</view>
<view class="cu-bar bg-white margin-top">
<view class="action">
<text>图片上传</text>
</view>
<view class="action">
{{imgList.length}}/3
</view>
</view>
<view class="cu-form-group padding">
<view class="grid col-3 grid-square flex-sub">
<view class="bg-img" wx:for="{{imgList}}" wx:key="this" bindtap="ViewImage" data-url="{{imgList[index]}}">
<image src="{{imgList[index]}}" mode="aspectFill"></image>
<view class="cu-tag bg-red" catchtap="DelImg" data-id="{{index}}">
<text class="cuIcon-close"></text>
</view>
</view>
<view class="solids" bindtap="ChooseImage" wx:if="{{imgList.length<3}}">
<text class="cuIcon-cameraadd"></text>
</view>
</view>
</view>
</form>
<view class="cu-btn-group padding flex justify-center">
<button class="basis-sm cu-btn bg-green shadow margin-sm" bindtap="submitform">发布</button>
</view>
pages/addnews/addnews.js
// pages/addnews/addnews.js
var util = require(\'../../utils/util.js\');
const db = wx.cloud.database();
Page({
/**
* 页面的初始数据
*/
data: {
imgList: [],
momentInfo: {istop: 0},
userInfo: {}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
this.tabBar();
var userInfo = wx.getStorageSync(\'userInfo\');
if(userInfo == "") {
wx.navigateTo({
url: \'../auth/auth\',
})
} else {
this.setData({
userInfo: userInfo
})
}
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
switchChange: function(e) {
let momentInfo = this.data.momentInfo;
if(e.detail.value == true) {
momentInfo.istop = 1;
} else {
momentInfo.istop = 0;
}
this.setData({
momentInfo: momentInfo
})
},
updateValue: function(e) {
let name = e.currentTarget.dataset.name;
let momentInfo = this.data.momentInfo;
momentInfo[name] = e.detail.value;
this.setData({
momentInfo: momentInfo
})
},
ChooseImage: function() {
wx.chooseImage({
count: 3,
sizeType: [\'original\', \'compressed\'],
sourceType: [\'album\'],
success: (res) => {
wx.showLoading({
title: \'图片上传中...\',
})
var time = util.formatTime(new Date());
console.log(time);
var FilePaths = [];
const temFilePaths = res.tempFilePaths;
let promiseArr = [];
for(let i = 0; i < temFilePaths.length; i++) {
let promise = new Promise((resolve, reject) => {
var randstring = Math.floor(Math.random() * 1000000).toString() + \'.png\';
randstring = time + \'-\' + randstring;
console.log(randstring);
wx.cloud.uploadFile({
cloudPath: \'newImages/\' + randstring,
filePath: temFilePaths[i],
success: res => {
console.log(res.fileID);
FilePaths[i] = res.fileID,
resolve(res)
},
fail: err => {
reject(error);
}
})
})
promiseArr.push(promise);
}
Promise.all(promiseArr).then((result) => {
if(this.data.imgList.length != 0) {
this.setData({
imgList: this.data.imgList.concat(FilePaths)
})
} else {
this.setData({
imgList: FilePaths
})
}
wx.hideLoading({
success: (res) => {},
})
})
}
})
},
ViewImage: function(e) {
wx.previewImage({
urls: this.data.imgList,
current: e.currentTarget.dataset.url
})
},
DelImg: function(e) {
console.log(e.currentTarget.dataset.id);
var id = e.currentTarget.dataset.id;
var imgList = this.data.imgList;
wx.cloud.deleteFile({
fileList: [imgList[id]]
}).then(res => {
imgList.splice(id, 1);
this.setData({
imgList: imgList
})
console.log(res.fileList)
}).catch(error => {
})
},
submitform: function(e) {
let momentInfo = this.data.momentInfo;
let userInfo = this.data.userInfo;
if(momentInfo.title && momentInfo.content) {
db.collection(\'moments\').add({
data: {
title: momentInfo.title,
content: momentInfo.content,
publisher: userInfo.nickName,
imgUrl: this.data.imgList,
avatarUrl: userInfo.avatarUrl,
submitdate: db.serverDate(),
istop: momentInfo.istop,
comment: 0,
appreciate: {length: 0, people: []},
view: {length:0, people: []}
}
}).then(wx.reLaunch({
url: \'../home/home\',
}))
} else {
wx.showToast({
title: \'检查内容\',
icon: "none",
duration: 1500
})
}
},
tabBar(){
if(typeof this.getTabBar === \'function\' && this.getTabBar()){
this.getTabBar().setData({
selected:1
})
}
}
})
查看、点赞的云函数
cloudfunctions\moment\index.js
const cloud = require(\'wx-server-sdk\');
cloud.init();
const TcbRouter = require(\'tcb-router\');
const db = cloud.database();
const _ = db.command;
exports.main = async(event, context) => {
const app = new TcbRouter({event});
app.router(\'view_inc\', async(ctx, next) => {
console.log("增加")
try {
db.collection(\'moments\').where({
_id: _.eq(event.id),
view: {
people: _.elemMatch(_.eq(event.openid))
}
}).get().then(res => {
if(res.data.length == 0) {
return db.collection(\'moments\').doc(event.id).update({
data: {
view: {
people: _.push(event.openid),
length: _.inc(1)
}
}
})
}
})
} catch(e) {
console.log(e)
}
await next();
})
app.router(\'appreciate_inc\', async(ctx, next) => {
try {
db.collection(\'moments\').where({
_id: _.eq(event.id),
appreciate: {
people: _.elemMatch(_.eq(event.openid))
}
}).get().then(res => {
if(res.data.length == 0) {
return db.collection(\'moments\').doc(event.id).update({
data: {
appreciate: {
people: _.push(event.openid),
length: _.inc(1)
}
}
})
}
})
} catch(e) {
console.log(e)
}
await next();
})
app.router(\'comment_inc\', async(ctx, next) => {
try {
return db.collection(\'moments\').doc(event.id).update({
data:{
comment: _.inc(1)
}
})
} catch(e) {
console.log(e)
}
await next();
})
return app.serve();
}
修复问题
由于自定义组件不能使用ID,属性等选择符,将custom-tab-bar/index.wxss
文件引入的外部样式表做相应的修改。
源文件
@import "../colorui/main.wxss"; @import "../colorui//icon.wxss"; .tabbar { background-color: white; } .active { color: orange; } .default { color: rgb(51, 24, 24); }
修改后
.tabbar { background-color: white; } .active { color: orange; } .default { color: rgb(51, 24, 24); } .cu-bar { display: flex; position: relative; align-items: center; min-height: 100rpx; justify-content: space-between; } .cu-bar .action { display: flex; align-items: center; height: 100%; justify-content: center; max-width: 100%; } .cu-bar.tabbar .action .cuIcon-home, .cu-bar.tabbar .action .cuIcon-edit { width: 100rpx; position: relative; display: block; height: auto; margin: 0 auto 10rpx; text-align: center; font-size: 40rpx; } .cu-bar.tabbar { padding: 0; height: calc(100rpx + env(safe-area-inset-bottom) / 2); padding-bottom: calc(env(safe-area-inset-bottom) / 2); } .cu-bar.tabbar .action { font-size: 22rpx; position: relative; flex: 1; text-align: center; padding: 0; display: block; height: auto; line-height: 1; margin: 0; overflow: initial; } .cuIcon-home:before { content: "\e6b8"; } .cuIcon-edit:before { content: "\e649"; }
全部改为使用class选择器。
请发表评论