彻底重构-3

This commit is contained in:
yml
2026-04-09 12:24:14 +08:00
parent 606ef875e2
commit 60054adcc4
37 changed files with 1324 additions and 3630 deletions
@@ -0,0 +1,19 @@
import { Router } from 'express'
import { getAdminAuditLogs } from '../../services/admin/admin-audit-service.js'
import { createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.use(requireAdminRoles(['admin']))
router.get('/audit-logs', createJsonHandler(
(req) => getAdminAuditLogs(req.query),
{
successMessage: 'ok',
errorMessage: '读取操作审计日志失败',
scope: '[admin/audit-logs]',
},
))
export default router
+35
View File
@@ -0,0 +1,35 @@
import { Router } from 'express'
import { getAdminSessionSummary, loginAdmin } from '../../services/admin/admin-auth-service.js'
import { createJsonHandler, extractBearerToken } from './shared.js'
const router = Router()
router.post('/auth/login', createJsonHandler(
(req) => loginAdmin(req.body?.username, req.body?.password),
{
successMessage: '登录成功',
errorMessage: '后台登录失败',
scope: '[admin/auth/login]',
},
))
router.get('/auth/session', createJsonHandler(
(req) => getAdminSessionSummary(extractBearerToken(req)),
{
successMessage: 'ok',
errorMessage: '读取后台登录态失败',
scope: '[admin/auth/session]',
},
))
router.post('/auth/logout', createJsonHandler(
() => ({ success: true }),
{
successMessage: '已退出登录',
errorMessage: '后台退出失败',
scope: '[admin/auth/logout]',
},
))
export default router
+79
View File
@@ -0,0 +1,79 @@
import { Router } from 'express'
import {
createAdminCdk,
getAdminCdks,
importAdminCdks,
invalidateAdminCdk,
releaseAdminInventoryCdk,
} from '../../services/admin/admin-service.js'
import { createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.get('/cdks', createJsonHandler(
(req) => getAdminCdks(req.query),
{
successMessage: 'ok',
errorMessage: '读取 CDK 列表失败',
scope: '[admin/cdks]',
},
))
router.post('/cdks', createJsonHandler(
(req) => createAdminCdk(req.body),
{
successMessage: 'CDK 已新增',
errorMessage: '新增 CDK 失败',
scope: '[admin/cdks]',
},
))
router.post('/cdks/import', createJsonHandler(
(req) => importAdminCdks(req.body),
{
successMessage: '导入完成',
errorMessage: '导入 CDK 失败',
scope: '[admin/cdks/import]',
},
))
router.post('/cdks/:cdkId/release', requireAdminRoles(['admin']), createJsonHandler(
(req) => releaseAdminInventoryCdk(req.params.cdkId),
{
successMessage: 'CDK 已释放',
errorMessage: '释放库存 CDK 失败',
scope: '[admin/cdks/:cdkId/release]',
audit: (req, data) => ({
action: 'inventory_cdk_released',
targetType: 'cdk',
targetId: String(req.params.cdkId),
data: {
cdkId: data.cdk?.cdkId,
skuCode: data.cdk?.skuCode,
cdkCode: data.cdk?.cdkCode,
},
}),
},
))
router.post('/cdks/:cdkId/invalidate', requireAdminRoles(['admin']), createJsonHandler(
(req) => invalidateAdminCdk(req.params.cdkId, req.body),
{
successMessage: 'CDK 已作废',
errorMessage: '作废 CDK 失败',
scope: '[admin/cdks/:cdkId/invalidate]',
audit: (req, data) => ({
action: 'inventory_cdk_invalidated',
targetType: 'cdk',
targetId: String(req.params.cdkId),
data: {
cdkId: data.cdk?.cdkId,
skuCode: data.cdk?.skuCode,
invalidReason: data.cdk?.invalidReason,
},
}),
},
))
export default router
@@ -0,0 +1,17 @@
import { Router } from 'express'
import { getAdminDashboardSummary } from '../../services/admin/admin-service.js'
import { createJsonHandler } from './shared.js'
const router = Router()
router.get('/dashboard/summary', createJsonHandler(
() => getAdminDashboardSummary(),
{
successMessage: 'ok',
errorMessage: '读取后台概览失败',
scope: '[admin/dashboard/summary]',
},
))
export default router
+26
View File
@@ -0,0 +1,26 @@
import { Router } from 'express'
import { getAdminOrderDetail, getAdminOrders } from '../../services/admin/admin-service.js'
import { createJsonHandler } from './shared.js'
const router = Router()
router.get('/orders', createJsonHandler(
(req) => getAdminOrders(req.query),
{
successMessage: 'ok',
errorMessage: '读取订单列表失败',
scope: '[admin/orders]',
},
))
router.get('/orders/:orderId', createJsonHandler(
(req) => getAdminOrderDetail(req.params.orderId),
{
successMessage: 'ok',
errorMessage: '读取订单详情失败',
scope: '[admin/orders/:orderId]',
},
))
export default router
@@ -0,0 +1,37 @@
import { Router } from 'express'
import { getAdminAgisoShopConfigs, updateAdminAgisoShopConfigs } from '../../services/admin/admin-service.js'
import { createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.use(requireAdminRoles(['admin']))
router.get('/platform-config/agiso-shops', createJsonHandler(
() => getAdminAgisoShopConfigs(),
{
successMessage: 'ok',
errorMessage: '读取 Agiso 店铺配置失败',
scope: '[admin/platform-config/agiso-shops]',
},
))
router.post('/platform-config/agiso-shops', createJsonHandler(
(req) => updateAdminAgisoShopConfigs(req.body),
{
successMessage: 'Agiso 店铺配置已保存',
errorMessage: '保存 Agiso 店铺配置失败',
scope: '[admin/platform-config/agiso-shops]',
audit: (_req, data) => ({
action: 'platform_shop_config_updated',
targetType: 'platform_config',
targetId: 'agiso_shops',
data: {
shopCount: data.shops.length,
filePath: data.filePath,
},
}),
},
))
export default router
+84
View File
@@ -0,0 +1,84 @@
import { requireAdminRole, verifyAdminSessionToken } from '../../services/admin/admin-auth-service.js'
import { writeAdminAuditLog } from '../../services/admin/admin-audit-service.js'
import { buildSuccessPayload, createHttpError, sendRouteError } from '../../utils/http.js'
import { logWarn } from '../../utils/logger.js'
export function createJsonHandler(action, { successMessage = 'ok', errorMessage, scope, audit } = {}) {
return async (req, res) => {
try {
const data = await action(req, res)
await recordAdminAudit(req.adminSession, req, data, audit)
res.json(buildSuccessPayload(data, successMessage))
} catch (error) {
sendRouteError(res, error, errorMessage, scope)
}
}
}
export function createFileHandler(action, { errorMessage, scope } = {}) {
return async (req, res) => {
try {
const filePath = await action(req, res)
res.sendFile(filePath)
} catch (error) {
sendRouteError(res, error, errorMessage, scope)
}
}
}
export async function requireAdminSession(req, res, next) {
try {
req.adminSession = await verifyAdminSessionToken(extractBearerToken(req))
next()
} catch (error) {
sendRouteError(res, error, '后台鉴权失败', '[admin/auth]')
}
}
export function requireAdminRoles(allowedRoles) {
return (req, res, next) => {
try {
requireAdminRole(req.adminSession, allowedRoles)
next()
} catch (error) {
sendRouteError(res, error, '后台鉴权失败', '[admin/auth/role]')
}
}
}
async function recordAdminAudit(session, req, data, audit) {
if (!audit) {
return
}
const payload = typeof audit === 'function' ? audit(req, data) : audit
if (!payload) {
return
}
try {
await writeAdminAuditLog(session, payload)
} catch (error) {
logWarn('[admin/audit]', '后台审计日志写入失败,已跳过', {
action: payload.action,
targetType: payload.targetType,
targetId: payload.targetId,
error,
})
}
}
export function extractBearerToken(req) {
const authorization = String(req.headers.authorization || '').trim()
const matched = authorization.match(/^Bearer\s+(.+)$/i)
if (!matched) {
throw createHttpError('未登录或登录已失效', {
statusCode: 401,
errorCode: 'admin_auth_required',
})
}
return matched[1]
}
+128
View File
@@ -0,0 +1,128 @@
import { Router } from 'express'
import {
closeAdminTask,
getAdminTaskDetail,
getAdminTaskScreenshotPath,
getAdminTasks,
markAdminTaskManualReview,
regenerateAdminTaskClaimLink,
releaseAdminTaskCdk,
retryAdminTask,
} from '../../services/admin/admin-service.js'
import { createFileHandler, createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.get('/tasks', createJsonHandler(
(req) => getAdminTasks(req.query),
{
successMessage: 'ok',
errorMessage: '读取任务列表失败',
scope: '[admin/tasks]',
},
))
router.get('/tasks/:taskId', createJsonHandler(
(req) => getAdminTaskDetail(req.params.taskId),
{
successMessage: 'ok',
errorMessage: '读取任务详情失败',
scope: '[admin/tasks/:taskId]',
},
))
router.get('/tasks/:taskId/screenshot', createFileHandler(
(req) => getAdminTaskScreenshotPath(req.params.taskId),
{
errorMessage: '读取任务截图失败',
scope: '[admin/tasks/:taskId/screenshot]',
},
))
router.post('/tasks/:taskId/retry', createJsonHandler(
(req) => retryAdminTask(req.params.taskId),
{
successMessage: '任务已重试',
errorMessage: '重试任务失败',
scope: '[admin/tasks/:taskId/retry]',
},
))
router.post('/tasks/:taskId/release-cdk', requireAdminRoles(['admin']), createJsonHandler(
(req) => releaseAdminTaskCdk(req.params.taskId),
{
successMessage: 'CDK 已释放',
errorMessage: '释放 CDK 失败',
scope: '[admin/tasks/:taskId/release-cdk]',
audit: (req, data) => ({
action: 'task_release_cdk',
targetType: 'task',
targetId: String(req.params.taskId),
data: {
taskId: data.task.taskId,
taskNo: data.task.taskNo,
inventoryItemId: data.task.inventoryItemId,
},
}),
},
))
router.post('/tasks/:taskId/regenerate-claim-link', requireAdminRoles(['admin']), createJsonHandler(
(req) => regenerateAdminTaskClaimLink(req.params.taskId),
{
successMessage: '领取链接已重新生成',
errorMessage: '重新生成领取链接失败',
scope: '[admin/tasks/:taskId/regenerate-claim-link]',
audit: (req, data) => ({
action: 'task_regenerate_claim_link',
targetType: 'task',
targetId: String(req.params.taskId),
data: {
taskId: data.task.taskId,
taskNo: data.task.taskNo,
claimTokenId: data.task.claimTokenId,
},
}),
},
))
router.post('/tasks/:taskId/close', requireAdminRoles(['admin']), createJsonHandler(
(req) => closeAdminTask(req.params.taskId),
{
successMessage: '任务已关闭',
errorMessage: '关闭任务失败',
scope: '[admin/tasks/:taskId/close]',
audit: (req, data) => ({
action: 'task_closed',
targetType: 'task',
targetId: String(req.params.taskId),
data: {
taskId: data.task.taskId,
taskNo: data.task.taskNo,
status: data.task.status,
},
}),
},
))
router.post('/tasks/:taskId/mark-manual-review', requireAdminRoles(['admin']), createJsonHandler(
(req) => markAdminTaskManualReview(req.params.taskId),
{
successMessage: '任务已转人工处理',
errorMessage: '标记人工处理失败',
scope: '[admin/tasks/:taskId/mark-manual-review]',
audit: (req, data) => ({
action: 'task_mark_manual_review',
targetType: 'task',
targetId: String(req.params.taskId),
data: {
taskId: data.task.taskId,
taskNo: data.task.taskNo,
status: data.task.status,
},
}),
},
))
export default router
+97
View File
@@ -0,0 +1,97 @@
import { Router } from 'express'
import {
createManagedAdminUser,
getAdminUserList,
resetManagedAdminUserPassword,
updateManagedAdminUserRole,
updateManagedAdminUserStatus,
} from '../../services/admin/admin-auth-service.js'
import { createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.use(requireAdminRoles(['admin']))
router.get('/users', createJsonHandler(
(req) => getAdminUserList(req.query),
{
successMessage: 'ok',
errorMessage: '读取后台用户列表失败',
scope: '[admin/users]',
},
))
router.post('/users', createJsonHandler(
(req) => createManagedAdminUser(req.body),
{
successMessage: '后台用户已创建',
errorMessage: '创建后台用户失败',
scope: '[admin/users:create]',
audit: (_req, data) => ({
action: 'admin_user_created',
targetType: 'admin_user',
targetId: String(data.user.userId),
data: {
username: data.user.username,
role: data.user.role,
status: data.user.status,
},
}),
},
))
router.post('/users/:userId/role', createJsonHandler(
(req) => updateManagedAdminUserRole(req.params.userId, req.body, req.adminSession),
{
successMessage: '用户角色已更新',
errorMessage: '更新用户角色失败',
scope: '[admin/users/:userId/role]',
audit: (_req, data) => ({
action: 'admin_user_role_updated',
targetType: 'admin_user',
targetId: String(data.user.userId),
data: {
username: data.user.username,
role: data.user.role,
},
}),
},
))
router.post('/users/:userId/status', createJsonHandler(
(req) => updateManagedAdminUserStatus(req.params.userId, req.body, req.adminSession),
{
successMessage: '用户状态已更新',
errorMessage: '更新用户状态失败',
scope: '[admin/users/:userId/status]',
audit: (_req, data) => ({
action: 'admin_user_status_updated',
targetType: 'admin_user',
targetId: String(data.user.userId),
data: {
username: data.user.username,
status: data.user.status,
},
}),
},
))
router.post('/users/:userId/reset-password', createJsonHandler(
(req) => resetManagedAdminUserPassword(req.params.userId, req.body),
{
successMessage: '用户密码已重置',
errorMessage: '重置用户密码失败',
scope: '[admin/users/:userId/reset-password]',
audit: (_req, data) => ({
action: 'admin_user_password_reset',
targetType: 'admin_user',
targetId: String(data.user.userId),
data: {
username: data.user.username,
},
}),
},
))
export default router
@@ -0,0 +1,48 @@
import { Router } from 'express'
import {
getAdminWebhookEventDetail,
getAdminWebhookEvents,
replayAdminWebhookEvent,
} from '../../services/admin/admin-service.js'
import { createJsonHandler, requireAdminRoles } from './shared.js'
const router = Router()
router.get('/webhook-events', createJsonHandler(
(req) => getAdminWebhookEvents(req.query),
{
successMessage: 'ok',
errorMessage: '读取 webhook 列表失败',
scope: '[admin/webhook-events]',
},
))
router.get('/webhook-events/:eventId', createJsonHandler(
(req) => getAdminWebhookEventDetail(req.params.eventId),
{
successMessage: 'ok',
errorMessage: '读取 webhook 详情失败',
scope: '[admin/webhook-events/:eventId]',
},
))
router.post('/webhook-events/:eventId/replay', requireAdminRoles(['admin']), createJsonHandler(
(req) => replayAdminWebhookEvent(req.params.eventId),
{
successMessage: 'Webhook 已重放',
errorMessage: '重放 webhook 失败',
scope: '[admin/webhook-events/:eventId/replay]',
audit: (req, data) => ({
action: 'webhook_replayed',
targetType: 'webhook_event',
targetId: String(req.params.eventId),
data: {
eventId: data.eventId,
replayed: data.replayed,
},
}),
},
))
export default router