refactor(user): 重构用户模块代码

- 移除了不必要的 getAllUsers 控制器方法
-重命名 findUserList 为 getUserList,更符合方法的实际功能- 引入 UserDTO 类,用于用户数据传输和验证
- 优化了错误处理和日志记录
- 简化了代码结构,提高了可读性和可维护性
This commit is contained in:
LingandRX 2025-01-05 19:41:03 +08:00
parent adc9f2259e
commit 21e4c3ea8a
6 changed files with 67 additions and 48 deletions

View File

@ -5,40 +5,32 @@ import FetchResult from '../common/web/fetchResult.js'
import messages from '../config/messages.js' import messages from '../config/messages.js'
import { HTTP_STATUS } from '../common/constant/httpStatus.js' import { HTTP_STATUS } from '../common/constant/httpStatus.js'
import { SearchQuery } from '../models/search.js' import { SearchQuery } from '../models/search.js'
import { UserDTO } from '../dto/userDTO.js'
const UserController = { const UserController = {
async getAllUsers(res) { async getUserList(req, res) {
try {
const users = await userService.getUserList()
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', users)
} catch (err) {
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
},
async findUserList(req, res) {
try { try {
const { page, size, sort } = req.query const { page, size, sort } = req.query
const search = new SearchQuery({ page: page, size: size, sort: sort }) const search = new SearchQuery({ page: page, size: size, sort: sort })
const result = await userService.getUserList(search) const result = await userService.getUserList(search)
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', result) return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', result)
} catch (err) { } catch (err) {
console.log(err) logger(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
}, },
createUser: [ createUser: [
body('account').isLength({ min: 3 }).withMessage('Account must be at least 3 characters long'), body('account').isLength({ min: 3 }).withMessage(UserDTO.validationMessages.account.minLength),
body('account').isEmpty().withMessage('Account is required'), body('account').isEmpty().withMessage(UserDTO.validationMessages.account.empty),
body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'), body('password').isLength({ min: 6 }).withMessage(UserDTO.validationMessages.password.minLength),
body('password').isEmpty().withMessage('Password is required'), body('password').isEmpty().withMessage(UserDTO.validationMessages.password.empty),
async (req, res, next) => { async (req, res, next) => {
const errors = validationResult(req) const err = validationResult(req)
if (!errors.isEmpty()) { if (!err.isEmpty()) {
return FetchResult.formatResult( return FetchResult.formatResult(
res, res,
HTTP_STATUS.BAD_REQUEST, HTTP_STATUS.BAD_REQUEST,
errors err
.array() .array()
.map((err) => err.msg) .map((err) => err.msg)
.join(', ') .join(', ')
@ -53,7 +45,7 @@ const UserController = {
await userService.createUser(user) await userService.createUser(user)
return FetchResult.formatResult(res, HTTP_STATUS.CREATED, messages.user.created) return FetchResult.formatResult(res, HTTP_STATUS.CREATED, messages.user.created)
} catch (err) { } catch (err) {
logger('Error creating user: ', err) logger(err)
if (err.message === messages.user.alreadyExists) { if (err.message === messages.user.alreadyExists) {
return FetchResult.formatResult(res, HTTP_STATUS.CONFLICT, messages.user.alreadyExists) return FetchResult.formatResult(res, HTTP_STATUS.CONFLICT, messages.user.alreadyExists)
} }
@ -90,7 +82,7 @@ const UserController = {
return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.accountPasswordNotMatch) return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.accountPasswordNotMatch)
} }
logger('Error logging in: ', err) logger(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
@ -102,7 +94,7 @@ const UserController = {
req.session.destroy() req.session.destroy()
return FetchResult.formatResult(res, HTTP_STATUS.OK, messages.user.logout) return FetchResult.formatResult(res, HTTP_STATUS.OK, messages.user.logout)
} catch (err) { } catch (err) {
logger('Error logging out: ', err) logger(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
} }
@ -118,10 +110,10 @@ const UserController = {
} }
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.exists) return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.exists)
} catch (err) { } catch (err) {
logger('Error checking user existence: ', err) logger(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
}, }
} }
export default UserController export default UserController

28
dto/userDTO.js Normal file
View File

@ -0,0 +1,28 @@
export class UserDTO {
constructor(user) {
this.id = user._id
this.username = user.username
this.account = user.account
this.password = user.password
this.email = user.email
this.registerDate = user.registerDate
this.lastLoginDate = user.lastLoginDate
}
static validationMessages = {
account: {
minLength: 'Account must be at least 3 characters long.',
maxLength: 'Account must be at most 20 characters long.',
empty: 'Account is required.'
},
password: {
minLength: 'Password must be at least 6 characters long.',
empty: 'Password is required.'
},
passwordEmpty: 'Password is required.',
username: 'Username is required and must be at least 3 characters long.',
email: 'Email is required and must be a valid email address.',
registerDate: 'Register date is required and must be a valid date.',
lastLoginDate: 'Last login date is required and must be a valid date.'
}
}

View File

@ -29,7 +29,6 @@ UserSchema.pre('save', async function (next) {
} }
}) })
// 更新 lastLoginDate 在用户登录时
UserSchema.methods.updateLastLoginDate = function () { UserSchema.methods.updateLastLoginDate = function () {
this.lastLoginDate = new Date() this.lastLoginDate = new Date()
} }

View File

@ -1,5 +1,6 @@
import User from '../models/userModel.js' import User from '../models/userModel.js'
import { SearchResult } from '../models/search.js' import { SearchResult } from '../models/search.js'
import logger from 'morgan'
const userRepository = { const userRepository = {
async startTransaction() { async startTransaction() {
@ -49,9 +50,9 @@ const userRepository = {
searchResult.list = data searchResult.list = data
return searchResult return searchResult
} catch (error) { } catch (err) {
console.log(error) logger(err)
throw error throw err
} }
}, },
async selectUserById(id) { async selectUserById(id) {
@ -69,7 +70,13 @@ const userRepository = {
async selectUserByPhone(phone) { async selectUserByPhone(phone) {
return User.findOne({ phone: phone }) return User.findOne({ phone: phone })
}, },
async selectUserByAccountExist(account) {
/**
* 检查用户是否存在
* @param account
* @returns {Promise<boolean>}
*/
async selectUserByAccountExists(account) {
const exist = await User.exists({ account: account }) const exist = await User.exists({ account: account })
return exist !== null return exist !== null
}, },

View File

@ -3,8 +3,7 @@ import userController from '../controllers/userController.js'
const router = express.Router() const router = express.Router()
router.get('/', userController.getAllUsers)
router.post('/', userController.createUser) router.post('/', userController.createUser)
router.get('/list', userController.findUserList) router.get('/list', userController.getUserList)
export default router export default router

View File

@ -37,11 +37,6 @@ const userService = {
return userRepository.selectUserByAccountExist(account) return userRepository.selectUserByAccountExist(account)
}, },
// Removed the unnecessary try-catch block and simplified the function
async getAllUser() {
return await userRepository.selectAllUser()
},
async getUserList(searchQuery) { async getUserList(searchQuery) {
return userRepository.selectUserList(searchQuery) return userRepository.selectUserList(searchQuery)
}, },
@ -53,28 +48,27 @@ const userService = {
* @throws {Error} - 如果用户已存在或事务失败 * @throws {Error} - 如果用户已存在或事务失败
*/ */
async createUser(user) { async createUser(user) {
const { account } = user
const session = await userRepository.startTransaction() const session = await userRepository.startTransaction()
try { try {
// 检查用户是否已存在 const userExists = await userRepository.selectUserByAccountExists(user.account)
const existingUser = await userRepository.selectUserByAccount(account)
if (existingUser) { if (userExists) {
return new Error(messages.user.alreadyExists) return new Error(messages.user.alreadyExists)
} }
// 创建新用户 await userRepository.createUser(user)
const result = await userRepository.createUser(user)
// 提交事务
await userRepository.commitTransaction(session) await userRepository.commitTransaction(session)
return result
} catch (err) { } catch (err) {
// 回滚事务 logger(err)
await userRepository.rollbackTransaction(session).catch((rollbackErr) => { try {
logger('Error rolling back transaction: ', rollbackErr) await userRepository.rollbackTransaction(session)
}) } catch (err) {
throw err // 将错误抛给调用方Controller 层) logger(err)
throw err
}
throw err
} }
} }
} }