first
This commit is contained in:
663
server-api/app/controller/app/AppraisalController.php
Normal file
663
server-api/app/controller/app/AppraisalController.php
Normal file
@@ -0,0 +1,663 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller\app;
|
||||
|
||||
use app\support\MessageDispatcher;
|
||||
use app\support\ContentService;
|
||||
use app\support\FileStorageService;
|
||||
use app\support\PublicAssetUrlService;
|
||||
use app\support\WarehouseService;
|
||||
use support\Request;
|
||||
use support\think\Db;
|
||||
use function str_starts_with;
|
||||
|
||||
class AppraisalController
|
||||
{
|
||||
public function uploadFile(Request $request)
|
||||
{
|
||||
$userId = app_user_id($request);
|
||||
$draftId = (int)$request->post('draft_id', 0);
|
||||
$itemCode = trim((string)$request->post('item_code', ''));
|
||||
$itemName = trim((string)$request->post('item_name', ''));
|
||||
|
||||
if (!$draftId || $itemCode === '') {
|
||||
return api_error('草稿 ID 和资料项编码不能为空', 422);
|
||||
}
|
||||
|
||||
$draft = Db::name('appraisal_drafts')->where('id', $draftId)->where('user_id', $userId)->find();
|
||||
if (!$draft) {
|
||||
return api_error('草稿不存在', 404);
|
||||
}
|
||||
|
||||
$file = $request->file('file');
|
||||
if (!$file || !$file->isValid()) {
|
||||
return api_error('上传文件无效', 422);
|
||||
}
|
||||
|
||||
$extension = strtolower($file->getUploadExtension() ?: 'jpg');
|
||||
$filename = sprintf('%s_%s.%s', $itemCode, uniqid(), $extension);
|
||||
$relativeDir = 'uploads/appraisal/' . date('Ymd');
|
||||
$relativePath = $relativeDir . '/' . $filename;
|
||||
$this->storage()->putUploadedFile($file, $relativePath);
|
||||
|
||||
$fileUrl = $this->storage()->publicUrl($request, $relativePath);
|
||||
|
||||
return api_success([
|
||||
'file_id' => md5($relativePath),
|
||||
'item_code' => $itemCode,
|
||||
'item_name' => $itemName,
|
||||
'file_url' => $fileUrl,
|
||||
'thumbnail_url' => $fileUrl,
|
||||
'name' => $file->getUploadName(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function createDraft(Request $request)
|
||||
{
|
||||
$userId = app_user_id($request);
|
||||
$serviceProvider = (string)$request->input('service_provider', 'anxinyan');
|
||||
$serviceMode = (string)$request->input('service_mode', 'physical');
|
||||
|
||||
$draftId = Db::name('appraisal_drafts')->insertGetId([
|
||||
'user_id' => $userId,
|
||||
'service_mode' => $serviceMode,
|
||||
'service_provider' => $serviceProvider,
|
||||
'current_step' => 1,
|
||||
'status' => 'draft',
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
return api_success([
|
||||
'draft_id' => (int)$draftId,
|
||||
'service_provider' => $serviceProvider,
|
||||
'service_mode' => $serviceMode,
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteFile(Request $request)
|
||||
{
|
||||
$fileUrl = trim((string)$request->post('file_url', ''));
|
||||
if ($fileUrl === '') {
|
||||
return api_error('文件地址不能为空', 422);
|
||||
}
|
||||
|
||||
$relativePath = $this->storage()->storagePath($fileUrl);
|
||||
if (!str_starts_with($relativePath, 'uploads/appraisal/')) {
|
||||
return api_error('不允许删除该文件', 403);
|
||||
}
|
||||
|
||||
$this->storage()->delete($relativePath);
|
||||
|
||||
return api_success([
|
||||
'file_url' => $fileUrl,
|
||||
], '删除成功');
|
||||
}
|
||||
|
||||
public function draftDetail(Request $request)
|
||||
{
|
||||
$draftId = (int)$request->input('draft_id', 0);
|
||||
$draft = Db::name('appraisal_drafts')->where('id', $draftId)->where('user_id', app_user_id($request))->find();
|
||||
if (!$draft) {
|
||||
return api_error('草稿不存在', 404);
|
||||
}
|
||||
|
||||
$product = Db::name('appraisal_draft_products')->where('draft_id', $draftId)->find();
|
||||
$extra = Db::name('appraisal_draft_extras')->where('draft_id', $draftId)->find();
|
||||
|
||||
return api_success([
|
||||
'draft_id' => (int)$draft['id'],
|
||||
'service_provider' => $draft['service_provider'],
|
||||
'service_mode' => $draft['service_mode'],
|
||||
'current_step' => (int)$draft['current_step'],
|
||||
'product_info' => $product ?: new \stdClass(),
|
||||
'extra_info' => $extra ?: new \stdClass(),
|
||||
'upload_info' => [
|
||||
'items' => $this->draftUploadItems($draftId, $request),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function saveDraft(Request $request)
|
||||
{
|
||||
$draftId = (int)$request->input('draft_id', 0);
|
||||
$draft = Db::name('appraisal_drafts')->where('id', $draftId)->where('user_id', app_user_id($request))->find();
|
||||
if (!$draft) {
|
||||
return api_error('草稿不存在', 404);
|
||||
}
|
||||
|
||||
$currentStep = (int)$request->input('current_step', $draft['current_step']);
|
||||
$productInfo = (array)$request->input('product_info', []);
|
||||
$extraInfo = (array)$request->input('extra_info', []);
|
||||
$uploadInfo = (array)$request->input('upload_info', []);
|
||||
|
||||
Db::name('appraisal_drafts')
|
||||
->where('id', $draftId)
|
||||
->update([
|
||||
'service_provider' => $request->input('service_provider', $draft['service_provider']),
|
||||
'current_step' => $currentStep,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
if ($productInfo) {
|
||||
$payload = [
|
||||
'draft_id' => $draftId,
|
||||
'category_id' => $productInfo['category_id'] ?? null,
|
||||
'brand_id' => $productInfo['brand_id'] ?? null,
|
||||
'color' => $productInfo['color'] ?? '',
|
||||
'size_spec' => $productInfo['size_spec'] ?? '',
|
||||
'serial_no' => $productInfo['serial_no'] ?? '',
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
$exists = Db::name('appraisal_draft_products')->where('draft_id', $draftId)->find();
|
||||
if ($exists) {
|
||||
Db::name('appraisal_draft_products')->where('draft_id', $draftId)->update($payload);
|
||||
} else {
|
||||
$payload['created_at'] = date('Y-m-d H:i:s');
|
||||
Db::name('appraisal_draft_products')->insert($payload);
|
||||
}
|
||||
}
|
||||
|
||||
if ($extraInfo) {
|
||||
$purchaseDate = $extraInfo['purchase_date'] ?? null;
|
||||
if ($purchaseDate === '') {
|
||||
$purchaseDate = null;
|
||||
}
|
||||
$payload = [
|
||||
'draft_id' => $draftId,
|
||||
'purchase_channel' => $extraInfo['purchase_channel'] ?? '',
|
||||
'purchase_price' => $extraInfo['purchase_price'] ?? 0,
|
||||
'purchase_date' => $purchaseDate,
|
||||
'usage_status' => $extraInfo['usage_status'] ?? '',
|
||||
'condition_desc' => $extraInfo['condition_desc'] ?? '',
|
||||
'has_accessories' => !empty($extraInfo['accessories']) ? 1 : 0,
|
||||
'accessories_json' => json_encode($extraInfo['accessories'] ?? [], JSON_UNESCAPED_UNICODE),
|
||||
'remark' => $extraInfo['remark'] ?? '',
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
$exists = Db::name('appraisal_draft_extras')->where('draft_id', $draftId)->find();
|
||||
if ($exists) {
|
||||
Db::name('appraisal_draft_extras')->where('draft_id', $draftId)->update($payload);
|
||||
} else {
|
||||
$payload['created_at'] = date('Y-m-d H:i:s');
|
||||
Db::name('appraisal_draft_extras')->insert($payload);
|
||||
}
|
||||
}
|
||||
|
||||
if ($uploadInfo) {
|
||||
$draftUploadIds = Db::name('appraisal_draft_uploads')->where('draft_id', $draftId)->column('id');
|
||||
if ($draftUploadIds) {
|
||||
Db::name('appraisal_draft_upload_files')->whereIn('draft_upload_id', $draftUploadIds)->delete();
|
||||
}
|
||||
Db::name('appraisal_draft_uploads')->where('draft_id', $draftId)->delete();
|
||||
foreach (($uploadInfo['items'] ?? []) as $item) {
|
||||
$draftUploadId = Db::name('appraisal_draft_uploads')->insertGetId([
|
||||
'draft_id' => $draftId,
|
||||
'template_id' => $uploadInfo['template_id'] ?? null,
|
||||
'item_code' => $item['item_code'] ?? '',
|
||||
'item_name' => $item['item_name'] ?? '',
|
||||
'is_required' => !empty($item['is_required']) ? 1 : 0,
|
||||
'quality_status' => $item['quality_status'] ?? 'pending',
|
||||
'quality_message' => $item['quality_message'] ?? '',
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
foreach (($item['files'] ?? []) as $index => $file) {
|
||||
Db::name('appraisal_draft_upload_files')->insert([
|
||||
'draft_upload_id' => $draftUploadId,
|
||||
'file_id' => $file['file_id'] ?? '',
|
||||
'file_url' => $this->assetUrlService()->storagePath((string)($file['file_url'] ?? '')),
|
||||
'thumbnail_url' => $this->assetUrlService()->storagePath((string)($file['thumbnail_url'] ?? ($file['file_url'] ?? ''))),
|
||||
'sort_order' => $index,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return api_success(['draft_id' => $draftId, 'current_step' => $currentStep]);
|
||||
}
|
||||
|
||||
public function uploadTemplate(Request $request)
|
||||
{
|
||||
$categoryId = (int)$request->input('category_id', 1);
|
||||
$serviceProvider = (string)$request->input('service_provider', 'anxinyan');
|
||||
|
||||
$template = Db::name('upload_templates')
|
||||
->where('scope_type', 'category')
|
||||
->where('scope_id', $categoryId)
|
||||
->where('service_provider', $serviceProvider)
|
||||
->where('is_enabled', 1)
|
||||
->find();
|
||||
|
||||
if (!$template) {
|
||||
$template = Db::name('upload_templates')
|
||||
->where('scope_type', 'category')
|
||||
->where('scope_id', $categoryId)
|
||||
->where('service_provider', 'anxinyan')
|
||||
->where('is_enabled', 1)
|
||||
->find();
|
||||
}
|
||||
|
||||
if (!$template) {
|
||||
return api_success([
|
||||
'template_id' => 0,
|
||||
'required_items' => [],
|
||||
'optional_items' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
$items = Db::name('upload_template_items')
|
||||
->where('template_id', $template['id'])
|
||||
->where('is_enabled', 1)
|
||||
->order('sort_order', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$requiredItems = [];
|
||||
$optionalItems = [];
|
||||
foreach ($items as $item) {
|
||||
$payload = [
|
||||
'item_code' => $item['item_code'],
|
||||
'item_name' => $item['item_name'],
|
||||
'guide_text' => $item['guide_text'],
|
||||
'sample_image_url' => $this->assetUrlService()->normalizeUrl((string)$item['sample_image_url'], $request),
|
||||
'is_required' => (bool)$item['is_required'],
|
||||
'quality_status' => $item['is_required'] ? 'pending' : 'optional',
|
||||
'quality_message' => '',
|
||||
];
|
||||
if ($item['is_required']) {
|
||||
$requiredItems[] = $payload;
|
||||
} else {
|
||||
$optionalItems[] = $payload;
|
||||
}
|
||||
}
|
||||
|
||||
return api_success([
|
||||
'template_id' => (int)$template['id'],
|
||||
'required_items' => $requiredItems,
|
||||
'optional_items' => $optionalItems,
|
||||
]);
|
||||
}
|
||||
|
||||
public function preview(Request $request)
|
||||
{
|
||||
$draftId = (int)$request->input('draft_id', 0);
|
||||
|
||||
$draft = Db::name('appraisal_drafts')->where('id', $draftId)->where('user_id', app_user_id($request))->find();
|
||||
$product = Db::name('appraisal_draft_products')->where('draft_id', $draftId)->find();
|
||||
$extra = Db::name('appraisal_draft_extras')->where('draft_id', $draftId)->find();
|
||||
|
||||
if (!$draft) {
|
||||
return api_error('预览数据不存在', 404);
|
||||
}
|
||||
|
||||
$serviceConfig = $this->serviceConfig((string)$draft['service_provider']);
|
||||
$policyConfig = (new ContentService())->getPolicyConfig();
|
||||
|
||||
return api_success([
|
||||
'service_summary' => [
|
||||
'service_provider' => $draft['service_provider'],
|
||||
'service_provider_text' => $draft['service_provider'] === 'zhongjian' ? '中检鉴定' : '实物鉴定',
|
||||
],
|
||||
'product_summary' => [
|
||||
'product_name' => $this->resolveProductName($product),
|
||||
'category_name' => $this->lookupName('catalog_categories', 'name', $product['category_id'] ?? null),
|
||||
'brand_name' => $this->lookupName('catalog_brands', 'name', $product['brand_id'] ?? null),
|
||||
'price' => $extra['purchase_price'] ?? 0,
|
||||
],
|
||||
'upload_summary' => [
|
||||
'uploaded_count' => $this->countUploadedDraftItems($draftId),
|
||||
],
|
||||
'fee_detail' => [
|
||||
'service_fee' => (float)$serviceConfig['price'],
|
||||
'discount_fee' => 0,
|
||||
'pay_amount' => (float)$serviceConfig['price'],
|
||||
],
|
||||
'agreements' => $policyConfig['appraisal_agreements'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function submit(Request $request)
|
||||
{
|
||||
$userId = app_user_id($request);
|
||||
$draftId = (int)$request->input('draft_id', 0);
|
||||
$returnAddressId = (int)$request->input('return_address_id', 0);
|
||||
$sourceChannel = $this->normalizeOrderSourceChannel((string)$request->input('source_channel', 'mini_program'));
|
||||
$sourceCustomerId = trim((string)$request->input('source_customer_id', ''));
|
||||
|
||||
if ($sourceChannel === 'enterprise_push' && $sourceCustomerId === '') {
|
||||
return api_error('大客户推送订单必须提供客户 ID', 422);
|
||||
}
|
||||
if ($sourceChannel !== 'enterprise_push') {
|
||||
$sourceCustomerId = '';
|
||||
}
|
||||
|
||||
$draft = Db::name('appraisal_drafts')->where('id', $draftId)->where('user_id', $userId)->find();
|
||||
$product = Db::name('appraisal_draft_products')->where('draft_id', $draftId)->find();
|
||||
$extra = Db::name('appraisal_draft_extras')->where('draft_id', $draftId)->find();
|
||||
|
||||
if (!$draft || !$product) {
|
||||
return api_error('提交数据不完整', 422);
|
||||
}
|
||||
|
||||
$serviceConfig = $this->serviceConfig((string)$draft['service_provider']);
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$orderNo = 'AXY' . date('YmdHis') . mt_rand(100, 999);
|
||||
$appraisalNo = 'AXY-APP-' . date('Ymd') . '-' . mt_rand(1000, 9999);
|
||||
$estimated = date('Y-m-d H:i:s', strtotime(sprintf('+%d hours', (int)$serviceConfig['sla_hours'])));
|
||||
$productName = $this->resolveProductName($product);
|
||||
$warehouseService = new WarehouseService();
|
||||
$defaultAddress = Db::name('user_addresses')
|
||||
->where('user_id', $userId)
|
||||
->where('is_default', 1)
|
||||
->find();
|
||||
$returnAddress = null;
|
||||
if ($returnAddressId > 0) {
|
||||
$returnAddress = Db::name('user_addresses')
|
||||
->where('id', $returnAddressId)
|
||||
->where('user_id', $userId)
|
||||
->find();
|
||||
if (!$returnAddress) {
|
||||
return api_error('寄回地址不存在,请重新选择', 422);
|
||||
}
|
||||
}
|
||||
if (!$returnAddress) {
|
||||
$returnAddress = $defaultAddress ?: Db::name('user_addresses')
|
||||
->where('user_id', $userId)
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
}
|
||||
if (!$returnAddress) {
|
||||
return api_error('请先添加并确认寄回地址', 422);
|
||||
}
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$orderId = Db::name('orders')->insertGetId([
|
||||
'order_no' => $orderNo,
|
||||
'appraisal_no' => $appraisalNo,
|
||||
'user_id' => $userId,
|
||||
'service_mode' => $draft['service_mode'],
|
||||
'service_provider' => $draft['service_provider'],
|
||||
'payment_status' => 'paid',
|
||||
'order_status' => 'pending_shipping',
|
||||
'display_status' => '待寄送商品',
|
||||
'estimated_finish_time' => $estimated,
|
||||
'source_channel' => $sourceChannel,
|
||||
'source_customer_id' => $sourceCustomerId,
|
||||
'pay_amount' => $serviceConfig['price'],
|
||||
'paid_at' => $now,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
Db::name('order_products')->insert([
|
||||
'order_id' => $orderId,
|
||||
'category_id' => $product['category_id'] ?? null,
|
||||
'category_name' => $this->lookupName('catalog_categories', 'name', $product['category_id'] ?? null),
|
||||
'brand_id' => $product['brand_id'] ?? null,
|
||||
'brand_name' => $this->lookupName('catalog_brands', 'name', $product['brand_id'] ?? null),
|
||||
'color' => $product['color'] ?? '',
|
||||
'size_spec' => $product['size_spec'] ?? '',
|
||||
'serial_no' => $product['serial_no'] ?? '',
|
||||
'product_name' => $productName,
|
||||
'product_cover' => '',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
Db::name('order_extras')->insert([
|
||||
'order_id' => $orderId,
|
||||
'purchase_channel' => $extra['purchase_channel'] ?? '',
|
||||
'purchase_price' => $extra['purchase_price'] ?? 0,
|
||||
'purchase_date' => $extra['purchase_date'] ?? null,
|
||||
'usage_status' => $extra['usage_status'] ?? '',
|
||||
'condition_desc' => $extra['condition_desc'] ?? '',
|
||||
'has_accessories' => $extra['has_accessories'] ?? 0,
|
||||
'accessories_json' => $extra['accessories_json'] ?? json_encode([], JSON_UNESCAPED_UNICODE),
|
||||
'remark' => $extra['remark'] ?? '',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
if ($returnAddress) {
|
||||
Db::name('order_return_addresses')->insert([
|
||||
'order_id' => $orderId,
|
||||
'user_address_id' => (int)$returnAddress['id'],
|
||||
'consignee' => $returnAddress['consignee'] ?? '',
|
||||
'mobile' => $returnAddress['mobile'] ?? '',
|
||||
'province' => $returnAddress['province'] ?? '',
|
||||
'city' => $returnAddress['city'] ?? '',
|
||||
'district' => $returnAddress['district'] ?? '',
|
||||
'detail_address' => $returnAddress['detail_address'] ?? '',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
$shippingTarget = $warehouseService->bindOrderTarget(
|
||||
$orderId,
|
||||
(string)$draft['service_provider'],
|
||||
!empty($product['category_id']) ? (int)$product['category_id'] : null,
|
||||
$defaultAddress ?: null
|
||||
);
|
||||
|
||||
Db::name('order_timelines')->insertAll([
|
||||
[
|
||||
'order_id' => $orderId,
|
||||
'node_code' => 'created',
|
||||
'node_text' => '下单成功',
|
||||
'node_desc' => '订单已生成并完成支付',
|
||||
'operator_type' => 'system',
|
||||
'operator_id' => null,
|
||||
'occurred_at' => $now,
|
||||
'created_at' => $now,
|
||||
],
|
||||
[
|
||||
'order_id' => $orderId,
|
||||
'node_code' => 'pending_shipping',
|
||||
'node_text' => '待寄送商品',
|
||||
'node_desc' => sprintf(
|
||||
'请尽快将商品寄送至%s,以免影响处理时效',
|
||||
$shippingTarget['warehouse_name'] ?: '鉴定中心'
|
||||
),
|
||||
'operator_type' => 'system',
|
||||
'operator_id' => null,
|
||||
'occurred_at' => $now,
|
||||
'created_at' => $now,
|
||||
],
|
||||
]);
|
||||
|
||||
$draftUploads = Db::name('appraisal_draft_uploads')->where('draft_id', $draftId)->select()->toArray();
|
||||
foreach ($draftUploads as $draftUpload) {
|
||||
$draftFiles = Db::name('appraisal_draft_upload_files')->where('draft_upload_id', $draftUpload['id'])->select()->toArray();
|
||||
if (!$draftFiles) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$orderUploadId = Db::name('order_upload_items')->insertGetId([
|
||||
'order_id' => $orderId,
|
||||
'template_id' => $draftUpload['template_id'],
|
||||
'item_code' => $draftUpload['item_code'],
|
||||
'item_name' => $draftUpload['item_name'],
|
||||
'is_required' => $draftUpload['is_required'],
|
||||
'source_type' => 'initial',
|
||||
'status' => $draftUpload['quality_status'],
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
foreach ($draftFiles as $draftFile) {
|
||||
Db::name('order_upload_files')->insert([
|
||||
'order_upload_item_id' => $orderUploadId,
|
||||
'file_id' => $draftFile['file_id'],
|
||||
'file_url' => $draftFile['file_url'],
|
||||
'thumbnail_url' => $draftFile['thumbnail_url'],
|
||||
'quality_status' => $draftUpload['quality_status'],
|
||||
'quality_message' => $draftUpload['quality_message'],
|
||||
'uploaded_by_user_id' => $userId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Db::name('appraisal_tasks')->insert([
|
||||
'order_id' => $orderId,
|
||||
'task_stage' => 'first_review',
|
||||
'service_provider' => $draft['service_provider'],
|
||||
'status' => 'pending',
|
||||
'assignee_id' => null,
|
||||
'assignee_name' => '未分配',
|
||||
'started_at' => null,
|
||||
'submitted_at' => null,
|
||||
'sla_deadline' => $estimated,
|
||||
'is_overtime' => 0,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
Db::name('appraisal_drafts')->where('id', $draftId)->update([
|
||||
'status' => 'submitted',
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
(new MessageDispatcher())->sendInboxEvent('order_created', [
|
||||
'user_id' => $userId,
|
||||
'biz_type' => 'order',
|
||||
'biz_id' => (int)$orderId,
|
||||
'order_no' => $orderNo,
|
||||
'appraisal_no' => $appraisalNo,
|
||||
'product_name' => $productName,
|
||||
'pay_amount' => (string)$serviceConfig['price'],
|
||||
'fallback_title' => '订单提交成功',
|
||||
'fallback_content' => '您的鉴定订单已提交成功,可前往订单中心查看进度。',
|
||||
]);
|
||||
|
||||
Db::commit();
|
||||
} catch (\Throwable $e) {
|
||||
Db::rollback();
|
||||
return api_error('提交失败,请稍后重试', 500, [
|
||||
'detail' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
return api_success([
|
||||
'order_id' => (int)$orderId,
|
||||
'order_no' => $orderNo,
|
||||
'appraisal_no' => $appraisalNo,
|
||||
'pay_amount' => (float)$serviceConfig['price'],
|
||||
'next_status' => 'pending_shipping',
|
||||
]);
|
||||
}
|
||||
|
||||
private function lookupName(string $table, string $field, mixed $id): string
|
||||
{
|
||||
if (empty($id)) {
|
||||
return '';
|
||||
}
|
||||
return (string)Db::name($table)->where('id', $id)->value($field);
|
||||
}
|
||||
|
||||
private function resolveProductName(?array $product): string
|
||||
{
|
||||
if (!$product) {
|
||||
return '';
|
||||
}
|
||||
$categoryName = $this->lookupName('catalog_categories', 'name', $product['category_id'] ?? null);
|
||||
$brandName = $this->lookupName('catalog_brands', 'name', $product['brand_id'] ?? null);
|
||||
$fallbackName = trim($categoryName . ' ' . $brandName);
|
||||
if ($fallbackName !== '') {
|
||||
return $fallbackName;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private function serviceConfig(string $serviceProvider): array
|
||||
{
|
||||
$configs = [
|
||||
'anxinyan' => ['price' => 99.00, 'sla_hours' => 48],
|
||||
'zhongjian' => ['price' => 199.00, 'sla_hours' => 72],
|
||||
];
|
||||
if (isset($configs[$serviceProvider])) {
|
||||
return $configs[$serviceProvider];
|
||||
}
|
||||
return $configs['anxinyan'];
|
||||
}
|
||||
|
||||
private function draftUploadItems(int $draftId, Request $request): array
|
||||
{
|
||||
$uploads = Db::name('appraisal_draft_uploads')->where('draft_id', $draftId)->select()->toArray();
|
||||
if (!$uploads) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(function (array $item) use ($request) {
|
||||
$files = Db::name('appraisal_draft_upload_files')
|
||||
->where('draft_upload_id', $item['id'])
|
||||
->order('sort_order', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return [
|
||||
'item_code' => $item['item_code'],
|
||||
'item_name' => $item['item_name'],
|
||||
'is_required' => (bool)$item['is_required'],
|
||||
'quality_status' => $item['quality_status'],
|
||||
'quality_message' => $item['quality_message'],
|
||||
'files' => array_map(fn (array $file) => [
|
||||
'file_id' => $file['file_id'],
|
||||
'file_url' => $this->assetUrlService()->normalizeUrl((string)$file['file_url'], $request),
|
||||
'thumbnail_url' => $this->assetUrlService()->normalizeUrl((string)$file['thumbnail_url'], $request),
|
||||
], $files),
|
||||
];
|
||||
}, $uploads);
|
||||
}
|
||||
|
||||
private function countUploadedDraftItems(int $draftId): int
|
||||
{
|
||||
$uploadIds = Db::name('appraisal_draft_upload_files')
|
||||
->alias('f')
|
||||
->join('appraisal_draft_uploads u', 'u.id = f.draft_upload_id')
|
||||
->where('u.draft_id', $draftId)
|
||||
->group('u.id')
|
||||
->column('u.id');
|
||||
|
||||
return count($uploadIds);
|
||||
}
|
||||
|
||||
private function assetUrlService(): PublicAssetUrlService
|
||||
{
|
||||
return new PublicAssetUrlService();
|
||||
}
|
||||
|
||||
private function storage(): FileStorageService
|
||||
{
|
||||
return new FileStorageService();
|
||||
}
|
||||
|
||||
private function normalizeOrderSourceChannel(string $sourceChannel): string
|
||||
{
|
||||
$sourceChannel = trim($sourceChannel);
|
||||
$aliases = [
|
||||
'wechat_mini_program' => 'mini_program',
|
||||
'weixin_mini_program' => 'mini_program',
|
||||
'mp_weixin' => 'mini_program',
|
||||
'miniapp' => 'mini_program',
|
||||
'user_app' => 'mini_program',
|
||||
'web_h5' => 'h5',
|
||||
'enterprise' => 'enterprise_push',
|
||||
'enterprise_order' => 'enterprise_push',
|
||||
'customer_push' => 'enterprise_push',
|
||||
'large_customer_push' => 'enterprise_push',
|
||||
];
|
||||
$sourceChannel = $aliases[$sourceChannel] ?? $sourceChannel;
|
||||
|
||||
return in_array($sourceChannel, ['mini_program', 'h5', 'enterprise_push'], true)
|
||||
? $sourceChannel
|
||||
: 'mini_program';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user