前言
作为一个即将毕业的大学生,我谙晓多少基础不好的同学做毕设的苦恼。在我们自己的专业,一般毕设都是以 小程序或者网站 的形式开发,必须一个人进行前后端的全过程的开发。
因此我就构思能不能开发一个覆盖面比较广,能够达到快速改造,快速迁移部署,且技术栈相对容易的开源小程序。最初我想着开发的是一个商城小程序,但是商城的话改造性不强,所以我就选择了开发一个更加百搭的的 社区论坛小程序。
为什么说百搭呢,毕设当然需要有一定的特殊性,但是这又和小程序需要百搭 相悖,社区小程序的话可以非常方便的改成各种各样的其他类型小程序,主题色改个黑色就是 潮流社区小程序,改个黄色就是 校园便捷小程序,改个红色就是 党校培训小程序,蓝色就是 科技论坛社区。
😊 总之科技以换皮为主
戳这里就可以获得源代码啦👇
由于个人开发者原因没办法上线,如果想要看效果的可以私信我哈,下面放一部分小程序的展示图片👇
首页
侧边栏
文章详情
个人主页
发布表单
我的关注
还有CMS后台的一些展示
安装及部署
由于还有一点点功能在开发中,安装及部署的流程之后完善,欢迎插眼关注~
已实现功能
- 可快速配置的主题颜色
- 首页列表展示,轮播图
- 文章,用户的搜索功能
- 文章的发布,编辑,图片上传
- 文章评论,点赞,分享
- 用户登录,登出,个人信息编辑,关注,个人主页
- 消息实时通知
- CMS后台管理系统生成
技术栈
原生微信小程序
云开发(省去了后端和后台)
colorui样式库(关注点集中,提升开发效率)
主题样式
默认为 #008080 的蓝绿色
开发思路
之所以选择云开发是因为云开发解决了毕业设计中 后端开发 和 管理后台 两个问题,通过云函数我们可以直接在小程序中实现与数据库的交互,省去了服务器部署后端语言学习的过程~不仅如此,后台管理系统也可以直接通过云开发CMS直接生成!
这样我们唯一的任务就是开发小程序啦!
开发规范
由于云开发CMS对于联表的兼容性不是很好,因此大部分表格都通过冗余字段的方式让CMS可以快速查询数据。
在开发时为了让开发者更加容易迁移和改造,我尽量避免了一些必须在云函数中执行的方法,例如 联表查询(lookup) 方法,选择的几乎都是可以直接在小程序端就能执行的数据库方法。
整体模块化的方式可以参考我的这篇文章 # 原生小程序也要写的爽~教你如何优雅的在小程序中进行模块化
整体异步编程的方式可以参考我的这篇文章 # 小程序中如何优雅的使用async await异步编程
目录结构
oil-community
├── cloudfunctions 云函数目录
│ ├── post
│ └── user
└── miniprogram
├── components 通用组件目录
├── lib 无关业务通用方法目录
├── miniprogram_npm npm包
├── pages 所有页面
├── static 静态文件目录
├── template 页面模板目录
└── utils 业务相关通用方法目录
utils
与业务相关的通用方法都放在utils文件夹中
router
需要参数且需要复用的路由跳转放在 utils/router
目录中对应的模块内
下面是其中一个模块:
//post.js
module.exports = {
showPostForm(type = "add", postId) {
// 跳转至文章详情
wx.navigateTo({
url: `/pages/form/post-form/post-form?type=${type}&postId=${postId}`,
})
},
showPostDetail(postId) {
// 跳转至文章详情
wx.navigateTo({
url: `/pages/post-detail/post-detail?postId=${postId}`,
})
},
showPostList({ title, type }) {
wx.navigateTo({
url: `/pages/post-list/post-list?type=${type}&title=${title}`,
})
}
}
request
需要参数且需要复用的请求放在 utils/request
目录中对应的模块内
下面是其中一个模块:
// request.js
const db = wx.cloud.database()
const _ = db.command
const $ = db.command.aggregate
module.exports = {
getUser(userId) {
const getUserInfo = db.collection("user")
.doc(userId)
.get()
// 获取用户发布数量
const getPostNum = db.collection("post")
.where({ userId })
.count()
// 获取用户获赞总数
const getFavorNum = db.collection("post").aggregate()
.match({ userId })
.group({
_id: null,
favorNum: $.sum('$favorNum')
})
.end()
return Promise.all([getUserInfo, getPostNum, getFavorNum])
},
getUserList(match = {}, project = {}, lastTime = new Date().getTime()) {
return db.collection("user")
.aggregate()
.project({
...project,
fansNum: true,
avatarUrl: true,
intro:true,
nickName: true,
createTime: true
})
.match({ createTime: _.lt(lastTime), ...match })
.sort({ createTime: -1 })
.limit(10)
.end()
}
}
lib
与业务无关的通用方法都放在 lib 目录中,事实上很多lib中的方法本应是放在 utils 目录下的通用方法,但是由于个人习惯将方法以 是否与业务耦合 的方式进行区分了~
在lib目录中,所有的方法即使是迁移到了另外一个小程序上也是可以直接使用的,
下面是其中一个模块:
// modal.js 通用弹窗方法
const config = getApp().globalData.config
module.exports = {
// 弹出确认框,有取消按钮
async showConfirm(title, confirmText = "确认") {
const res = await wx.showModal({
title,
cancelColor: '#b6b6b6',
confirmText,
confirmColor: config.primaryColor,
})
if (res.cancel) {
return false
} else if (res.confirm) {
return true
}
},
// 弹出提示框,无取消按钮
async showMessage(content, confirmText = "确认") {
await wx.showModal({
title: '提示',
content,
showCancel: false,
confirmText,
confirmColor: config.primaryColor,
})
}
}
在调用的时候我个人的习惯是按需引入,也就是在每个js中单独require某个模块,使用方式如下:
//home.js
// 引入方法
const app = getApp()
const debounce = app.require("lib/debounce")
const loginCheck = app.require("utils/loginCheck")
Page({
//...do someting
})
但是如果你想偷个懒,不想在模块中一个个引入,想减少一点代码量。你也可以写一个全部通用方法的入口文件index.js
,将所有模块在index.js
统一引入后再将 index.js暴露给app.js并挂载
具体操作如下
// index.js
const fileSystemManager = wx.getFileSystemManager()
const moduleArr = fileSystemManager.readdirSync("/lib")
.filter(item => {
return item.split(".")[1] === "js"
})
.map(item => {
return { [item.split(".")[0]]: require(item) }
})
module.exports = { ...moduleArr }
在app.js中引入即可
const lib = require("./lib/index")
App({
...lib
//... do something
})