社区类微信小程序全栈
CONTENTS:
该项目实现的是微型的交流平台(书法)小程序客户端的实现,以提供用户平台进行作品的分享与交流。建立这一平台的初衷是为了给本校的书法社团提供一个交流分享平台,大体上平台实现的是作品的上传,浏览,点赞评论等功能;
就目前已完成部分而言,已经实现公共的动态发布浏览等所有流程(即所有在平台注册成功的用户都有权限进行发布浏览等全流程),后期扩展来说,除了一些拓展外,还需要划分用户群体,根据用户群体划分权限。比如:根据学校划分群体,以实现本校拓展至多校,在单个学校中,又根据学号划分群体,以区分社员和非社员,有关后期拓展在后文再作详述;
据我2016年至2018年在书法社的任职,该社的现状为缺少沟通,社团的所有日常交流方式仅为QQ群,在对外上,社团基本处于封闭状态,与外部交流联系也几乎没有,而有一部分原因即是没有交流的途径。
- QQ群作为一个即时通讯工具,不具备良好的作品交流分享功能,用户只能通过上传图片至群相册,却无法实现分类筛选,按关键字搜索,以及评论点赞的功能,在资源管理上也明显不适用,归根到底QQ作为一款即时通讯工具,虽然集成了社区(QQ空间),但其作用范围局限于好友间,而无法按不同的群体划分动态;
- 百度贴吧同作为一个社区应用,具有较为开放的能力,同样有着动态发布点赞评论管理等全流程的完善功能,但就我校书法社团当前来说并未使用百度贴吧来作为分享交流平台,就本质上而言,百度贴吧终究是一个开放的平台,这意味着所有人都可以浏览,都可以发布,用户权限不受限制。
注:虚线外框表示该功能暂未实现,其余均为已实现的功能;
数据库使用的是MySql,后期拓展的数据库尚未完成,后期拓展可能对当前数据库进行改写,当前设计的数据表有:
calligraphy
(书法动态表)comment
(评论表)message_log
(反馈日志表)tag
(分类标签表)temp_ck_code
(临时验证码表)user
(用户信息表) 各表详细设计如下:
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
calligraphy_id |
Int |
主键 | 作品(动态)的唯一标识 | 自增长 |
img_path |
Varchar` | / | 动态图片路径 | 当前设定每条动态仅一张图片,后期作为可扩充项将修改 |
title |
Varchar |
/ | 动态标题 | / |
content |
Varchar |
/ | 动态主要内容 | / |
tags |
Varchar |
/ | 动态标签合集 | 这里使用字符串拼接保存标签,详情在后文讲述 |
user_id |
Int |
外键 | 发帖者的id | 关联user表 |
view |
Int |
/ | 浏览数量 | / |
good |
Int |
/ | 点赞数量 | / |
good_list |
Int |
/ | 点赞用户集合 | 这里使用字符串拼接保存标签,详情在后文讲述 |
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
comment_id |
Int |
主键 | 评论唯一标识 | 自增长 |
comment_content |
Varchar |
/ | 评论主要内容 | / |
calligraphy_id |
Int |
外键 | 评论的动态id |
关联calligraphy表 |
user_id |
Int |
外键 | 评论者的id |
关联user 表 |
date |
Varchar |
/ | 评论日期 | / |
time |
Varchar |
/ | 评论时间 | / |
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
msg_id |
Int |
主键 | 反馈日志唯一标识 | 自增长 |
title |
Varchar |
/ | 反馈标题 | / |
content |
varchar |
/ | 反馈主要内容 | / |
user_id |
Int |
外键 | 反馈者的id |
关联user 表 |
date |
Varchar |
/ | 反馈日期 | / |
time |
Varchar |
/ | 反馈时间 | / |
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
tag_id |
Int |
主键 | 标签唯一标识 | 自增长 |
tag_name |
Varchar |
/ | 标签名 | / |
bg_color |
varchar |
/ | 标签颜色 | 用于前端样式 |
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
id |
Int |
主键 | 临时验证码唯一标识 | 自增长 |
code_value |
Varchar |
/ | 临时验证码的值 | / |
create_time |
datetime |
/ | 生成时间 | 用于作过期清除处理 |
regist_username |
Varchar |
/ | 注册的用户名 | 用于注册时未生成user_id 区分用户 |
字段名 | 类型 | 键 | 注释 | 备注 |
---|---|---|---|---|
user_id |
Int |
主键 | 用户唯一标识 | 自增长 |
user_name |
Varchar |
/ | 用户名(可作为唯一标示) | / |
password |
Varchar |
/ | 用户密码 | / |
head_path |
Varchar |
/ | 用户头像路径 | / |
email |
Varchar |
/ | 用户绑定的邮箱 | / |
user_status |
Varchar |
/ | 用户状态 | 用于区分用户身份,目前系统暂未实现此模块 |
school_number |
Varchar |
/ | 学号 | 用于绑定用户学号以更改用户身份 |
Phone |
Varchar |
/ | 可选的用户信息-电话号码 | / |
wx_openid |
Varchar |
/ | 微信openid |
用户绑定微信小程序后以openid 作为用户唯一标识 |
temp_ck_code |
Varchar |
/ | 临时验证码 | 用于找回密码时向用户发送验证码 |
小程序的界面路由如下(未包括登录流程):
以下是各功能模块详述:
流程图
详情描述:
用户进入登录流程(有关如何进入登录,在后文其他流程中的登录判断后依据登录状况路由至登录界面),首先必须以微信身份登录,在该平台的小程序客户端中,微信账号将作为平台身份的唯一标识,所以用户必须将微信账号与平台账号进行绑定,微信登录成功后将判断绑定情况,如果已绑定,直接进入系统,如果未绑定,将路由至绑定页面进行绑定操作,待绑定成功方可进入流程。
流程图
详情描述:
用户注册时,必须制定的字段为:用户名,密码,邮箱,其中邮箱必须通过验证码校验,验证码格式为随机6位数,目前,每个邮箱可作为多个账号的绑定邮箱,所以,暂不支持通过邮箱登录,在后期将进行邮箱的绑定限制。
流程图
详情描述:
用户进入详情页面时,点赞按钮需要依据用户登录状态来显示相应的样式,如果用户未登录则按钮为未点击状态,点击后根据用户登录状态,如果已登录则请求后台进行点赞或取消点赞的操作并更新前端样式,如果用户未登录或绑定,则引导用户路由至登录/绑定页面。
流程图
详情描述:
在该项目中,很多操作都是基于用户的登录,如以下操作都基于用户的登录:动态发布,评论,点赞,个人中心的进入,反馈,解绑微信,更换头像,更新用户信息。 登录流程主要判断两点:1. 微信是否登录,2. 微信账号是否绑定平台账号,二者成立时判定为已登录。
流程图
详情描述:
发布时,主要填写标题和主要内容的表单,以及要上传的图片的选择,上传前,主要做表单合法性的验证,即表单不可有空值,必须选择图片,上传后在后端主要做图片的接收,以及图像的压缩,并存储,在成功后将数据写入数据库,为确保图片名不重复,图片的命名为“发布者id
” +“_
” + 当前时间戳,在这一流程成功后写入数据库。
瀑布流在web开发中是很常见的布局,在web中可以通过js
直接操作dom
实现,或者可以使用jQuery
插件实现,但在小程序中,js
无法直接操作dom
,只能通过数据绑定来实现,在此作简单原理讲述:
首先定义全部item数组(items
),再分别定义col1[ ]
和col2[ ]
数组,分别用来储存左边和右边两列item
,定义左右高度h1
,h2
,初始值为0
,在页面中存放一个view
,并使其隐藏,在view
中存放所有items
的图像,为图像绑定微信bindload
事件,在图像加载时,获取该图像信息,获取图像的真实高度和宽度,并根据在页面onload
中获取的系统宽度和高度,计算出图片缩小后的高度,并判断左右列的高度,进行将图片添加到col1[ ]
或col2[ ]
数组中,并更新h1
或h2
的高度;
在页面中,瀑布流使用flex
布局,父容器flex-direction
为row
,子容器flex-direction
为column
,原理图如下:
个人中心大体上使用的是tab
嵌套,个人中心中有3个子tab
,并且,子tab
间可进行滑动切换,tab
标签上滑动至顶部时固定在顶部,布局图如下:
页面根容器使用flex
布局,flex-direction
为colum
,头部容器高度自适应,底部tab
主容器的高度固定,为屏幕高度100vh
,tab
中嵌套scroll-view
以保证内容可滚动浏览,同时向上滚动时头部离开屏幕,而tab
标签固定在顶部;
Tab
使用的是小程序原生的swiper
组件,让其占满tab
主显示区,在切换tab
时,通过数据绑定更改tab
标签的状态,在点击tab
标签时,改变swiper
组件的当前下标,从而实现tab
嵌套,以及滑动切换tab
;
- 全局配置
- 页面配置
- 注册页面
-onLoad()
- onShow()
- onPullDownRefresh()
- 数据绑定
- 列表渲染
- 条件渲染
wx.getSystemInfo(Object object)
- 用于获取系统信息,在本应用中是获取设备宽度和高度;
setTimeout(function callback, number delay, any rest)
- 定时器,应用于延时触发;
wx.navigateBack(Object object)
- 关闭当前页面,返回上一页面或多级页面;
wx.switchTab(Object object)
- 路由至主tab时必须使用的方法;
wx.navigateTo(Object object)
- 保留当前页面,跳转到应用内的某个页面,页面栈新入栈;
wx.showLoading(Object object)
- 显示加载框,与
wx.hideLoading
搭配使用
- 显示加载框,与
wx.hideLoading(Object object)
- 隐藏加载框,与
wx.showLoading
搭配使用
- 隐藏加载框,与
wx.showToast(Object object)
- 显示消息提示框;
wx.showModal(Object object)
- 显示模态对话框
wx.request(Object object)
- 发起 HTTPS 网络请求;
wx.uploadFile(Object object)
- 将本地资源上传到服务器。客户端发起一个
HTTPS POST
请求,其中content-type
为multipart/form-data
- 将本地资源上传到服务器。客户端发起一个
wx.setStorage(Object object)
- 将数据存储在本地缓存中指定的
key
中。会覆盖掉原来该 key 对应的内容。数据存储生命周期跟小程序本身一致,即除用户主- 动删除或超过一定时间被自动清理,否则数据都一直可用。单个key
允许存储的最大数据长度为1MB
,所有数据存储上限为10MB
;
- 将数据存储在本地缓存中指定的
wx.getStorage(Object object)
- 从本地缓存中异步获取指定
key
的内容
- 从本地缓存中异步获取指定
wx.clearStorage(Object object)
- 清理本地数据缓存
wx.previewImage(Object object)
- 在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作。
wx.chooseImage(Object object)
- 从本地相册选择图片或使用相机拍照。
wx.login(Object object)
- 调用接口获取登录凭证(
code
)
- 调用接口获取登录凭证(
wx.checkSession(Object object)
- 检查登录态是否过期。
设计理念上基本遵循Google material design
,采用扁平的布局风格,布局多使用卡片具体如下:
在布局中,所有元素必须确保在不同比例和分辨率的设备上显示正常,布局上优先采用css3的flex属性,由于小程序对flex的支持不像web一样受浏览器限制,flex布局在小程序中可以较为理想的实现其效果;所有容器大小使用微信的‘rpx’单位,部分单位使用绝对像素;
所有的容器应该与其兄弟容器对齐,所有容器的margin和padding必须明确,文字不可直接贴于容器边界;
首先,避免同一个页面出现过多色彩(外部图片中的颜色不做考虑)
为了有效地传达信息的视觉层次,应该使用深浅不同的文本。对于白色背景上的文字,标准alpha
值为87%
(#000000
)。视觉层次偏低的次要文字,应该使用54%(#000000
)的alpha值。而像正文和标签中用于提示用户的文字,视觉层次更低,应该使用26%
(#000000
)的alpha
值。其它元素,如图标和分隔线,也应该具有黑色的alpha
值,而不是实心颜色,以确保他们能适应任何颜色的背景。
组件包括大部分页面元素,如button(包括单选按钮和多选按钮等),卡片,分割线,表单等;组件的样式必须带有阴影,关于阴影的规范在第5点阴影中详述。组件尽量采用应用主题色;
所有阴影颜色使用rgba定义,通常可设置为rgba(0,0,0,0.1)
/ rgba(0,0,0,0.2)
,所有阴影的大小及距离使用绝对像素(px
)定义,x轴,y轴的位移绝对值建议小于5px
,阴影半径建议值在10
– 20px
;
部分界面如下
注: 原图详情参见/img/ui
下的文件,全部界面参见应用
目前,登录页面通过点击个人中心时判断登录状态实现,而登录页面并没有被独立成一个页面,而是通过wx:if来判断页面中显示的登录还是个人中心,这种结构虽然可以实现效果,却带来一系列问题,比如:
- 在其他页面需要登录时,必须通过wx.switchTab跳转到个人中心进行登录操作,并且登录流程结束后需要用户手动返回之前浏览的地方,在页面栈中,之前的页面将不会被保存;
- 单个页面的代码量严重冗杂,不符合小程序的规范;
- 不利于后期对代码的维护;
在当前已实现的功能中,数据库的设计尚存在一些问题,在此作详述:
在3.2.1 calligraphy(书法动态表)
中,针对动态所属标签,以及已点赞的列表,目前使用的是字符串拼接,通过字符串拼接,来保存所属tag
的id
,或者点赞者的id
,这种保存的方法唯一的优点是数据库的设计比较简便,但在做解析的时候,如果数据量较大,对性能的消耗较大,可另建动态和点赞/分类tag
关联表,在数据量较大时,通过数据库查询,性能优于字符串的解析。
在该项目中,其实多处前端用到的都是类似的场景,在代码表现中,本可以通过微信提供的模板能力使代码量减少,代码结构更简洁,规范,更利于后期的修改和维护,但在实现中我却没有如此实践,导致代码量臃肿,后期维护难,代码可读性不高;
在这次开发中,服务端api接口的接口是最不能令自己满意的,在我编写api
中,首先,api
所对应的功能而言不够细,而是单纯地做了针对性的api
,针对小程序实际请求时所需的某项功能编写特定的api
,如此必定导致后期api
的维护是个比较严重的问题,对前端所需的新功能也就必须编写新的api
接口来做适配;
其次,api
的返回参数也不算规范,在众多接口中,返回参数的格式不统一,状态码不统一,大部分使用的格式如下:
{'status':status,'message':message,'data':data }
但是status
状态码却没有统一有时候成功是0
,有时候编写的是000
,显然并不规范;
在这一小程序的全栈开发过程中,主要侧重的是利用小程序的能力实现的前端开发,注重于小程序的性能与细节,以达到良好的用户体验,如在开发过程中,针对以下问题,考虑到用户体验,特做了相应的优化:
在如下场景需要加载动态项:
- 首页动态瀑布流
- 个人中心-我的发布
- 个人中心-我的点赞
- 个人中心-我的评论
而动态项的数目往往是较为大的,所以在请求时,我设定的是每次加载
10
条,并且在用户滑动到页面底部时,用户可通过提示文本知道,需要继续加载,或者已加载完毕,或者正在加载,我觉得这虽然是细节但却是必要的用户体验;而符合手机客户端的习惯,下拉时,也尽量实现动态项的刷新重加载。
在进入动态详情后,往往动态的图片将不再是低质量的缩略图,而是用户上传时的原图,通常会较大,必定需要加载,而起初我未作任何处理,使图片出现得很突兀,所以通过微信小程序的 wx:if
增加了一个图像加载动画,加载动画使用 css3
的 animation
实现,从而与用户交互,反馈用户图像正在加载的信息。
在开发过程中,我曾遇到多次此类问题,即按钮在点击时,触发了网路请求,比如像开发者发送反馈,或者是发布动态,这时如果以较快的速度点击,便会造成请求的多次触发,为了避免这一影响用户体验的情况,为按钮添加了状态判断,如果点击了按钮,并且请求并未完成,那么再次点击按钮将不做任何操作,以此避免用户的反复操作导致不必要的请求及资源浪费;
最后总结本次的开发,总的来说结果不尽人意,虽然实现了思维导图中的功能,但究其开发过程以及开发的背后,是无法令人满意的,正如 8.3
, 8.4
中所诉,在代码的整体框架上,就并不系统并不严谨,所以在做后期拓展之前,有必要先完成当前框架的更新。