新增接单平台第一期闭环
This commit is contained in:
@@ -11,6 +11,7 @@ import platformConfigRouter from "./admin/platform-config.js";
|
||||
import { requireAdminSession } from "./admin/session.js";
|
||||
import tasksRouter from "./admin/tasks.js";
|
||||
import usersRouter from "./admin/users.js";
|
||||
import workerPlatformRouter from "./admin/worker-platform.js";
|
||||
import { buildNotFoundPayload } from "../utils/http.js";
|
||||
|
||||
const router = Router();
|
||||
@@ -25,6 +26,7 @@ router.use(kuaishouIndustryRouter);
|
||||
router.use(ordersRouter);
|
||||
router.use(tasksRouter);
|
||||
router.use(cloudtentaclesRecordsRouter);
|
||||
router.use(workerPlatformRouter);
|
||||
router.use(devMockRouter);
|
||||
|
||||
router.use((req, res) => {
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import {
|
||||
acceptAdminWorkOrder,
|
||||
creditAdminWorkerWallet,
|
||||
createAdminMockWorkOrder,
|
||||
getAdminWorkerPlatformSummary,
|
||||
listAdminWorkerLevels,
|
||||
listAdminWorkerUsers,
|
||||
listAdminWorkOrders,
|
||||
markAdminWorkOrderProblem,
|
||||
publishAdminWorkOrder,
|
||||
reviewAdminWorkerUser,
|
||||
saveAdminWorkerLevel,
|
||||
} from '../../services/worker-platform/worker-platform-service.js'
|
||||
import { createJsonHandler, requireAdminRoles } from './session.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.get(
|
||||
'/worker-platform/summary',
|
||||
createJsonHandler(() => getAdminWorkerPlatformSummary(), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单平台概览失败',
|
||||
scope: '[admin/worker-platform/summary]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/worker-platform/levels',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler(() => listAdminWorkerLevels(), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单等级失败',
|
||||
scope: '[admin/worker-platform/levels]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/levels',
|
||||
requireAdminRoles(['admin']),
|
||||
createJsonHandler((req) => saveAdminWorkerLevel(req.body || {}), {
|
||||
successMessage: '接单等级已保存',
|
||||
errorMessage: '保存接单等级失败',
|
||||
scope: '[admin/worker-platform/levels]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'worker_level_saved',
|
||||
targetType: 'worker_level',
|
||||
targetId: String((data as { level?: { levelKey?: string } })?.level?.levelKey || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/worker-platform/workers',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler((req) => listAdminWorkerUsers(req.query), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单员列表失败',
|
||||
scope: '[admin/worker-platform/workers]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/workers/:workerId/review',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => reviewAdminWorkerUser(String(req.params.workerId || ''), req.body || {}), {
|
||||
successMessage: '接单员审核状态已更新',
|
||||
errorMessage: '审核接单员失败',
|
||||
scope: '[admin/worker-platform/workers/:workerId/review]',
|
||||
audit: (req, data) => ({
|
||||
action: 'worker_reviewed',
|
||||
targetType: 'worker',
|
||||
targetId: String(req.params.workerId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/workers/:workerId/wallet-credit',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => creditAdminWorkerWallet(String(req.params.workerId || ''), req.body || {}), {
|
||||
successMessage: '接单员余额已增加',
|
||||
errorMessage: '人工充值失败',
|
||||
scope: '[admin/worker-platform/workers/:workerId/wallet-credit]',
|
||||
audit: (req, data) => ({
|
||||
action: 'worker_wallet_credited',
|
||||
targetType: 'worker',
|
||||
targetId: String(req.params.workerId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/worker-platform/orders',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler((req) => listAdminWorkOrders(req.query), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单订单失败',
|
||||
scope: '[admin/worker-platform/orders]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/mock',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => createAdminMockWorkOrder(req.body || {}), {
|
||||
successMessage: '接单工单 Mock 已生成',
|
||||
errorMessage: '生成接单工单 Mock 失败',
|
||||
scope: '[admin/worker-platform/orders/mock]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'work_order_mock_created',
|
||||
targetType: 'work_order',
|
||||
targetId: String((data as { order?: { workOrderId?: number } })?.order?.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/:workOrderId/publish',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => publishAdminWorkOrder(String(req.params.workOrderId || '')), {
|
||||
successMessage: '订单已发布到抢单大厅',
|
||||
errorMessage: '发布接单订单失败',
|
||||
scope: '[admin/worker-platform/orders/:workOrderId/publish]',
|
||||
audit: (req, data) => ({
|
||||
action: 'work_order_published',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/:workOrderId/problem',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler((req) => markAdminWorkOrderProblem(String(req.params.workOrderId || ''), req.body || {}), {
|
||||
successMessage: '订单已标记为问题单',
|
||||
errorMessage: '标记问题单失败',
|
||||
scope: '[admin/worker-platform/orders/:workOrderId/problem]',
|
||||
audit: (req, data) => ({
|
||||
action: 'work_order_marked_problem',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/:workOrderId/accept',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => acceptAdminWorkOrder(String(req.params.workOrderId || '')), {
|
||||
successMessage: '订单已验收通过',
|
||||
errorMessage: '验收接单订单失败',
|
||||
scope: '[admin/worker-platform/orders/:workOrderId/accept]',
|
||||
audit: (req, data) => ({
|
||||
action: 'work_order_accepted',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import { createRateLimitMiddleware, getBodyFieldRateLimitKey } from '../middleware/rate-limit.js'
|
||||
import {
|
||||
collectLookupWorkOrder,
|
||||
collectSubmitWorkOrder,
|
||||
} from '../services/worker-platform/worker-platform-service.js'
|
||||
import { buildNotFoundPayload, createRouteHandler } from '../utils/http.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
const collectRateLimit = createRateLimitMiddleware({
|
||||
scope: 'collect',
|
||||
windowMs: 60_000,
|
||||
max: 60,
|
||||
key: getBodyFieldRateLimitKey('orderNo'),
|
||||
})
|
||||
|
||||
router.post(
|
||||
'/lookup',
|
||||
collectRateLimit,
|
||||
createRouteHandler((req) => collectLookupWorkOrder(req.body || {}), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '查询待完善订单失败',
|
||||
scope: '[collect/lookup]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/submit',
|
||||
collectRateLimit,
|
||||
createRouteHandler((req) => collectSubmitWorkOrder(req.body || {}), {
|
||||
successMessage: '资料已提交',
|
||||
errorMessage: '提交补充资料失败',
|
||||
scope: '[collect/submit]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.use((req, res) => {
|
||||
res.status(404).json(buildNotFoundPayload(req))
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,130 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import { createRateLimitMiddleware, getBodyFieldRateLimitKey } from '../middleware/rate-limit.js'
|
||||
import {
|
||||
getWorkerProfile,
|
||||
getWorkerSessionSummary,
|
||||
grabWorkerHallOrder,
|
||||
listWorkerHallOrders,
|
||||
listWorkerMyOrders,
|
||||
loginWorker,
|
||||
registerWorker,
|
||||
submitWorkerOrderAcceptance,
|
||||
} from '../services/worker-platform/worker-platform-service.js'
|
||||
import { buildNotFoundPayload, createRouteHandler } from '../utils/http.js'
|
||||
import {
|
||||
extractWorkerBearerToken,
|
||||
getRequiredWorkerSession,
|
||||
requireActiveWorker,
|
||||
requireWorkerSession,
|
||||
} from './worker/session.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.post(
|
||||
'/auth/register',
|
||||
createRateLimitMiddleware({
|
||||
scope: 'worker:register',
|
||||
windowMs: 60_000,
|
||||
max: 10,
|
||||
key: getBodyFieldRateLimitKey('username'),
|
||||
}),
|
||||
createRouteHandler((req) => registerWorker(req.body || {}), {
|
||||
successMessage: '注册成功,等待后台审核',
|
||||
errorMessage: '接单账号注册失败',
|
||||
scope: '[worker/auth/register]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/auth/login',
|
||||
createRateLimitMiddleware({
|
||||
scope: 'worker:login',
|
||||
windowMs: 60_000,
|
||||
max: 10,
|
||||
key: getBodyFieldRateLimitKey('username'),
|
||||
}),
|
||||
createRouteHandler((req) => loginWorker(req.body?.username, req.body?.password), {
|
||||
successMessage: '登录成功',
|
||||
errorMessage: '接单端登录失败',
|
||||
scope: '[worker/auth/login]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/auth/session',
|
||||
createRouteHandler((req) => getWorkerSessionSummary(extractWorkerBearerToken(req)), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单登录态失败',
|
||||
scope: '[worker/auth/session]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/auth/logout',
|
||||
createRouteHandler(() => ({ success: true }), {
|
||||
successMessage: '已退出登录',
|
||||
errorMessage: '退出失败',
|
||||
scope: '[worker/auth/logout]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.use(requireWorkerSession)
|
||||
|
||||
router.get(
|
||||
'/profile',
|
||||
createRouteHandler((req) => getWorkerProfile(getRequiredWorkerSession(req)), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单员信息失败',
|
||||
scope: '[worker/profile]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/hall/orders',
|
||||
requireActiveWorker,
|
||||
createRouteHandler((req) => listWorkerHallOrders(req.query, getRequiredWorkerSession(req)), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取抢单大厅失败',
|
||||
scope: '[worker/hall/orders]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/hall/orders/:workOrderId/grab',
|
||||
requireActiveWorker,
|
||||
createRouteHandler((req) => grabWorkerHallOrder(String(req.params.workOrderId || ''), getRequiredWorkerSession(req)), {
|
||||
successMessage: '抢单成功',
|
||||
errorMessage: '抢单失败',
|
||||
scope: '[worker/hall/orders/:workOrderId/grab]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/orders',
|
||||
requireActiveWorker,
|
||||
createRouteHandler((req) => listWorkerMyOrders(req.query, getRequiredWorkerSession(req)), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取我的订单失败',
|
||||
scope: '[worker/orders]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/orders/:workOrderId/submit-acceptance',
|
||||
requireActiveWorker,
|
||||
createRouteHandler(
|
||||
(req) => submitWorkerOrderAcceptance(String(req.params.workOrderId || ''), req.body || {}, getRequiredWorkerSession(req)),
|
||||
{
|
||||
successMessage: '验收资料已提交',
|
||||
errorMessage: '提交验收资料失败',
|
||||
scope: '[worker/orders/:workOrderId/submit-acceptance]',
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
router.use((req, res) => {
|
||||
res.status(404).json(buildNotFoundPayload(req))
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
|
||||
import {
|
||||
requireActiveWorkerSession,
|
||||
verifyWorkerSessionToken,
|
||||
type WorkerSession,
|
||||
} from '../../services/worker-platform/worker-platform-service.js'
|
||||
import { createHttpError, sendRouteError } from '../../utils/http.js'
|
||||
|
||||
export async function requireWorkerSession(req: Request, res: Response, next: NextFunction): Promise<void> {
|
||||
try {
|
||||
req.workerSession = await verifyWorkerSessionToken(extractWorkerBearerToken(req))
|
||||
next()
|
||||
} catch (error) {
|
||||
sendRouteError(res, error, '接单端鉴权失败', '[worker/auth]')
|
||||
}
|
||||
}
|
||||
|
||||
export function requireActiveWorker(req: Request, res: Response, next: NextFunction): void {
|
||||
try {
|
||||
requireActiveWorkerSession(req.workerSession)
|
||||
next()
|
||||
} catch (error) {
|
||||
sendRouteError(res, error, '接单账号审核状态无效', '[worker/auth/active]')
|
||||
}
|
||||
}
|
||||
|
||||
export function getRequiredWorkerSession(req: Request): WorkerSession {
|
||||
if (req.workerSession) {
|
||||
return req.workerSession
|
||||
}
|
||||
|
||||
throw createHttpError('未登录或登录已失效', {
|
||||
statusCode: 401,
|
||||
errorCode: 'worker_auth_required',
|
||||
})
|
||||
}
|
||||
|
||||
export function extractWorkerBearerToken(req: Request): string {
|
||||
const authorization = String(req.headers.authorization || '').trim()
|
||||
const matched = authorization.match(/^Bearer\s+(.+)$/i)
|
||||
if (!matched?.[1]) {
|
||||
throw createHttpError('未登录或登录已失效', {
|
||||
statusCode: 401,
|
||||
errorCode: 'worker_auth_required',
|
||||
})
|
||||
}
|
||||
|
||||
return matched[1].trim()
|
||||
}
|
||||
Reference in New Issue
Block a user