支持更新代练中订单价格

This commit is contained in:
yml2213
2026-08-15 17:31:42 +08:00
parent 00491daf5b
commit 57fda860dc
3 changed files with 41 additions and 5 deletions
@@ -754,6 +754,16 @@ export async function submitAdminWorkOrderMaterial(
errorCode: 'work_order_material_status_invalid', errorCode: 'work_order_material_status_invalid',
}) })
} }
if (
workOrder.status === WORK_ORDER_STATUS.IN_PROGRESS &&
workOrder.sharing_enabled === true &&
payload.rewardAmount !== undefined
) {
throw createHttpError('拼单订单的份额奖励已锁定,不能在更新资料时修改价格', {
statusCode: 409,
errorCode: 'work_order_material_reward_sharing_invalid',
})
}
const fields = resolveRequirementFields(workOrder) const fields = resolveRequirementFields(workOrder)
const submittedFields = normalizeSubmittedFields(payload.fields || payload.material || payload) const submittedFields = normalizeSubmittedFields(payload.fields || payload.material || payload)
@@ -762,6 +772,10 @@ export async function submitAdminWorkOrderMaterial(
) )
const now = nowIso() const now = nowIso()
const screenshots = normalizeUploadedFiles(payload.screenshots || payload.files) const screenshots = normalizeUploadedFiles(payload.screenshots || payload.files)
const rewardAmount =
workOrder.status === WORK_ORDER_STATUS.IN_PROGRESS && payload.rewardAmount !== undefined
? normalizeAmountFen(payload.rewardAmount, workOrder.reward_amount)
: workOrder.reward_amount
const material = { const material = {
...safeParseJson(workOrder.material_json), ...safeParseJson(workOrder.material_json),
collect: { collect: {
@@ -781,6 +795,7 @@ export async function submitAdminWorkOrderMaterial(
const updated = await updateWorkOrder(workOrder.id, { const updated = await updateWorkOrder(workOrder.id, {
status: nextStatus, status: nextStatus,
material_json: material, material_json: material,
reward_amount: rewardAmount,
updated_at: now, updated_at: now,
}) })
await createWorkOrderEvent({ await createWorkOrderEvent({
@@ -793,7 +808,7 @@ export async function submitAdminWorkOrderMaterial(
: 'material_completed', : 'material_completed',
fromStatus: workOrder.status, fromStatus: workOrder.status,
toStatus: nextStatus, toStatus: nextStatus,
payloadJson: JSON.stringify({ fields: submittedFields, complete }), payloadJson: JSON.stringify({ fields: submittedFields, complete, rewardAmount }),
now, now,
}) })
return { order: mapWorkOrderAdmin(updated || workOrder), complete } return { order: mapWorkOrderAdmin(updated || workOrder), complete }
@@ -126,6 +126,11 @@ const FILTERABLE_WORK_ORDER_STATUSES = [
'cancelled', 'cancelled',
] as const ] as const
type MaterialFormValues = {
fields?: Record<string, string>
rewardAmount?: number
}
export default function WorkOrdersPanel() { export default function WorkOrdersPanel() {
const { message, modal } = App.useApp() const { message, modal } = App.useApp()
const navigate = useNavigate() const navigate = useNavigate()
@@ -151,7 +156,7 @@ export default function WorkOrdersPanel() {
const [deductOrder, setDeductOrder] = useState<WorkOrder | null>(null) const [deductOrder, setDeductOrder] = useState<WorkOrder | null>(null)
const [problemForm] = Form.useForm() const [problemForm] = Form.useForm()
const [resolutionForm] = Form.useForm() const [resolutionForm] = Form.useForm()
const [materialForm] = Form.useForm() const [materialForm] = Form.useForm<MaterialFormValues>()
const [deductForm] = Form.useForm<{ amount?: number; note?: string }>() const [deductForm] = Form.useForm<{ amount?: number; note?: string }>()
const [editForm] = Form.useForm<{ const [editForm] = Form.useForm<{
productName?: string productName?: string
@@ -378,7 +383,7 @@ export default function WorkOrdersPanel() {
resolutionForm.resetFields() resolutionForm.resetFields()
} }
async function submitMaterial(values: { fields?: Record<string, string> }) { async function submitMaterial(values: MaterialFormValues) {
if (!materialOrder) return if (!materialOrder) return
const succeeded = await runAction( const succeeded = await runAction(
() => () =>
@@ -386,6 +391,9 @@ export default function WorkOrdersPanel() {
materialOrder.workOrderId, materialOrder.workOrderId,
values.fields || {}, values.fields || {},
materialScreenshots, materialScreenshots,
materialOrder.status === 'in_progress' && !materialOrder.sharing?.enabled
? Number(values.rewardAmount || 0)
: undefined,
), ),
materialOrder.status === 'in_progress' ? '订单资料已更新' : '订单资料已保存', materialOrder.status === 'in_progress' ? '订单资料已更新' : '订单资料已保存',
) )
@@ -410,7 +418,10 @@ export default function WorkOrdersPanel() {
function openMaterialModal(row: WorkOrder) { function openMaterialModal(row: WorkOrder) {
setMaterialOrder(row) setMaterialOrder(row)
materialForm.setFieldsValue({ fields: getMaterialFields(row) }) materialForm.setFieldsValue({
fields: getMaterialFields(row),
rewardAmount: Math.round(Number(row.rewardAmount || 0)) / 100,
})
setMaterialScreenshots(getMaterialScreenshots(row)) setMaterialScreenshots(getMaterialScreenshots(row))
} }
@@ -1320,6 +1331,15 @@ export default function WorkOrdersPanel() {
destroyOnHidden destroyOnHidden
> >
<Form form={materialForm} layout="vertical" onFinish={submitMaterial}> <Form form={materialForm} layout="vertical" onFinish={submitMaterial}>
{materialOrder?.status === 'in_progress' && !materialOrder.sharing?.enabled ? (
<Form.Item
label="发单价格"
name="rewardAmount"
rules={[{ required: true, message: '请输入发单价格' }]}
>
<InputNumber min={0} precision={2} addonAfter="元" style={{ width: '100%' }} />
</Form.Item>
) : null}
<Form.Item label="粘贴自动识别"> <Form.Item label="粘贴自动识别">
<Space.Compact style={{ width: '100%' }}> <Space.Compact style={{ width: '100%' }}>
<Input.TextArea <Input.TextArea
@@ -231,10 +231,11 @@ export function submitAdminWorkOrderMaterial(
workOrderId: number, workOrderId: number,
fields: Record<string, string>, fields: Record<string, string>,
screenshots?: UploadedFile[], screenshots?: UploadedFile[],
rewardAmount?: number,
) { ) {
return apiPost<{ order: WorkOrder; complete: boolean }>( return apiPost<{ order: WorkOrder; complete: boolean }>(
`/api/v1/admin/worker-platform/orders/${workOrderId}/material`, `/api/v1/admin/worker-platform/orders/${workOrderId}/material`,
{ fields, screenshots }, { fields, screenshots, rewardAmount },
) )
} }