完善接单平台上传与物品规则
This commit is contained in:
@@ -1,36 +1,38 @@
|
||||
import { Router } from "express";
|
||||
import { Router } from 'express'
|
||||
|
||||
import authRouter from "./admin/auth.js";
|
||||
import auditLogsRouter from "./admin/audit-logs.js";
|
||||
import cloudtentaclesRecordsRouter from "./admin/cloudtentacles-records.js";
|
||||
import dashboardRouter from "./admin/dashboard.js";
|
||||
import devMockRouter from "./admin/dev-mock.js";
|
||||
import kuaishouIndustryRouter from "./admin/kuaishou-industry.js";
|
||||
import ordersRouter from "./admin/orders.js";
|
||||
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";
|
||||
import authRouter from './admin/auth.js'
|
||||
import auditLogsRouter from './admin/audit-logs.js'
|
||||
import cloudtentaclesRecordsRouter from './admin/cloudtentacles-records.js'
|
||||
import dashboardRouter from './admin/dashboard.js'
|
||||
import devMockRouter from './admin/dev-mock.js'
|
||||
import filesRouter from './admin/files.js'
|
||||
import kuaishouIndustryRouter from './admin/kuaishou-industry.js'
|
||||
import ordersRouter from './admin/orders.js'
|
||||
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();
|
||||
const router = Router()
|
||||
|
||||
router.use(authRouter);
|
||||
router.use(requireAdminSession);
|
||||
router.use(dashboardRouter);
|
||||
router.use(usersRouter);
|
||||
router.use(auditLogsRouter);
|
||||
router.use(platformConfigRouter);
|
||||
router.use(kuaishouIndustryRouter);
|
||||
router.use(ordersRouter);
|
||||
router.use(tasksRouter);
|
||||
router.use(cloudtentaclesRecordsRouter);
|
||||
router.use(workerPlatformRouter);
|
||||
router.use(devMockRouter);
|
||||
router.use(authRouter)
|
||||
router.use(requireAdminSession)
|
||||
router.use(filesRouter)
|
||||
router.use(dashboardRouter)
|
||||
router.use(usersRouter)
|
||||
router.use(auditLogsRouter)
|
||||
router.use(platformConfigRouter)
|
||||
router.use(kuaishouIndustryRouter)
|
||||
router.use(ordersRouter)
|
||||
router.use(tasksRouter)
|
||||
router.use(cloudtentaclesRecordsRouter)
|
||||
router.use(workerPlatformRouter)
|
||||
router.use(devMockRouter)
|
||||
|
||||
router.use((req, res) => {
|
||||
res.status(404).json(buildNotFoundPayload(req));
|
||||
});
|
||||
res.status(404).json(buildNotFoundPayload(req))
|
||||
})
|
||||
|
||||
export default router;
|
||||
export default router
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import { uploadSingleFile } from '../file-upload.js'
|
||||
import { uploadFileAsset } from '../../services/file-storage/file-storage-service.js'
|
||||
import { createJsonHandler, getRequiredAdminSession, requireAdminRoles } from './session.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.post(
|
||||
'/files/upload',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
uploadSingleFile,
|
||||
createJsonHandler(
|
||||
(req) => {
|
||||
const session = getRequiredAdminSession(req)
|
||||
return uploadFileAsset({
|
||||
file: req.file,
|
||||
scene: req.body?.scene,
|
||||
uploaderType: 'admin',
|
||||
uploaderId: String(session.userId || session.username || ''),
|
||||
})
|
||||
},
|
||||
{
|
||||
successMessage: '文件已上传',
|
||||
errorMessage: '文件上传失败',
|
||||
scope: '[admin/files/upload]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'file_uploaded',
|
||||
targetType: 'file',
|
||||
targetId: String((data as { file?: { objectKey?: string } })?.file?.objectKey || ''),
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
export default router
|
||||
@@ -5,13 +5,19 @@ import {
|
||||
creditAdminWorkerWallet,
|
||||
createAdminMockWorkOrder,
|
||||
getAdminWorkerPlatformSummary,
|
||||
listAdminWorkCategories,
|
||||
listAdminWorkProductRules,
|
||||
listAdminWorkerLevels,
|
||||
listAdminWorkerUsers,
|
||||
listAdminWorkOrders,
|
||||
markAdminWorkOrderProblem,
|
||||
publishAdminWorkOrder,
|
||||
reviewAdminWorkerUser,
|
||||
saveAdminWorkCategory,
|
||||
saveAdminWorkProductRule,
|
||||
saveAdminWorkerLevel,
|
||||
submitAdminWorkOrderMaterial,
|
||||
syncAdminWorkerOrdersFromSource,
|
||||
} from '../../services/worker-platform/worker-platform-service.js'
|
||||
import { createJsonHandler, requireAdminRoles } from './session.js'
|
||||
|
||||
@@ -47,7 +53,61 @@ router.post(
|
||||
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> : {},
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/worker-platform/categories',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler(() => listAdminWorkCategories(), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单分类失败',
|
||||
scope: '[admin/worker-platform/categories]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/categories',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => saveAdminWorkCategory(req.body || {}), {
|
||||
successMessage: '接单分类已保存',
|
||||
errorMessage: '保存接单分类失败',
|
||||
scope: '[admin/worker-platform/categories]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'work_category_saved',
|
||||
targetType: 'work_category',
|
||||
targetId: String(
|
||||
(data as { category?: { categoryKey?: string } })?.category?.categoryKey || '',
|
||||
),
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/worker-platform/product-rules',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler((req) => listAdminWorkProductRules(req.query), {
|
||||
successMessage: 'ok',
|
||||
errorMessage: '读取接单物品规则失败',
|
||||
scope: '[admin/worker-platform/product-rules]',
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/product-rules',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => saveAdminWorkProductRule(req.body || {}), {
|
||||
successMessage: '接单物品规则已保存',
|
||||
errorMessage: '保存接单物品规则失败',
|
||||
scope: '[admin/worker-platform/product-rules]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'work_product_rule_saved',
|
||||
targetType: 'work_product_rule',
|
||||
targetId: String((data as { rule?: { ruleKey?: string } })?.rule?.ruleKey || ''),
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
@@ -65,33 +125,39 @@ router.get(
|
||||
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> : {},
|
||||
}),
|
||||
}),
|
||||
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> : {},
|
||||
}),
|
||||
}),
|
||||
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(
|
||||
@@ -115,11 +181,46 @@ router.post(
|
||||
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> : {},
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/source-orders/sync',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
createJsonHandler((req) => syncAdminWorkerOrdersFromSource(req.body || {}), {
|
||||
successMessage: '源订单同步完成',
|
||||
errorMessage: '同步源订单失败',
|
||||
scope: '[admin/worker-platform/source-orders/sync]',
|
||||
audit: (_req, data) => ({
|
||||
action: 'work_order_source_synced',
|
||||
targetType: 'source_order',
|
||||
targetId: '',
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/:workOrderId/material',
|
||||
requireAdminRoles(['admin', 'operator', 'support']),
|
||||
createJsonHandler(
|
||||
(req) => submitAdminWorkOrderMaterial(String(req.params.workOrderId || ''), req.body || {}),
|
||||
{
|
||||
successMessage: '订单资料已保存',
|
||||
errorMessage: '补充订单资料失败',
|
||||
scope: '[admin/worker-platform/orders/:workOrderId/material]',
|
||||
audit: (req, data) => ({
|
||||
action: 'work_order_material_saved',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/worker-platform/orders/:workOrderId/publish',
|
||||
requireAdminRoles(['admin', 'operator']),
|
||||
@@ -131,7 +232,7 @@ router.post(
|
||||
action: 'work_order_published',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
@@ -139,17 +240,20 @@ router.post(
|
||||
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> : {},
|
||||
}),
|
||||
}),
|
||||
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(
|
||||
@@ -163,7 +267,7 @@ router.post(
|
||||
action: 'work_order_accepted',
|
||||
targetType: 'work_order',
|
||||
targetId: String(req.params.workOrderId || ''),
|
||||
data: data && typeof data === 'object' ? data as Record<string, unknown> : {},
|
||||
data: data && typeof data === 'object' ? (data as Record<string, unknown>) : {},
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
import multer from 'multer'
|
||||
|
||||
import { getMaxUploadSizeBytes } from '../services/file-storage/file-storage-service.js'
|
||||
import { createHttpError, sendRouteError } from '../utils/http.js'
|
||||
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: {
|
||||
fileSize: getMaxUploadSizeBytes(),
|
||||
files: 1,
|
||||
},
|
||||
})
|
||||
|
||||
export function uploadSingleFile(req: Request, res: Response, next: NextFunction): void {
|
||||
upload.single('file')(req, res, (error: unknown) => {
|
||||
if (!error) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
||||
const normalizedError =
|
||||
error instanceof multer.MulterError && error.code === 'LIMIT_FILE_SIZE'
|
||||
? createHttpError('文件超过上传大小限制', {
|
||||
statusCode: 400,
|
||||
errorCode: 'upload_file_too_large',
|
||||
cause: error,
|
||||
})
|
||||
: createHttpError('文件上传失败', {
|
||||
statusCode: 400,
|
||||
errorCode: 'upload_file_invalid',
|
||||
cause: error,
|
||||
})
|
||||
sendRouteError(res, normalizedError, '文件上传失败', '[files/upload]')
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import { getStoredFileObject } from '../services/file-storage/file-storage-service.js'
|
||||
import { buildNotFoundPayload, sendRouteError } from '../utils/http.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.get('/object', async (req, res) => {
|
||||
try {
|
||||
const object = await getStoredFileObject(req.query.key, req.query.variant)
|
||||
res.setHeader('Content-Type', object.contentType || 'application/octet-stream')
|
||||
res.setHeader('Cache-Control', 'private, max-age=300')
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff')
|
||||
object.reader.on('error', (error) => {
|
||||
if (!res.headersSent) {
|
||||
sendRouteError(res, error, '读取文件失败', '[files/object]')
|
||||
} else {
|
||||
res.destroy(error)
|
||||
}
|
||||
})
|
||||
object.reader.pipe(res)
|
||||
} catch (error) {
|
||||
sendRouteError(res, error, '读取文件失败', '[files/object]')
|
||||
}
|
||||
})
|
||||
|
||||
router.use((req, res) => {
|
||||
res.status(404).json(buildNotFoundPayload(req))
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Router } from 'express'
|
||||
|
||||
import { createRateLimitMiddleware, getBodyFieldRateLimitKey } from '../middleware/rate-limit.js'
|
||||
import { uploadSingleFile } from './file-upload.js'
|
||||
import { uploadFileAsset } from '../services/file-storage/file-storage-service.js'
|
||||
import {
|
||||
getWorkerProfile,
|
||||
getWorkerSessionSummary,
|
||||
@@ -80,6 +82,28 @@ router.get(
|
||||
}),
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/files/upload',
|
||||
requireActiveWorker,
|
||||
uploadSingleFile,
|
||||
createRouteHandler(
|
||||
(req) => {
|
||||
const session = getRequiredWorkerSession(req)
|
||||
return uploadFileAsset({
|
||||
file: req.file,
|
||||
scene: req.body?.scene || 'worker-acceptance',
|
||||
uploaderType: 'worker',
|
||||
uploaderId: String(session.workerId),
|
||||
})
|
||||
},
|
||||
{
|
||||
successMessage: '文件已上传',
|
||||
errorMessage: '文件上传失败',
|
||||
scope: '[worker/files/upload]',
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
router.get(
|
||||
'/hall/orders',
|
||||
requireActiveWorker,
|
||||
@@ -93,11 +117,15 @@ router.get(
|
||||
router.post(
|
||||
'/hall/orders/:workOrderId/grab',
|
||||
requireActiveWorker,
|
||||
createRouteHandler((req) => grabWorkerHallOrder(String(req.params.workOrderId || ''), getRequiredWorkerSession(req)), {
|
||||
successMessage: '抢单成功',
|
||||
errorMessage: '抢单失败',
|
||||
scope: '[worker/hall/orders/:workOrderId/grab]',
|
||||
}),
|
||||
createRouteHandler(
|
||||
(req) =>
|
||||
grabWorkerHallOrder(String(req.params.workOrderId || ''), getRequiredWorkerSession(req)),
|
||||
{
|
||||
successMessage: '抢单成功',
|
||||
errorMessage: '抢单失败',
|
||||
scope: '[worker/hall/orders/:workOrderId/grab]',
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
router.get(
|
||||
@@ -114,7 +142,12 @@ router.post(
|
||||
'/orders/:workOrderId/submit-acceptance',
|
||||
requireActiveWorker,
|
||||
createRouteHandler(
|
||||
(req) => submitWorkerOrderAcceptance(String(req.params.workOrderId || ''), req.body || {}, getRequiredWorkerSession(req)),
|
||||
(req) =>
|
||||
submitWorkerOrderAcceptance(
|
||||
String(req.params.workOrderId || ''),
|
||||
req.body || {},
|
||||
getRequiredWorkerSession(req),
|
||||
),
|
||||
{
|
||||
successMessage: '验收资料已提交',
|
||||
errorMessage: '提交验收资料失败',
|
||||
|
||||
Reference in New Issue
Block a user