import { request, uploadDirectFile, uploadFile } from "../utils/request"; import type { AdminSessionInfo } from "../utils/auth"; export interface AdminLoginResponse { token: string; admin_info: AdminSessionInfo; } export interface AdminFileAsset { file_id: string; file_url: string; thumbnail_url: string; name?: string; file_type?: string; mime_type?: string; } export interface AdminDirectUploadMeta { original_name?: string; file_size?: number; mime_type?: string; } export type AdminUploadScene = "appraisal_evidence" | "zhongjian_report" | "warehouse_inbound_evidence" | "warehouse_return_packing"; export interface AdminDirectUploadPolicy { enabled: boolean; upload_url?: string; form_data?: Record; asset?: AdminFileAsset; max_size?: number; max_size_text?: string; expires_at?: string; } export interface AdminExpressCompanyItem { id: number; company_name: string; company_code: string; status: string; status_text: string; is_default: boolean; sort_order: number; remark: string; created_at: string; updated_at: string; } function filenameFromPath(filePath: string) { return filePath.split(/[\\/]/).pop() || `upload-${Date.now()}`; } async function uploadManagedAdminFile( filePath: string, scene: AdminUploadScene, fallbackUrl: string, meta: AdminDirectUploadMeta = {}, fallbackFormData: Record = {}, ) { const policy = await request("/api/admin/file-upload/direct-policy", { method: "POST", data: { upload_scene: scene, original_name: meta.original_name || filenameFromPath(filePath), file_size: meta.file_size || 0, mime_type: meta.mime_type || "", }, }); const formData = { ...fallbackFormData, upload_scene: scene }; if (!policy.enabled) { return uploadFile(fallbackUrl, filePath, formData); } if (!policy.upload_url || !policy.form_data || !policy.asset) { throw new Error("OSS 上传签名无效,请稍后重试"); } await uploadDirectFile(policy.upload_url, filePath, policy.form_data); return policy.asset; } export interface PaginatedList { list: T[]; total?: number; page?: number; page_size?: number; } export interface AdminOrderListItem { id: number; order_no: string; appraisal_no: string; product_name: string; category_name: string; brand_name: string; service_provider: string; service_provider_text: string; source_channel: string; source_channel_text: string; source_customer_id: string; order_status: string; display_status: string; internal_tag_no?: string; warehouse_bucket?: string; warehouse_bucket_text?: string; estimated_finish_time: string; pay_amount: number; created_at: string; } export interface AdminManualOrderMaterialItem { item_code: string; item_name: string; is_required: boolean; files: AdminFileAsset[]; } export interface AdminManualOrderCreatePayload { service_provider: string; product_info: { category_id: number; brand_id: number; brand_name: string; product_name: string; color: string; size_spec: string; serial_no: string; }; extra_info: { purchase_channel: string; purchase_price: number; usage_status: string; condition_desc: string; remark: string; }; return_address: { consignee: string; mobile: string; province: string; city: string; district: string; detail_address: string; }; materials: AdminManualOrderMaterialItem[]; } export interface AdminManualOrderCreateResponse { order_id: number; order_no: string; appraisal_no: string; user_id: number; next_status: "pending_shipping"; } export interface AdminManualOrderMeta { categories: Array<{ id: number; name: string; code: string; supported_service_types: string[]; }>; brands: Array<{ id: number; name: string; en_name: string; code: string; category_ids: number[]; supported_service_types: string[]; }>; } export interface AdminOrderDetail { order_info: AdminOrderListItem & { can_mark_received: boolean; can_submit_return_logistics: boolean; return_logistics_block_reason: string; }; product_info: { product_name: string; category_name: string; brand_name: string; color: string; size_spec: string; serial_no: string; }; extra_info: Record; shipping_target: null | Record; return_address: null | { consignee: string; mobile: string; full_address: string; }; logistics_info: null | Record; inbound_attachments: AdminFileAsset[]; transfer_flow: null | { internal_tag_no: string; }; return_logistics: null | Record; supplement_task: null | Record; report_summary: null | { id?: number; report_no: string; report_title: string; report_status: string; report_status_text?: string; publish_time: string; }; timeline: Array<{ node_text: string; node_desc: string; occurred_at: string; }>; } export interface AdminWarehouseWorkbenchContext { order_info: { id: number; order_no: string; appraisal_no: string; service_provider: string; service_provider_text: string; source_channel: string; source_channel_text: string; source_customer_id: string; order_status: string; display_status: string; }; product_info: { product_name: string; category_name: string; brand_name: string; color: string; size_spec: string; serial_no: string; }; logistics_info: null | { express_company: string; tracking_no: string; tracking_status: string; }; return_address: null | { consignee: string; mobile: string; full_address: string; }; return_logistics: null | { express_company: string; tracking_no: string; tracking_status: string; }; transfer_flow: null | { id?: number; internal_tag_no: string; flow_status?: string; current_stage: string; current_stage_text: string; current_location: string; current_location_text: string; return_confirmed_at?: string; return_shipped_at?: string; }; report_info: null | { id: number; report_no: string; report_status: string; publish_time: string; zhongjian_report_no: string; zhongjian_report_files: AdminFileAsset[]; }; flow_logs?: Array<{ id: number; action_text: string; operator_name: string; remark: string; created_at: string; inbound_attachments?: AdminFileAsset[]; packing_attachments?: AdminFileAsset[]; }>; return_verification?: { verified: boolean; report_id: number; report_no: string; }; next_action?: string; next_action_text?: string; } export interface AdminAppraisalTaskListItem { id: number; order_id: number; order_no: string; appraisal_no: string; external_order_no: string; service_provider: string; service_provider_text: string; task_stage: string; task_stage_text: string; status: string; status_text: string; assignee_id: number; product_name: string; category_name: string; brand_name: string; assignee_name: string; result_text: string; started_at: string; submitted_at: string; sla_deadline: string; is_overtime: boolean; display_status: string; internal_tag_no?: string; } export interface AdminAppraisalTaskDetail { task_info: AdminAppraisalTaskListItem & { is_overtime: boolean; }; report_summary: null | { id: number; report_no: string; report_status: string; report_status_text: string; }; material_tag?: null | Record; product_info: { product_name: string; category_id: number; category_name: string; brand_id: number; brand_name: string; color: string; size_spec: string; serial_no: string; }; extra_info: Record; result_info: { result_text: string; result_desc: string; condition_grade: string; condition_desc?: string; valuation_min: number; valuation_max: number; valuation_desc?: string; attachments: AdminFileAsset[]; external_remark: string; internal_remark: string; key_points: Array<{ point_code: string; point_name: string; point_value: string; point_remark: string; }>; }; prefill_result_info?: null | (AdminAppraisalTaskDetail["result_info"] & { source_task_id?: number; source_stage?: string; source_stage_text?: string; }); appraisal_template: null | { id?: number; name?: string; code?: string; service_provider?: string; service_provider_text?: string; result_options: string[]; condition_options: string[]; valuation_hint?: string; key_points: Array<{ point_code: string; point_name: string; point_type: "text" | "textarea" | "select" | "boolean"; options: string[]; sort_order?: number; is_required: boolean; point_value: string; point_remark: string; }>; }; stage_tasks?: Array; timeline: Array<{ node_text: string; node_desc: string; occurred_at: string; }>; materials: Array<{ item_name: string; status: string; source_type: string; files: Array<{ file_id: string; file_url: string; thumbnail_url: string; }>; }>; supplement_task: null | { id: number; reason: string; deadline: string; status: string; items: Array<{ item_name: string; guide_text: string; is_required: boolean; }>; }; zhongjian_report: { report_no: string; files: AdminFileAsset[]; }; } export interface AdminReportListItem { id: number; order_id: number; order_no: string; appraisal_no: string; report_no: string; report_type: string; report_type_text: string; report_title: string; report_status: string; report_status_text: string; service_provider: string; service_provider_text: string; institution_name: string; publish_time: string; zhongjian_report_no: string; report_entry_admin_name: string; report_entered_at: string; product_name: string; category_name: string; brand_name: string; } export interface AdminReportDetail { report_header: Partial & { id: number; order_id: number; report_no: string; report_type: string; report_type_text: string; report_title: string; report_status: string; report_status_text: string; service_provider: string; service_provider_text: string; institution_name: string; publish_time: string; zhongjian_report_no: string; report_entry_admin_id: number; report_entry_admin_name: string; report_entered_at: string; }; product_info: Record; result_info: Record; appraisal_info: Record; valuation_info: Record; evidence_attachments: AdminFileAsset[]; zhongjian_report_files: AdminFileAsset[]; risk_notice_text: string; verify_info: { verify_status: string; verify_url: string; verify_qrcode_url: string; report_page_url: string; verify_count: number; }; } export const adminApi = { login(mobile: string, password: string) { return request("/api/admin/auth/login", { method: "POST", data: { mobile, password }, }); }, getAuthMe() { return request<{ admin_info: AdminSessionInfo }>("/api/admin/auth/me"); }, logout() { return request>("/api/admin/auth/logout", { method: "POST" }); }, getOrders(params?: Record) { return request>("/api/admin/orders", { params }); }, getOrderDetail(id: number) { return request("/api/admin/order/detail", { params: { id } }); }, getManualOrderMeta() { return request("/api/admin/manual-order/meta"); }, getExpressCompanies(params: { enabled_only?: 0 | 1 } = { enabled_only: 1 }) { return request<{ list: AdminExpressCompanyItem[]; default_company: string }>("/api/admin/express-companies", { params }); }, createManualOrder(data: AdminManualOrderCreatePayload) { return request("/api/admin/manual-order/create", { method: "POST", data: data as unknown as Record, }); }, uploadManualOrderFile(filePath: string) { return uploadFile("/api/admin/manual-order/file/upload", filePath); }, lookupWarehouseInbound(inboundNo: string) { return request("/api/admin/warehouse-workbench/inbound/lookup", { params: { inbound_no: inboundNo }, }); }, receiveWarehouseInbound(data: { inbound_no: string; internal_tag_no: string; inbound_attachments?: AdminFileAsset[] }) { return request("/api/admin/warehouse-workbench/inbound/receive", { method: "POST", data, }); }, uploadWarehouseInboundEvidenceFile(filePath: string, meta: AdminDirectUploadMeta = {}) { return uploadManagedAdminFile( filePath, "warehouse_inbound_evidence", "/api/admin/warehouse-workbench/inbound/evidence/upload", meta, ); }, lookupZhongjianWarehouseTransfer(internalTagNo: string) { return request("/api/admin/warehouse-workbench/zhongjian/lookup", { params: { internal_tag_no: internalTagNo }, }); }, zhongjianWarehouseOutbound(internalTagNo: string) { return request("/api/admin/warehouse-workbench/zhongjian/outbound", { method: "POST", data: { internal_tag_no: internalTagNo }, }); }, zhongjianWarehouseInbound(internalTagNo: string) { return request("/api/admin/warehouse-workbench/zhongjian/inbound", { method: "POST", data: { internal_tag_no: internalTagNo }, }); }, lookupWarehouseReturn(internalTagNo: string) { return request("/api/admin/warehouse-workbench/return/lookup", { params: { internal_tag_no: internalTagNo }, }); }, verifyWarehouseReturnMaterialTag(data: { internal_tag_no: string; qr_input: string }) { return request("/api/admin/warehouse-workbench/return/material-tag/verify", { method: "POST", data, }); }, confirmWarehouseReturnReport(data: { internal_tag_no: string; report_id: number }) { return request("/api/admin/warehouse-workbench/return/report/confirm", { method: "POST", data, }); }, confirmWarehouseReturnZhongjian(internalTagNo: string) { return request("/api/admin/warehouse-workbench/return/zhongjian/confirm", { method: "POST", data: { internal_tag_no: internalTagNo }, }); }, uploadWarehouseReturnPackingFile(filePath: string, meta: AdminDirectUploadMeta = {}) { return uploadManagedAdminFile( filePath, "warehouse_return_packing", "/api/admin/warehouse-workbench/return/packing/upload", meta, ); }, shipWarehouseReturn(data: { internal_tag_no: string; express_company: string; tracking_no: string; packing_attachments?: AdminFileAsset[] }) { return request("/api/admin/warehouse-workbench/return/ship", { method: "POST", data, }); }, getAppraisalTasks(params?: Record) { return request>("/api/admin/appraisal-tasks", { params }); }, getAppraisalTaskDetail(id: number) { return request("/api/admin/appraisal-task/detail", { params: { id } }); }, scanAppraisalTransferTag(internalTagNo: string) { return request<{ task_id: number; order_id: number; service_provider: string; service_provider_text: string }>( "/api/admin/appraisal-task/transfer-tag/scan", { method: "POST", data: { internal_tag_no: internalTagNo } }, ); }, saveAppraisalTaskResult(data: Record) { return request<{ id: number }>("/api/admin/appraisal-task/save-result", { method: "POST", data }); }, requestAppraisalTaskSupplement(data: Record) { return request<{ id: number; supplement_task_id: number }>("/api/admin/appraisal-task/request-supplement", { method: "POST", data, }); }, saveZhongjianAppraisalReport(data: Record) { return request<{ id: number; report: Record }>("/api/admin/appraisal-task/zhongjian-report/save", { method: "POST", data, }); }, publishAppraisalTaskWithMaterialTag(data: { id: number; qr_input: string }) { return request>("/api/admin/appraisal-task/material-tag/publish", { method: "POST", data, }); }, uploadAppraisalEvidenceFile( filePath: string, taskId?: number, meta: AdminDirectUploadMeta = {}, scene: AdminUploadScene = "appraisal_evidence", ) { const formData: Record = taskId ? { task_id: taskId } : {}; return uploadManagedAdminFile(filePath, scene, "/api/admin/appraisal-task/evidence/upload", meta, formData); }, deleteAppraisalEvidenceFile(fileUrl: string, taskId?: number) { return request<{ file_url: string }>("/api/admin/appraisal-task/evidence/delete", { method: "POST", data: { file_url: fileUrl, ...(taskId ? { task_id: taskId } : {}) }, }); }, getReports(params?: Record) { return request>("/api/admin/reports", { params }); }, getReportDetail(id: number) { return request("/api/admin/report/detail", { params: { id } }); }, };