自学项目笔记【帖子主页面】【个人主页】【发布页面】云开发
1、【主页】放帖子(包括分类)
index.js
const util = require("./../../../utils/util.js");
const http = require("./../../../utils/http.js");
const app = getApp()
wx.cloud.init()
const db = wx.cloud.database();
const posts = db.collection('posts')
Page({
data: {
formattedTime: '',
imgUrls :[],
show_auth:false,
userInfo: {
avatarUrl: 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLfibIwL69rkQFg61JCOhjZhAgAxlG4cLGKkl0XsUoMyItJDFHdlCukicog5fNq9z5XhauVuicdVXEDg/0',
nickName: '',
},
hasUserInfo: false,
praiseBorder: '',
notPraiseBorder: '',
posts: [],
postType: 1,
baseImageUrl: app.globalData.imageUrl,
show: 0,
hidden: false,
showCommentInput: false,
showCommentInput: false,
commentContent: '',
commentObjId: '',
commentType: '',
refcommentId: '',
filter:'',
pageSize: 10,
pageNumber: 1,
initPageNumber: 1,
showGeMoreLoadin: false,
currentTime: '',
notDataTips: false,
newMessage: false,
newMessageNumber: 0,
select: 1,
animationData: {},
commentValue: '',
showNormal: false,
showAudit: false,
topic:'',
showTopic:false,
showSelect: false,
showBegin: true,
showCancel: false,
showReport: false,
bindReport: false,
showSubmit: false,
showSearch:false,
tryAgant: false,
imageLeft: '',
imageRight: '',
postImageLeft: '',
PostImageRight: '',
rate: 0,
face: '',
conclusion: '',
canComment:true,
sharecomeIn:false,
shareId:'',
shareType:'',
param:app.globalData.param,
},
//获取帖子数据 index.js
onLoad: function(options) {
this.getDataFromCloud();//获取帖子数据
this.getUploadedImgUrls(); // 获取图片链接数据
this.showAllPosts(); // 初始化页面时显示所有帖子(全部时默认初始化显示全部帖子)
this.getPostsUser();
},
getDataFromCloud: function() {
const collection = db.collection('content');
collection.orderBy('ttime', 'desc').get().then((res) => {
const posts = res.data.map((item) => {
const created_at = this.formatTime(item.ttime); // 格式化发布时间
return {
...item,
created_at
};
});
this.setData({
posts: posts,
});
}).catch((error) => {
console.error('获取数据失败', error);
});
},
formatTime: function(timestamp) {
const date = new Date(timestamp);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
let minute = date.getMinutes();
if (minute < 10) {
minute = '0' + minute; // 在分钟前添加零
}
return `${year}-${month}-${day} ${hour}:${minute}`;
},
getUploadedImgUrls: function() {
const collection = db.collection('content');
collection.get().then((res) => {
const uploadedImgUrls = res.data.map((item) => item.imgUrls);
this.setData({
uploadedImgUrls: uploadedImgUrls
});
}).catch((error) => {
console.error('获取图片链接数据失败', error);
});
},
showAllPosts() {
const collection = db.collection('content');
collection.orderBy('ttime', 'desc').get().then((res) => {
const posts = res.data.map((item) => {
const created_at = this.formatTime(item.ttime); // 格式化发布时间
return {
...item,
created_at
};
});
this.setData({
posts: posts
});
}).catch((error) => {
console.error('获取数据失败', error);
});
},
getPostsUser: function() {
// 获取帖子数据
db.collection('content').orderBy('ttime', 'desc').get().then((res) => {
const posts = res.data.map((item) => {
const created_at = this.formatTime(item.ttime); // 格式化发布时间
return {
...item,
created_at
};
});
this.setData({
posts: posts
});
// 获取帖子对应的用户信息
posts.forEach((post, index) => {
const userId = post._openid;
db.collection('users').where({
_openid: userId
}).get().then((res) => {
const userInfo = res.data[0];
const updatedPosts = this.data.posts;
updatedPosts[index].userInfo = userInfo;
this.setData({
posts: updatedPosts
});
}).catch((error) => {
console.error('获取用户信息失败', error);
});
});
}).catch((error) => {
console.error('获取帖子数据失败', error);
});
},
toggleExpand(e) {
const index = e.currentTarget.dataset.index;
const item = this.data.posts[index];
item.isExpanded = !item.isExpanded;
this.setData({
posts: this.data.posts
});
},
onShow: function (option) {
if (app.globalData.reloadHome == true){
app.globalData.reloadHome = false;
this.setData({
pageNumber: this.data.initPageNumber,
posts: []
});
this.getPost();
}
let type = 0;
http.getNewInbox(type, res=>{
if (res.data.data != 0 && res.data.data != null && res.data.data != '') {
this.setData({
newMessage: true,
newMessageNumber: res.data.data
});
} else {
this.setData({
newMessage: false,
newMessageNumber: 0
});
}
});
},
/*点赞话题*/
praiseTopic: function (e) {
let id = e.currentTarget.dataset.id;
http.post('/praise/'+id+'/topic', {}, function (res) {
this.setData({topic:res.data.data});
});
},
/*分享*/
onShareAppMessage: function (res) {
return {
title: 'hi,同学,有人跟你表白了',
path: '/pages/home/index/index',
imageUrl:'https://img.wx-union.cn/share.jpg',
success: function (res) {
// 转发成功
},
fail: function (res) {
// 转发失败
}
}
},
onShareTimeline: function (res) {
return {
title: 'hi,同学,有人跟你表白了',
path: '/pages/home/index/index',
imageUrl:'https://img.wx-union.cn/share.jpg',
success: function (res) {
// 转发成功
},
fail: function (res) {
// 转发失败
}
}
},
/*获取具体类型的贴子*/
selected(event) {
const type = event.currentTarget.dataset.type;
// 更新选中状态
this.setData({
select: type
});
// 根据选中的选项卡执行相应的操作
switch (type) {
case '1': // 执行全部选项卡的操作
this.showAllPosts();
break;
case '2': // 执行关注选项卡的操作
this.showPostsByTag('关注');
break;
case '3': // 执行求问选项卡的操作
this.showPostsByTag('求问');
break;
case '4': // 执行交友选项卡的操作
this.showPostsByTag('交友');
break;
case '5': // 执行树洞选项卡的操作
this.showPostsByTag('树洞');
break;
default: // 默认情况下执行全部选项卡的操作
this.showAllPosts();
break;
}
},
showPostsByTag(tag) {
const collection = db.collection('content');
collection.where({
tag: tag
}).orderBy('ttime', 'desc').get().then((res) => {
this.setData({
posts: res.data
});
}).catch((error) => {
console.error('获取数据失败', error);
});
},
/*搜索*/
search:function(){
this.setData({
postType: 1,
posts: []
})
this.setData({
pageNumber: this.data.initPageNumber
});
wx.showLoading({
title: '搜索中...',
});
this.getPost();
},
/*进入新消息列表*/
openMessage: function () {
wx.navigateTo({
url: '/pages/personal/message/message?type=0&new_message=1'
})
},
/*下拉刷新,获取最新的贴子*/
onPullDownRefresh: function () {
this.setData({
pageNumber: this.data.initPageNumber,
posts:[]
});
this.getPost();
},
/*上拉加载更多*/
onReachBottom: function () {
this.setData({
showGeMoreLoadin: true
});
this.getPost();
},
/*获取用户信息*/
getUserInfo: function (e) {
app.globalData.userInfo = e.detail.userInfo//用户信息存到全局数据对象app.globalData.userInfo 中
this.setData({//调用setData方法,将用户信息更新到页面数据,从而实现在页面上展示
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
/*预览图片*/
previewImage(event) {
const imageUrl = event.currentTarget.dataset.src;
wx.previewImage({
current: imageUrl,
urls: [imageUrl],
});
},
/* 显示评论控制面板*/
showComment: function (event) {
this.setData({
show: 0
});
let id = event.target.id;
let hidden = event.target.dataset.show;
if (!hidden) {
this.setData({
show: id,
hidden: true
});
} else {
this.setData({
show: 0,
hidden: false
});
}
},
/*触摸屏幕后移动触发一些隐藏操作*/
hiddenComment: function () {
console.log('inde-hiddenComment:触摸后移动');
this.setData({
show: 0,
hidden: false,
showCommentInput: false
});
},
/*点赞*/
praise: function (event) {
let objId = event.target.dataset.obj;
let objType = 1;
this.setData({
show: 0,
hidden: false,
showCommentInput: false
});
http.post(`/praise`,{ obj_id: objId, obj_type: objType }, res => {
let postList = this.data.posts;
let newPostList = postList.map(item => {
if (objId == item.id) {
item.praises.push(res.data.data);
}
return item;
});
//重新赋值,更新数据列表
this.setData({
posts: newPostList
});
});
},
/*激活评论框*/
showCommentInput: function (event) {
let objId = event.target.dataset.objid;
let type = event.target.dataset.objtype;
this.setData({
commentObjId: objId,
commentType: type,
show: 0,
hidden: false,
showCommentInput: true
});
},
/*获取评论框的输入内容*/
getCommentContent: function (event) {
let content = event.detail.value;
this.setData({
commentContent: ''
})
this.setData({
commentContent: content
})
},
/*获取搜索框的内容*/
getFilter: function (event){
let content = event.detail.value;
this.setData({
filter: content
})
},
/*提交评论*/
sendComment: function (e) {
if (!this.data.canComment){
return false;
}
this.setData({ canComment: false })
wx.showLoading({
title: '发送中',
});
let content = this.data.commentContent;
let objId = this.data.commentObjId;
let type = this.data.commentType;
let refcommentId = this.data.refcommentId;
if (content == '') {
wx.showToast({
title: '内容不能为空',
icon: 'none'
})
this.setData({ canComment:true})
return false;
}
http.post('/comment', {
content: content,
obj_id: objId,
type: type,
ref_comment_id: refcommentId
}, res=> {
this.setData({ canComment:true})
wx.hideLoading();
this.setData({
commentContent: '',
commentObjId: '',
commentType: '',
showCommentInput: false,
refcommentId: ''
})
let postList = this.data.posts;
let newPostList = postList.map(item => {
if (objId == item.id) {
item.comments.push(res.data.data);
}
return item;
});
//重新赋值,更新数据列表
this.setData({
posts: newPostList
});
});
},
/*回复别人*/
commentOtherComment: function (e) {
let objId = e.currentTarget.dataset.objid;
let type = e.currentTarget.dataset.objtype;
let refcommentId = e.currentTarget.dataset.refid;
this.setData({
commentObjId: objId,
commentType: type,
show: 0,
hidden: false,
showCommentInput: true,
refcommentId: refcommentId
});
},
/* 删除评论*/
deleteComment: function (e) {
let objId = e.currentTarget.dataset.objid;
let commentId = e.currentTarget.dataset.refid;
wx.showModal({
title: '提示',
content: '确认删除该评论?',
success: res=> {
if (res.confirm) {
http.httpDelete(`/delete/${commentId}/comment`, {}, res => {
if (res.data.data == 1) {
let newPostList = this.data.posts.map(item => {
if (objId == item.id) {
let newComment = item.comments.filter((item, index) => {
if (item.id != commentId) {
return item;
}
});
item.comments = newComment;
}
return item;
});
this.setData({
posts: newPostList
});
}
});
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
/*删除帖子*/
deletePost: function (e) {
let objId = e.target.id;
wx.showModal({
title: '提示',
content: '确定删除吗?',
success: res=> {
if (res.confirm) {
http.httpDelete(`/delete/${objId}/post`, {}, res => {
let result = res.data.data;
if (result == 1) {
let newPosts = this.data.posts.filter((item, index) => {
if (item.id != objId) {
return item;
}
});
this.setData({
posts: newPosts
});
}
});
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
},
/*跳转到私信*/
letter: function (e) {
let id = e.target.dataset.obj;
let canChat = e.target.dataset.chat;
wx.navigateTo({
url: '/pages/personal/letter/letter?friend_id=' + id + '&can_chat=' + canChat
})
},
/* 关注*/
follow: function (e) {
let objId = e.target.dataset.obj;
http.post('/follow', {obj_id: objId,obj_type: 1}, res=> {
let follow = res.data.data;
let post = this.data.posts;
let newPost = post.map(item => {
if (item.id == follow.obj_id) {
item.follow = true;
}
return item;
});
this.setData({
posts: newPost
});
});
},
/* 取消关注*/
cancelFolllow: function (e) {
let objId = e.target.dataset.obj;
http.put(`/cancel/${objId}/follow/1`, {},res=> {
let follow = res.data.data;
let post = this.data.posts;
let newPost = post.map(item => {
if (item.id == objId) {
item.follow = false;
}
return item;
});
this.setData({
posts: newPost
});
});
},
topic:function(){
http.get(`/topic`, {}, res=> {
if(res.data.data){
let topicShow = res.data.data != null ? true : false;
this.setData({ topic: res.data.data, showTopic: topicShow });
}
});
},
openTopic:function(e){
let id = e.currentTarget.dataset.id;
wx.navigateTo({
url: '/pages/home/topic_detail/topic_detail?id=' + id
})
}
})
index.wxml
<!--index.wxml-->
<view class='all-container'>
<view class='page_row' bindtap="suo" style="width: 750rpx; height: 73rpx; display: flex; box-sizing: border-box; left: 0rpx; top: 0rpx; position: fixed">
<view class="search" style="width: 736rpx; height: 59rpx; display: block; box-sizing: border-box; position: relative; left: 0rpx; top: 8rpx">
<view class="df search_arr" style="width: 638rpx; height: 52rpx; display: block; box-sizing: border-box">
<icon class="searchcion" size='16' type='search' style="position: absolute; left: 401rpx; top: -2rpx"></icon>
<input style="width: 486rpx; height: 36rpx; display: flex; box-sizing: border-box; position: relative; left: -61rpx; top: -8rpx" class="sousuo" disabled placeholder="搜索" bindtap='/pages/search/search'/>
</view>
</view>
</view>
<view class="container" bindtouchmove="hiddenComment">
<!-- 选择卡 -->
<view class='nav-bar-container' style="position: fixed; left: -1rpx; top: 64rpx">
<view class='nav-bar'>
<view class='all {{select==1?"selected":""}}'
bindtap="selected"
data-type="1">全部</view>
<view class='follow {{select==2?"selected":""}}'
bindtap="selected"
data-type='2'>关注</view>
<view class='hot {{select==4?"selected":""}}'
bindtap="selected"
data-type='4'>交友</view>
<view class='new {{select==5?"selected":""}}'
bindtap="selected"
data-type='5'>树洞</view>
<view class='new {{select==3?"selected":""}}'
bindtap="selected"
data-type='3'>求问</view>
</view>
</view>
<view class='message-tip'
wx:if="{{newMessage}}"
bindtap='openMessage'>
<view class='tip-content'>
<view>远方飘来{{newMessageNumber}}条新消息</view>
</view>
</view>
<view class="container-wall" >
<view class='search-container' wx:if="{{showSearch}}"></view>
<view style="width: 750rpx; height: 64rpx; display: block; box-sizing: border-box"></view>
<view class="wall-item" wx:for="{{posts}}" wx:key="posts">
<view class="item-container">
<!-- 头像 -->
<view class="item-image">
<image bindtap='letter'
id="{{item.poster.avatar}}"
src="{{item.poster.avatar}}"
wx:if="{{item.private == 0}}"
data-obj="{{item.poster.id}}"
data-chat="{{item.private}}"
></image>
<image bindtap=''
src="/image/boy-icon.png"
wx:elif="{{item.private == 1 && item.poster.gender == 1}}"></image>
<image bindtap=''
src="/image/girl-icon.png"
wx:else></image>
</view>
<view hidden="{{!postsVisible}}" class="item-content">
<view class="user-name" style="width: 598rpx; height: 40rpx; display: flex; box-sizing: border-box">
<view wx:if="{{item.private == 0}}">
<view class='nickname'>{{item.poster.nickname}}</view>
</view>
<view wx:if="{{item.private == 1}}" class='nickname'>树洞</view>
<view class='follow-icon'
wx:if="{{!item.follow}}">
<view class='follow-world' data-obj="{{item.id}}" bindtap="follow">收藏</view>
</view>
<view class='had-follow'
wx:if="{{item.follow}}">
<view bindtap="cancelFolllow" data-obj="{{item.id}}" class='had-follow-world'>取消收藏</view>
</view>
</view>
<view class='for-user'
wx:if="{{item.topic != '无'}}">
<view style="width: 591rpx; height: 40rpx; display: block; box-sizing: border-box">表白@{{item.topic}}</view>
</view>
<!-- 帖子内容+图片 -->
<view wx:key="index">
<view class="post">
<text selectable class="content" wx:if="{{!isExpanded && item.content.length > 88}}" bindtap="toggleExpand" style="display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;">{{item.content}}</text>
<text selectable class="content" wx:else>{{item.content}}</text>
<text class="expand" wx:if="{{item.content.length > 88}}" bindtap="toggleExpand">{{isExpanded ? '收起' : '展开'}}</text>
<view class="image-list" style="display: flex; flex-wrap: wrap;">
<view wx:for="{{item.imgUrls}}" wx:key="index" style="width: 33.33%;">
<image src="{{item}}" mode="aspectFill" bindtap="previewImage" data-src="{{item}}" style="width: 80px; height: 80px;"></image>
</view>
</view>
</view>
</view>
<!-- 展示了用户学院信息 -->
<view class='user-college' wx:if="{{item.show_college}}">
<view>{{item.college}}</view>
</view>
<view class="post-time">
<view class='time-and-delete'>
<view>{{item.created_at}}</view>
<view class='delete-post'
id="{{item.id}}"
wx:if="{{item.can_delete}}"
bindtap='deletePost'>删除</view>
</view>
<view class='comment-container'>
<!-- 留言、点赞二合一按钮 -->
<view class='comment-icon-container'>
<image style='width:60rpx;height:60rpx'
src="/image/zan1.png"
bindtap="praise"
data-obj="{{item.id}}">
</image>
</view>
<view class='comment-icon-container'>
<image style='width:60rpx;height:60rpx;margin-left:40rpx'
src="/image/my-message.png"
bindtap="showCommentInput"
data-objid="{{item.id}}"
data-objtype='1'>
</image>
</view>
</view>
</view>
<view class="comment"
wx:if="{{item.praises.length > 0 || item.comments.length > 0}}" style="height: max-content; width: auto">
<view class="qipao"></view>
<view class="comment-detail">
<view class="praise-container"
wx:if="{{item.praises.length > 0}}">
<view class='praise-content'>
<image class='praise-user praise-item'
src='/image/ilike.png'></image>
<view class='praise-item'
wx:for="{{item.praises}}"
wx:key="{{item.praises}}">
<view class='praise-item-sub'>
<view>
<image class='praise-user-avatar'
src='{{item.avatar}}'></image>
</view>
<view class='praise-user-name'>
{{item.nickname}}
</view>
</view>
</view>
</view>
</view>
<view class='line'
wx:if="{{item.comments.length > 0 && item.praises.length > 0}}">
</view>
<view class='comment-user-wall'
wx:if='{{item.comments.length > 0}}'>
<view class='comment-user-container'
wx:for="{{item.comments}}"
wx:key="{{item.comments}}" wx:for-item="sub">
<view class='comment-wall-item'
bindtap="{{sub.can_delete?'deleteComment':'commentOtherComment'}}"
data-objid="{{item.id}}"
data-refid="{{sub.id}}"
data-objtype='1'>
<view class='comment-user-container' wx:if="{{!sub.ref_comment}}">
<view class="comment-user inline-item">
{{sub.commenter.nickname}}:
</view>
<view class='inline-item'>{{sub.content}}</view>
</view>
<view class='comment-user-container'
wx:if="{{sub.ref_comment}}">
<view class="comment-user inline-item">
{{sub.commenter.nickname}}
</view>
<view class="inline-item">回复</view>
<view class="comment-user inline-item">
{{sub.ref_comment.refCommenter.nickname}}:
</view>
<view class='inline-item'>{{sub.content}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<get-more-loading wx:if="{{showGeMoreLoadin}}"></get-more-loading>
<not-more wx:if="{{notDataTips && posts.length != 0}}"></not-more>
</view>
<view class='comment-input-container' wx:if="{{showCommentInput}}">
<textarea placeholder="评论"
auto-focus
maxlength="1024"
cursor-spacing="15"
fixed="true"
auto-height
bindinput='getCommentContent'/>
<view class='send-button' bindtap='sendComment'><view>发送</view></view>
</view>
</view>
2、【个人主页】
"pages/personal/index/personal",
personal.js
const app = getApp();
const http = require("./../../../utils/http.js");
Page({
data: {
user: '',
newLetterNumber: 0,
serviceId: '',
param: app.globalData.param,
isFollowed: false,
userInfo: {
avatarUrl: 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLfibIwL69rkQFg61JCOhjZhAgAxlG4cLGKkl0XsUoMyItJDFHdlCukicog5fNq9z5XhauVuicdVXEDg/0',
nickName: '点击登录',
school: '某某大学',
signature: 'My Signature',//个性签名
major: 'Computer Science',//专业
grade: '2019',
fans: 100,
follows: 50,
likes: 200,
collects: 150
},
islogin: false, //声明一个变量,默认为false,一旦登录成功,改为true
posts: [
{
imgUrl: 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLfibIwL69rkQFg61JCOhjZhAgAxlG4cLGKkl0XsUoMyItJDFHdlCukicog5fNq9z5XhauVuicdVXEDg/0',
title: '校园墙帖子1',
content: '这是校园墙的第一个帖子'
},
{
imgUrl: 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLfibIwL69rkQFg61JCOhjZhAgAxlG4cLGKkl0XsUoMyItJDFHdlCukicog5fNq9z5XhauVuicdVXEDg/0',
title: '校园墙帖子2',
content: '这是校园墙的第二个帖子'
},
{
imgUrl: 'https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLfibIwL69rkQFg61JCOhjZhAgAxlG4cLGKkl0XsUoMyItJDFHdlCukicog5fNq9z5XhauVuicdVXEDg/0',
title: '校园墙帖子3',
content: '这是校园墙的第三个帖子'
}
],
backgroundImg: 'cloud://cloud1-4glym37a786982ed.636c-cloud1-4glym37a786982ed-1319126137/imgList/帖子/26.98490775741331.png' ,// 默认背景图
showLoginButton: app.globalData.authStatus
},
//点击登录后执行
handleTapLogin() {
if (this.data.islogin) {
return;
}
wx.getUserProfile({
desc: '获取用户信息用于维护用户权益',
success: (res) => {
console.log('获取用户信息', res)
this.setData({
islogin: true,
userInfo: res.userInfo
});
this.login();
}
});
},
login() {
let db = wx.cloud.database();
db.collection('users').get().then(res => {
console.log('查询当前用户', res);
if (res.data.length == 0) {
console.log('没有查到用户', res);
this.regist();
wx.removeStorageSync('userInfo');//删除本地缓存中的用户信息
} else {
console.log('查到了用户', res);
let userInfo = res.data[0];
// 对性别字段进行映射转换
switch (userInfo.gender) {
case 0:
userInfo.gender = '未知';
break;
case 1:
userInfo.gender = '男性';
break;
case 2:
userInfo.gender = '女性';
break;
default:
// 如果userInfo.gender的值不是0、1或2,保持原值不变
break;
}
this.setData({ userInfo });
wx.setStorageSync('userInfo', userInfo); // 将用户信息存储到本地缓存
}
});
},
regist() {
let db = wx.cloud.database();
db.collection('users').add({
data: this.data.userInfo,
success: (res) => {
console.log('注册用户', res);
wx.setStorageSync('userInfo', this.data.userInfo); // 将用户信息存储到本地缓存
}
});
},
onShow: function () {
//this.newLetterCount();
this.checkLogin();
const userInfo = wx.getStorageSync('userInfo');
if (userInfo) {
this.setData({
islogin: true,
userInfo: userInfo
});
this.login();
}
},
handleTapAvatar() {//点击头像
wx.showActionSheet({
itemList: ['更换头像', '查看头像'],
success: res => {
const index = res.tapIndex;
if (index === 0) {
this.chooseImage(); // 调用选择图片的方法
} else if (index === 1) {
this.previewImage(); // 调用预览头像的方法
}
},
fail: err => {
console.log('选择失败', err);
}
});
},
previewImage() {
const userInfo = this.data.userInfo;
const path = userInfo.avatarUrl;
wx.previewImage({
urls: [path],
current: path,
fail: err => {
console.log('预览失败', err);
}
});
},
chooseImage(){
if (!this.data.islogin) {
wx.showToast({
title: '请先登录',
icon: 'none',
duration: 2000
});
return;
}
//选择图片
wx.chooseMedia({
count:1,
midiaType: ["image"],
success: (res)=>{
console.log('选择图片',res)
let path = res.tempFiles[0].tempFilePath
let userInfo = this.data.userInfo
userInfo.avatarUrl = path //用户信息头像路径改了
this.setData({ userInfo })//更新userInfo用户信息
//将图片上传到云存储空间 更新数据库持久化保存
this.upload(path)//调一个方法
}
})
},
upload(path){//上传文件 path:待上传的图片路径 ,path是形参
//需要通过当前文件的路径,生成一个随机文件名,存储在云端
let ext = path.substring(path.lastIndexOf('.')) //从.开始截取,截取到jpg
let cPath = 'imgList/头像/' + Math.random() + ext // 拼接文件夹路径//Math.random()生成随机数 然后拼接jpg
wx.cloud.uploadFile({
filePath: path, //云空间的图片路径, 需要随机生成
cloudPath: cPath, //本地需要上传的文件的路径
success: (res)=>{
console.log('上传图片',res)
//获取头像的路径
let fileID = res.fileID
//通过用户id,修改用户头像
this.updateAvatarUrl(fileID)//封装一个方法
// 更新页面中的头像展示
let userInfo = this.data.userInfo
userInfo.avatarUrl = fileID
this.setData({ userInfo })
}
})
},
updateAvatarUrl(fileID){ //更新用户id,更新用户的头像路径
let db = wx.cloud.database()
let id = this.data.userInfo._id
db.collection('users').doc(id).update({
data: {
avatarUrl:fileID
},
success: (res)=>{
console.log('头像修改成功',res)
// 更新页面中的头像展示
let userInfo = this.data.userInfo
userInfo.avatarUrl = fileID
this.setData({ userInfo })
}
})
},
toggleFollow() {
this.setData({
isFollowed: !this.data.isFollowed,
});
},
onLoad: function () {
this.checkAuth();
let userStorage = wx.getStorageSync('user');
if (userStorage){
this.setData({
user: userStorage
})
}
this.setData({ param: app.globalData.param })
this.getPersonalInfo();
//this.newLetterCount();
this.getService();
},
changeBackground: function() {
wx.chooseImage({
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
this.setData({
backgroundImg: tempFilePath
});
}
});
},
changeNickname: function() {
// 调用微信输入框 API,接收输入的昵称
// 发送新的昵称至服务器
// 响应成功后更新昵称
// this.setData({
// 'userInfo.nickname': newNickname
// });
},
changeSignature: function() {
// 调用微信输入框 API,接收输入的签名
// 发送新的签名至服务器
// 响应成功后更新签名
// this.setData({
// 'userInfo.signature': newSignature
// });
},
// ... 其它的函数
changeAvatar() {
// 调用微信选择图片 API,选择新的头像图片并上传至服务器
// ...
// 更新头像 URL
this.setData({
'userInfo.avatarUrl': newAvatarUrl
});
},
// onShow: function () {
// //this.newLetterCount();
// this.checkLogin();
// },
checkLogin:function(){
http.post(`/check_login`, {}, res => {
if (res.data.error_code == '5000') {
app.globalData.authStatus = true;
this.setData({
showLoginButton : true
})
}
});
},
/**
* 是否授权
*/
checkAuth:function(){
let that = this;
if (wx.getUserProfile) {
this.setData({
showLoginButton: false
})
that.getPersonalInfo()
}
},
/**
* 获取客服id
*/
getService: function () {
http.get(`/service`, {}, res => {
console.log('客服id:' + res.data.data);
this.setData({
serviceId: res.data.data
});
});
},
/**
* 获取个人信息
*/
getPersonalInfo() {
http.get(`/personal_info`, {}, res => {
console.log("getPersonalInfo");
console.log(res.data.data);
this.setData({
user: res.data.data
})
wx.setStorageSync('user', res.data.data);
});
},
/**
* 获取未读私信数量
*/
newLetterCount: function () {
http.get(`/new_messages`, {}, res => {
console.log(res.data.data);
if (res.data.data != null) {
this.setData({
newLetterNumber: res.data.data
})
}
});
},
/**
* 进入消息列表
*/
openMessage: function () {
wx.navigateTo({
url: '/pages/personal/message/message?type=0&new_message=0'
})
},
/**
* 进入私信列表
*/
openLetter: function () {
wx.navigateTo({
url: '/pages/personal/friends/friends'
})
},
/**
* 进入建议留言列表
*/
openSugesstion: function () {
let id = this.data.serviceId;
console.log('客服id' + id);
wx.navigateTo({
url: '/pages/personal/letter/letter?friend_id=' + id
})
},
/**
* 进入表白墙列表
*/
opendPostList: function () {
wx.navigateTo({
url: '/pages/personal/post_list/post_list'
})
},
/**
* 进入卖舍友列表
*/
openSaleList: function () {
wx.navigateTo({
url: '/pages/personal/sale_list/sale_list'
})
},
/**
* 进入匹配列表
*/
openMatchList: function () {
wx.navigateTo({
url: '/pages/help/help_single/help_single'
})
},
updateInfo: function () {
wx.navigateTo({
url: '/pages/personal/set_profile/set_profile'
})
},
/**
* 监听用户点击授权按钮
*/
getAuthUserInfo: function (data) {
this.setData({
showLoginButton: false
});
http.login(null, null, null, res => {
this.getPersonalInfo();
});
},
})
personal.wxml
<view class="personal-container">
<view class="bg-container" style="width: 750rpx; height: 336rpx; display: block; box-sizing: border-box; left: 0rpx; top: 0rpx">
<image class="background-img" src="{{backgroundImg}}" mode="aspectFill" style="width: 750rpx; height: 373rpx; display: inline-block; box-sizing: border-box"></image>
<view class='bg-image'>
<!-- wx:if="{{!showLoginButton}} -->
<image bindtap="handleTapAvatar" class='user-image' src='{{userInfo.avatarUrl}}' mode="aspectFill" style="position: absolute; left: -50rpx; top: 249rpx"></image>
</view>
<view class="container" style="position: relative; left: 0rpx; top: -94rpx; width: 750rpx; height: 80rpx; display: flex; box-sizing: border-box">
<view bindtap="handleTapLogin"class="nickname">{{userInfo.nickName}}</view>
<view class="userinfo" style="position: relative; left: 556rpx; top: -158rpx; width: 136rpx; height: 59rpx; display: flex; box-sizing: border-box">
<navigator url="../set_profile/set_profile" style="position: relative; left: 0rpx; top: 0rpx; width: 136rpx; height: 52rpx; display: block; box-sizing: border-box">编辑资料</navigator>
</view>
<view class="posts">
<block wx:for="{{posts}}" wx:key="index">
<view class="post">
<image class="post-img" src="{{item.imgUrl}}"></image>
<text class="post-title">{{item.title}}</text>
<text class="post-content">{{item.content}}</text>
</view>
</block>
</view>
</view>
<view style="position: relative; left: 0rpx; top: 431rpx"></view>
<view class="backg" style="position: relative; left: 0rpx; top: -108rpx; width: 750rpx; height: 308rpx; display: block; box-sizing: border-box">
<text class="text" style="position: relative; left: 0rpx; top: 5rpx">粉丝:{{userInfo.fans}}</text>
<text class="text" style="position: relative; left: 17rpx; top: 5rpx">关注:{{userInfo.follows}}</text>
<text class="text" style="position: relative; left: 41rpx; top: 5rpx">喜欢:{{userInfo.likes}}</text>
<text class="text" style="position: relative; left: 59rpx; top: 5rpx">收藏:{{userInfo.collects}}</text>
<view style="position: relative">
<button class="follow-button" wx:if="{{!isFollowed}}" bindtap="toggleFollow" style="position: relative; left: 0rpx; top: 0rpx">关注</button>
<button class="unfollow-button" wx:else bindtap="toggleFollow" style="position: relative; left: 0rpx; top: 0rpx">取消关注</button>
</view>
</view>
<view><text style="position: relative; left: 0rpx; top: -176rpx;">个性签名:</text>
<text style="position: relative; left: 0rpx; top: -176rpx;font-size: 13px;">{{userInfo.signature}}</text></view>
<text class="text" style="position: relative; left: 0rpx; top: -306rpx">年级专业:{{userInfo.grade}}级 {{userInfo.major}}</text>
</view>
</view>
3、【发布页面】
post.js
const app = getApp();
const http = require("./../../../utils/http.js");
const qiniuUtil = require("./../../../utils/qiniuToken.js");
const config = require("./../../../config.js");
wx.cloud.init()
const db = wx.cloud.database()
// const posts = db.collection('posts')
let datas
Page({
data: {
logs: [],
imageArray: [],
attachments: [],
private: false,
textContent: '',
name: '',
phone:'',
param: app.globalData.param,
showOptions: false,
selectedOption: '', // 存储选择的标签
showInput: false,
content: '', // 帖子内容
imgPreview: '',
imgList: [],
imgUrls: [], // 添加这一行
temFile: [],// 其它属性...
showAuthModal: false,
inputValue: '',
icon: {
width: "100rpx",
height: "100rpx",
path: "",
showImage:true
},
qiniu: {
uploadNumber: 9,
region: config.region,
token: '',
domain: config.qiniuDomain,
returnAllImage: true
},
canPost:true
},
// uploadImg() {//上传图片
// let temFiles = this.data.temFile;
// for (let i = 0; i < temFiles.length; i++) {
// let m = Math.random() * 100
// wx.cloud.uploadFile({
// cloudPath: ('imgList/帖子/' + m + '.png'), // 指定要上传的文件的小程序临时文件路径
// filePath: temFiles[i],
// success: res => { // 成功回调
// console.log('上传成功', res)
// },
// fail(err) {
// console.log("失败", err)
// }
// })
// }
// },
handleInput(event) { // 将 帖子内容输入框的值 保存到data中//将输入框数据存储在数据库
this.setData({
inputValue: event.detail.value,
});
},
handleAnonymousInput(event) {
this.setData({
anonymousValue: event.detail.value,// 将 匿名代号输入框的值 保存到data中
});
},
saveData: function(e) {// 将数据存入云数据库+发布按钮功能
if (this.data.inputValue === '') {
console.log('输入框内容为空');
return;// 输入框为空时,停止执行后续逻辑
}
this.uploadImg().then(uploadedImgUrls => {
const collection = db.collection('content');
collection.add({
data: {
content: this.data.inputValue,// 将输入框的值作为字段存入数据库
anonymous: this.data.anonymousValue,// 将第二个输入框的值作为字段存入数据库
ttime: new Date(),// 字段 来记录当前时间
imgUrls: uploadedImgUrls,//图片链接
tag: this.data.selectedOption || '其他' // 存储选择的标签,如果没有选择标签则默认为'其他'
},
success: (res) => {
console.log('数据存入云数据库成功', res);
console.log(this.data.imgUrls); // 打印图片链接数组
// 清空输入框的值
this.setData({
inputValue: '',
anonymousValue: '',
imgUrls: []
});
// 跳转到主页
wx.redirectTo({
url: '../index/index'
});
},
fail: (error) => {
console.error('数据存入云数据库失败', error);
}
});
});
},
uploadImg() {//上传图片
return new Promise((resolve, reject) => {
let temFiles = this.data.temFile;
let uploadedImgUrls = []; // 保存上传成功的图片链接
let uploadCount = 0; // 记录已上传的图片数量
if (temFiles.length === 0) {
resolve(uploadedImgUrls);
}
for (let i = 0; i < temFiles.length; i++) {
let m = Math.random() * 100;
wx.cloud.uploadFile({
cloudPath: ('imgList/帖子/' + m + '.png'),
filePath: temFiles[i],
success: res => {
console.log('上传成功', res);
uploadedImgUrls.push(res.fileID); // 将上传成功的图片链接保存到数组中
uploadCount++;
// 判断是否所有图片都已上传成功
if (uploadCount === temFiles.length) {
this.setData({
imgUrls: uploadedImgUrls // 将图片链接数组保存到data中
});
resolve(uploadedImgUrls);
}
},
fail(err) {
console.log("失败", err);
reject(err);
}
});
}
});
},
chooseImage() {//选择图片
wx.chooseImage({
count: 9,//最多选择9张
sizeType: ['compressed', 'original'],
sourceType: ['album', 'camera'],
success: res => {
this.setData({
imgList: this.data.imgList.concat(res.tempFilePaths),
temFile: this.data.temFile.concat(res.tempFilePaths)
});
},
fail(err) {
console.log("选择失败", err);
}
});
},
preview(e) {//预览图片
let img = e.currentTarget.dataset.src;
let imgList = this.data.imgList;
wx.previewImage({
current: img,// 当前显示图片的http链接
urls: imgList// 需要预览的图片http链接列表(数组)
});
},
delImg(e) {//删除图片
let that = this;
console.log('点击删除图片===>', e);
let index = e.currentTarget.dataset.index;
let imgList = that.data.imgList;
wx.showModal({
title: '提示',
content: '删除该图片?',
confirmColor: 'red',
success(res) {
if (res.confirm) {
console.log('用户点击确定');
imgList.splice(index, 1);
that.setData({
imgList
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},
deleteImg: function() {
const {
imgPreview
} = this.data;
this.setData({
imgPreview: ''
});
},
post: function() {
this.setData({
canPost: false
});
let content = this.data.textContent;
let attachments = this.data.attachments;
let privateValue = this.data.private;
let username = this.data.name;
let mobile = this.data.phone;
if (content == '' && attachments == '') {
wx.showLoading({
title: '内容不能为空!',
});
this.setData({
canPost: true
});
setTimeout(function() {
wx.hideLoading();
}, 1500);
return false;
}
wx.showLoading({
title: '发送中..'
});
},
toggleInput: function (event) {
this.setData({
showInput: event.detail.value
});
},
toggleOptions() {
this.setData({
showOptions: !this.data.showOptions
});
},
selectOption(event) {
const option = event.currentTarget.dataset.option;
this.setData({
selectedOption: option,
showOptions: false
});
},
tabSelect:function(e){
var current = e.currentTarget.dataset.id
this.setData({
current:current
})
},
getName: function (event) {
let value = event.detail.value;
this.setData({
name: value
});
},
getPhone: function (event){
let value = event.detail.value;
this.setData({
phone: value
});
},
/**
* 预览图片
*/
previewImage: function (event) {
let url = event.target.id;
wx.previewImage({
current: '',
urls: [url]
})
},
/**
* 设置是否匿名
*/
setPrivate: function (event) {
this.setData({
private: event.detail.value
});
},
/**
* 获取输入内容
*/
getTextContent: function (event) {
let value = event.detail.value;
this.setData({
textContent: value
});
},
// 点击发布按钮
handlePublish: function() {
// 判断用户是否已进行身份认证
if (!this.data.isAuth) {
this.setData({
showAuthModal: true
});
} else {
// 执行发布逻辑
// ...
}
},
// 输入框输入事件
// handleInput: function(e) {
// this.setData({
// inputValue: e.detail.value
// });
// },
// 取消按钮点击事件
handleCancel: function() {
this.setData({
showAuthModal: false,
inputValue: ''
});
},
// 确定按钮点击事件
handleOK: function() {
// 获取输入框的值
const inputValue = this.data.inputValue;
// 执行身份认证逻辑
// ...
// 关闭弹窗
this.setData({
showAuthModal: false,
inputValue: ''
});
}
})
/**
* 弹窗选项
showActionSheet({
itemList: ['A', 'B', 'C'],
success: function (res) {
if (!res.cancel) {
console.log(res.tapIndex) //这里是点击了那个按钮的下标
}
}
})*/
post.wxml
<view class='form'>
<textarea maxlength="1024" value='{{copyData}}' class='textarea-content' placeholder="发表你的想法..." bindinput="handleInput"/>
</view>
<view class="img_box" style=" width: 697rpx; height: 286rpx;">
<view class="img_item" wx:for="{{imgList}}" wx:for-item="item" wx:key="index" style="flex: 0 0 30%; box-sizing: border-box;">
<image bindtap="preview" data-src="{{item}}" class="img_item_i" src="{{item}}" mode="aspectFill"></image>
<view bindtap="delImg" data-index="{{index}}" class="closeImv" style="position: absolute; top: 6rpx; right: 6rpx;">
<icon type="cancel" size="20"></icon>
</view>
</view>
<view wx:if="{{imgList.length<9}}" style="justify-content: center; align-items: center; font-size: 180rpx; color: rgba(255, 255, 255, 0.671); text-align: center; vertical-align: center; display: flex; border: 1px solid white00; width: 146rpx; height: 146rpx; position: relative; line-height: 210rpx; box-sizing: border-box; left: 0rpx; top: -20rpx" bindtap="chooseImage">+
</view>
</view>
<view class='location' style="border: none; height: 70rpx; display: flex; box-sizing: border-box">
<image style="position: relative; left: 80rpx; top: 3rpx;width: 45rpx; height: 45rpx" src="/image/number-sign.png" />
<navigator url="../posthuati/posthuati" style="position: relative; left: 80rpx; top: 3rpx">添加话题</navigator>
</view>
<view class='location' style="height: 70rpx; display: flex;border: none; box-sizing: border-box">
<image style="position: relative; left: 80rpx; top: 3rpx; width: 45rpx; height: 45rpx; display: block; box-sizing: border-box" src="/image/tag.png" />
<text class="like-word" bindtap="toggleOptions" style="position: relative; left: 80rpx; top: 3rpx">选择标签</text>
<view class='item' style="position: relative; color: #ffffff; width: 97rpx; height: 52rpx; display: block; box-sizing: border-box; left: 479rpx; top: 3rpx">匿名</view>
<switch style="position: relative; left: 286rpx; top: -2rpx; display: block; box-sizing: border-box" bindchange="toggleInput" color='#CF6F27'/>
</view>
<view class="options" style="position: relative; left: 303rpx; top: -228rpx; width: 127rpx; height: 218rpx; display: block; box-sizing: border-box">
<block wx:if="{{showOptions}}">
<view style="position: relative;">
<button class="buttons" bindtap="selectOption" style=" position: relative; top: -10rpx; box-sizing: border-box"data-option="求问">求问</button>
<button class="buttons" bindtap="selectOption" style="position: relative; top: -8rpx; box-sizing: border-box"data-option="交友">交友</button>
<button class="buttons" bindtap="selectOption" style=" position: relative; top: -6rpx; box-sizing: border-box" data-option="树洞">树洞</button>
<button class="buttons" bindtap="selectOption" style=" position: relative; top: -4rpx; box-sizing: border-box" data-option="其他">其他</button>
</view>
</block>
<block wx:else >
<text class="selected-option" style="color: #ffffff;font-weight: bold; display: block; box-sizing: border-box; position: relative; left: -70rpx; top: 148rpx">{{selectedOption}}</text>
</block>
</view>
<view style="width: 750rpx; height: 68rpx;position: relative;top: -240rpx;display: block; box-sizing: border-box">
<view wx:if="{{showInput}}" style="color: #ffffff;width: 750rpx; height: 68rpx;">
<input bindinput="handleAnonymousInput" style="height: 52rpx; width: 228rpx; display: block; box-sizing: border-box; position: relative; top: 0rpx; left: 523rpx"placeholder="输入你的代号 "placeholder-style="color: #ffffff;font-size: 14px;"></input>
</view></view>
<view style="position: relative;top: -200rpx;display: block; box-sizing: border-box">
<!-- 发布按钮 -->
<button class='button-container' bindtap="saveData" disabled='{{!canPost}}' style="width: 624rpx; height: 92rpx; display: block; box-sizing: border-box; left: 0rpx; top: 0rpx"> 发布 </button>
<!-- 弹窗组件 -->
<view class="modal" wx:if="{{showModal}}">
<view class="modal-content">
<view class="modal-title">身份认证</view>
<view class="modal-text">为了确认您是本校人员,请输入你的学号或者工号</view>
<input class="tinput" bindinput="handleInput" placeholder="请输入你的学工号" value="{{inputValue}}" />
<view class="modal-buttons">
<button class="cancel-button" bindtap="handleCancel">Cancel</button>
<button class="ok-button" bindtap="handleOK">OK</button>
</view>
</view>
</view>
</view>
4、【资料填写】
set_profile.js
const db = wx.cloud.database();
const usersCollection = db.collection('users');
Page({
data: {
userInfo: null,
formData: {
nickName: '',
gender: '',
school: '',
grade: '',
major: '',
signature: ''
}//存储输入框的值
},
onLoad: function () {
const userInfo = wx.getStorageSync('userInfo');
if (userInfo) {
this.setData({
userInfo: userInfo,
});
console.log('获取用户信息成功', userInfo);
}
},
handleInput(event) {
let nickName = event.detail.value; // 获取输入框的值
this.setData({
'formData.nickName': nickName
});
},
genderInput(event) {
let gender = event.detail.value; // 获取输入框的值
this.setData({
'formData.gender': gender
});
},
schoolInput(event) {
let school = event.detail.value; // 获取输入框的值
this.setData({
'formData.school': school
});
},
gradeInput(event) {
let grade = event.detail.value; // 获取输入框的值
this.setData({
'formData.grade': grade
});
},
majorInput(event) {
let major = event.detail.value; // 获取输入框的值
this.setData({
'formData.major': major
});
},
signatureInput(event) {
let signature = event.detail.value; // 获取输入框的值
this.setData({
'formData.signature': signature
});
},
back() {
let db = wx.cloud.database();
let id = this.data.userInfo._id;
let formData = this.data.formData;
// 过滤掉值为空字符串的字段
let filteredData = Object.keys(formData).reduce((acc, key) => {
if (formData[key] !== '') {
acc[key] = formData[key];
}
return acc;
}, {});
db.collection('users').doc(id).update({
data: filteredData,
success: (res) => {
console.log('个人信息更新成功', res);
wx.navigateBack();
},
fail: (err) => {
console.error('个人信息更新失败', err);
}
});
}
})
set_profile.wxml
<view class="container">
<form class="content" bindsubmit="handleSubmit">
<view class='username item' >
<view class='label'>昵称</view>
<input bindinput="handleInput" name="nickName" value="{{ userInfo.nickName }}" class='input' />
</view>
</form>
<form class="content" bindsubmit="genderSubmit">
<view class='username item'>
<view class='label'>性别</view>
<input bindinput="genderInput" name="gender" value="{{ userInfo.gender }}" class='input' />
</view>
</form>
<form class="content" bindsubmit="schoolSubmit">
<view class='username item'>
<view class='label'>学校</view>
<input bindinput="schoolInput" name="school" value="{{ userInfo.school }}" class='input' />
</view>
</form>
<form class="content" bindsubmit="gradeSubmit">
<view class='username item'>
<view class='label'>年级</view>
<input bindinput="gradeInput" name="grade" value="{{ userInfo.grade }}" class='input' />
</view>
</form>
<form class="content" bindsubmit="majorSubmit">
<view class='username item'>
<view class='label'>专业</view>
<input bindinput="majorInput" name="major" value="{{ userInfo.major }}" class='input' />
</view>
</form>
<form class="content" bindsubmit="signatureSubmit">
<view class='username item'>
<view class='label'>个性签名</view>
<input bindinput="signatureInput" name="signature" value="{{ userInfo.signature }}" class='input' />
</view>
</form>
</view>
<view class='button-container'>
<button form-type='submit' bindtap="back"> 保存 </button>
</view>
<!-- <view class='avatar'>
<view class="form-label">头像</view>
<image style="width: 99rpx; height: 99rpx; display: inline-block; box-sizing: border-box" class="avatar" src="{{ userInfo.avatarUrl }}" mode="aspectFill"/>
<input bindinput="handleInput" name="avatarUrl" value="{{ userInfo.avatarUrl }}" hidden />
</view> -->
<!--
<view class='number item'>
<view class='label'>学号</view>
<input name="uno" type="number" class='input' />
</view> -->
5、【实现效果】
可以分类不同标签的帖子【全部】【交友】【树洞】【求问】,【关注】、点赞、评论 还没搞