七、从零模拟新浪微博-个人主页
代码仓库:https://github.com/changeclass/koa2-weibo
用户数据
视图路由层
router.get('/profile', loginRedirect, async (ctx, next) => { const { userName } = ctx.session.userInfo ctx.redirect(`/profile/${userName}`) })当访问路由没有用户名时,默认跳转到自己用户名下。
router.get('/profile/:userName', loginRedirect, async (ctx, next) => { const { userName: curUserName } = ctx.params // 获取微博第一页数据 // controller const result = await getProfileBlogList(curUserName, 0) const { isEmpty, blogList, pageSize, pageIndex, count } = result.data await ctx.render('profile', { blogData: { isEmpty, blogList, pageSize, pageIndex, count }, userData: { userInfo: ctx.session.userInfo, fansData: { count: 0, list: [] }, followersData: { count: 0, list: [] } } }) })控制器层
/** * @description: 个人主页 * @author: 小康 * @url: https://xiaokang.me * @Date: 2020-12-19 09:47:36 * @LastEditTime: 2020-12-19 09:47:36 * @LastEditors: 小康 */ const { getBlogListByUser } = require('../services/blog') const { PAGE_SIZE } = require('../config/constant') const { SuccessModel } = require('../model/ResModel') /** * @author: 小康 * @url: https://xiaokang.me * @param {string} userName 用户名 * @param {number} pageIndex 当前页面索引 默认0 * @description: 创建微博 */ async function getProfileBlogList(userName, pageIndex = 0) { const result = await getBlogListByUser({ userName, pageIndex, PAGE_SIZE }) const blogList = result.blogList return new SuccessModel({ isEmpty: blogList.length === 0, blogList, pageSize: PAGE_SIZE, pageIndex, count: result.count }) } module.exports = { getProfileBlogList }服务层
const { Blog, User } = require('../db/model/index') const { formatUser } = require('./_format') /** * @author: 小康 * @url: https://xiaokang.me * @param {*} userName 用户名 * @param {*} pageIndex 页面索引 * @param {*} pageSize 页面大小 * @description: 根据用户名查询微博 */ async function getBlogListByUser({ userName, pageIndex = 0, pageSize = 10 }) { // 拼接查询条件 const userWhereOpts = {} if (userName) { userWhereOpts.userName = userName } // 执行查询 const result = await Blog.findAndCountAll({ limit: pageSize, // 每页多少条 offset: pageSize * pageIndex, // 跳过多少条 order: [['id', 'desc']], include: [ { model: User, attributes: ['userName', 'nickName', 'picture'], where: userWhereOpts } ] }) // 获取dataValues let blogList = result.rows.map((row) => row.dataValues) blogList = blogList.map((blogItem) => { const user = blogItem.user.dataValues blogItem.user = formatUser(user) return blogItem }) return { count: result.count, blogList } }
格式化时间、用户数据
用户数据主页是判断访问的用户是否存在。
const { isExist } = require('../../controller/user')
router.get('/profile/:userName', loginRedirect, async (ctx, next) => {
// 已登录用户的信息
const myUserInfo = ctx.session.userInfo
const myUserName = myUserInfo.userName
let curUserInfo
const { userName: curUserName } = ctx.params
const isMe = myUserName === curUserName
if (isMe) {
// 是当前登录用户
curUserInfo = myUserInfo
} else {
// 不是当前登录用户
const existResult = await isExist(curUserName)
if (existResult.errno !== 0) {
// 用户名不存在
return
}
// 用户名存在
curUserInfo = existResult.data
}
// ....
})格式化时间主要是格式化微博内容,处理在服务层。
blog.js
const { formatUser, formatBlog } = require('./_format')
// 获取dataValues
let blogList = result.rows.map((row) => row.dataValues)
// 格式化
blogList = formatBlog(blogList)
blogList = blogList.map((blogItem) => {
const user = blogItem.user.dataValues
blogItem.user = formatUser(user)
return blogItem
})_format
/**
* @description: 数据格式化
* @author: 小康
* @url: https://xiaokang.me
* @Date: 2020-12-17 14:32:10
* @LastEditTime: 2020-12-17 14:32:10
* @LastEditors: 小康
*/
const { DEFAULT_PICTURE, REG_FOR_AT_WHO } = require('../config/constant')
const { timeFormat } = require('../utils/dt')
/**
* 格式化头像
* @author 小康
* @date 2020-12-17
* @param {Object} obj 用户对象
* @returns {Object} 处理后的结果
*/
function _formatUserPicture(obj) {
if (obj.picture == null) {
obj.picture = DEFAULT_PICTURE
}
return obj
}
/**
* 格式化用户
* @author 小康
* @date 2020-12-17
* @param {Array|Object} list 用户列表或单个用户对象
* @returns {any}
*/
function formatUser(list) {
if (list == null) {
return list
}
if (list instanceof Array) {
// 数组 用户列表
return list.map(_formatUserPicture)
}
// 单个对象
let result = list
result = _formatUserPicture(result)
return result
}
/**
* 格式化数据的时间
* @param {Object} obj 数据
*/
function _formatDBTime(obj) {
obj.createdAtFormat = timeFormat(obj.createdAt)
obj.updatedAtFormat = timeFormat(obj.updatedAt)
return obj
}
/**
* 格式化微博内容
* @param {Object} obj 微博数据对象
*/
function _formatContent(obj) {
obj.contentFormat = obj.content
// 格式化 @
// from '哈喽 @张三 - zhangsan 你好'
// to '哈喽 <a href="/profile/zhangsan">张三</a> 你好'
obj.contentFormat = obj.contentFormat.replace(
REG_FOR_AT_WHO,
(matchStr, nickName, userName) => {
return `<a href="/profile/${userName}">@${nickName}</a>`
}
)
return obj
}
/**
* 格式化微博信息
* @param {Array|Object} list 微博列表或者单个微博对象
*/
function formatBlog(list) {
if (list == null) {
return list
}
if (list instanceof Array) {
// 数组
return list.map(_formatDBTime).map(_formatContent)
}
// 对象
let result = list
result = _formatDBTime(result)
result = _formatContent(result)
return result
}
module.exports = { formatUser, formatBlog }dt.js
/**
* @description:
* @author: 小康
* @url: https://xiaokang.me
* @Date: 2020-12-19 10:54:11
* @LastEditTime: 2020-12-19 10:54:12
* @LastEditors: 小康
*/
const { format } = require('date-fns')
/**
* 格式化时间,如 09.05 23:02
* @param {string} str 时间字符串
*/
function timeFormat(str) {
return format(new Date(str), 'MM.dd HH:mm')
}
module.exports = {
timeFormat
}加载更多
api路由层/** * @description: 个人主页 API 路由 * @author: 小康 * @url: https://xiaokang.me * @Date: 2020-12-19 11:20:02 * @LastEditTime: 2020-12-19 11:20:02 * @LastEditors: 小康 */ const router = require('koa-router')() const { getProfileBlogList } = require('../../controller/blog-profile') const { loginCheck } = require('../../middlewares/loginChecks') const { getBlogListStr } = require('../../utils/blog') router.prefix('/api/profile') // 加载更多 router.get('/loadMore/:userName/:pageIndex', loginCheck, async (ctx, next) => { let { userName, pageIndex } = ctx.params pageIndex = parseInt(pageIndex) const result = await getProfileBlogList(userName, pageIndex) result.data.blogListTpl = getBlogListStr(result.data.blogList) ctx.body = result }) module.exports = router工具方法
/** * @description: 微博数据相关的工具方法 * @author: 小康 * @url: https://xiaokang.me * @Date: 2020-12-19 11:30:22 * @LastEditTime: 2020-12-19 11:30:22 * @LastEditors: 小康 */ const fs = require('fs') const path = require('path') const ejs = require('ejs') // 获取 blog-list.ejs 文件内容 const BLOG_LIST_TPL = fs .readFileSync(path.join(__dirname, '..', 'views', 'widgets', 'blog-list.ejs')) .toString() /** * @author: 小康 * @url: https://xiaokang.me * @param {Array} blogList 微博列表 * @param {Boolean} canReply 是否可以回复 * @description: 根据blogList渲染出HTML字符串 */ function getBlogListStr(blogList = [], canReply = false) { return ejs.render(BLOG_LIST_TPL, { blogList, canReply }) } module.exports = { getBlogListStr }
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小康博客!
评论
TwikooDisqusjs








