|
|
@@ -306,5 +306,119 @@ export function createUserRoutes(withAuth: WithAuth) {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+ /**
|
|
|
+ * 将粉丝用户转换为学员并设置有效期
|
|
|
+ * @param {number} id - 用户ID
|
|
|
+ * @param {string} expiresAt - 有效期截止日期 (ISO格式)
|
|
|
+ * @returns {object} 转换后的用户信息
|
|
|
+ */
|
|
|
+ usersRoutes.post('/:id/convert-to-student', withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const user = c.get('user')!
|
|
|
+
|
|
|
+ // 检查是否为管理员
|
|
|
+ if (user.role !== 'admin') {
|
|
|
+ return c.json({ error: '无权执行此操作' }, 403)
|
|
|
+ }
|
|
|
+
|
|
|
+ const id = Number(c.req.param('id'))
|
|
|
+ if (!id || isNaN(id)) {
|
|
|
+ return c.json({ error: '无效的用户ID' }, 400)
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiClient = c.get('apiClient')
|
|
|
+ const body = await c.req.json()
|
|
|
+
|
|
|
+ // 验证必填字段
|
|
|
+ const { expiresAt } = body
|
|
|
+ if (!expiresAt) {
|
|
|
+ return c.json({ error: '缺少有效期参数' }, 400)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户是否存在且为粉丝
|
|
|
+ const existingUser = await apiClient.database.table('users')
|
|
|
+ .where('id', id)
|
|
|
+ .first()
|
|
|
+
|
|
|
+ if (!existingUser) {
|
|
|
+ return c.json({ error: '用户不存在' }, 404)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (existingUser.role !== 'follower') {
|
|
|
+ return c.json({ error: '只能将粉丝转为学员' }, 400)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新用户角色和有效期
|
|
|
+ await apiClient.database.table('users')
|
|
|
+ .where('id', id)
|
|
|
+ .update({
|
|
|
+ role: 'student',
|
|
|
+ student_expires_at: expiresAt,
|
|
|
+ updated_at: new Date()
|
|
|
+ })
|
|
|
+
|
|
|
+ const updatedUser = await apiClient.database.table('users')
|
|
|
+ .where('id', id)
|
|
|
+ .select('id', 'username', 'nickname', 'role', 'student_expires_at')
|
|
|
+ .first()
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ data: updatedUser,
|
|
|
+ message: '用户已成功转为学员'
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('转换用户角色失败:', error)
|
|
|
+ return c.json({ error: '转换用户角色失败' }, 500)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查并转换过期学员
|
|
|
+ * @returns {object} 转换结果统计
|
|
|
+ */
|
|
|
+ usersRoutes.get('/check-expired', withAuth, async (c) => {
|
|
|
+ try {
|
|
|
+ const apiClient = c.get('apiClient')
|
|
|
+ const now = new Date().toISOString()
|
|
|
+
|
|
|
+ // 查找所有已过期的学员
|
|
|
+ const expiredStudents = await apiClient.database.table('users')
|
|
|
+ .where('role', 'student')
|
|
|
+ .where('student_expires_at', '<', now)
|
|
|
+ .select('id', 'username', 'student_expires_at')
|
|
|
+
|
|
|
+ if (expiredStudents.length === 0) {
|
|
|
+ return c.json({
|
|
|
+ data: {
|
|
|
+ count: 0,
|
|
|
+ users: []
|
|
|
+ },
|
|
|
+ message: '没有过期学员需要转换'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量转换过期学员为粉丝
|
|
|
+ const userIds = expiredStudents.map(user => user.id)
|
|
|
+ await apiClient.database.table('users')
|
|
|
+ .whereIn('id', userIds)
|
|
|
+ .update({
|
|
|
+ role: 'follower',
|
|
|
+ student_expires_at: null,
|
|
|
+ updated_at: new Date()
|
|
|
+ })
|
|
|
+
|
|
|
+ return c.json({
|
|
|
+ data: {
|
|
|
+ count: expiredStudents.length,
|
|
|
+ users: expiredStudents
|
|
|
+ },
|
|
|
+ message: '过期学员已成功转为粉丝'
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('检查过期学员失败:', error)
|
|
|
+ return c.json({ error: '检查过期学员失败' }, 500)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
return usersRoutes
|
|
|
}
|