修复一些错误

This commit is contained in:
liu
2026-08-14 22:20:13 +08:00
parent 228212f8e3
commit 4bdaf2a219
12 changed files with 454 additions and 37 deletions
File diff suppressed because one or more lines are too long
+25 -7
View File
@@ -9,6 +9,7 @@ use App\Models\ProductPriceModel;
use App\Models\StoreOrderItemModel;
use App\Models\StoreOrderModel;
use App\Services\BillNumberService;
use App\Services\ItemImageResolver;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -161,7 +162,7 @@ class OrderController extends BaseMiniController
'total_amount', 'status', 'remark', 'purchase_id', 'bill_id', 'created_at',
])
->with(['items' => static fn ($itemsQuery) => $itemsQuery
->select(['id', 'order_id', 'product_name', 'quantity', 'unit'])
->select(['id', 'order_id', 'product_name', 'product_spec', 'quantity', 'unit', 'image_ids'])
->orderBy('id')]);
if (isset($params['status'])) {
$query->where('status', (int) $params['status']);
@@ -177,6 +178,28 @@ class OrderController extends BaseMiniController
->orderBy('id', 'desc')
->paginate((int) ($params['pageSize'] ?? 10));
// 商品预览(每单前 3 条明细):首图跨订单一次性批量解析
$previewMap = [];
$flatItems = [];
foreach ($paginator->getCollection() as $order) {
foreach ($order->items as $item) {
$flatItems[] = [
'order_id' => $order->id,
'product_name' => $item->product_name,
'product_spec' => $item->product_spec,
'quantity' => $item->quantity,
'unit' => $item->unit,
'image_ids' => (array) $item->image_ids,
];
}
}
app(ItemImageResolver::class)->resolve($flatItems);
foreach ($flatItems as $flatItem) {
$orderId = $flatItem['order_id'];
unset($flatItem['order_id']);
$previewMap[$orderId][] = $flatItem;
}
$paginator->getCollection()->transform(
static fn (StoreOrderModel $order): array => [
'id' => $order->id,
@@ -193,12 +216,7 @@ class OrderController extends BaseMiniController
'bill_id' => $order->bill_id,
'created_at' => $order->created_at?->toDateTimeString(),
'item_count' => $order->items->count(),
'items' => $order->items->take(3)
->map(static fn (StoreOrderItemModel $item): array => [
'product_name' => $item->product_name,
'quantity' => $item->quantity,
'unit' => $item->unit,
])->values()->all(),
'items' => $previewMap[$order->id] ?? [],
]
);
+60 -19
View File
@@ -46,35 +46,76 @@ class ProductController extends BaseMiniController
}
$pageSize = (int) $request->input('pageSize', 10);
$data = $query->orderBy('sort')
$paginator = $query->orderBy('sort')
->orderBy('id')
->paginate($pageSize)
->toArray();
->paginate($pageSize);
foreach ($data['data'] as &$row) {
$row['price'] = null;
// 当前门店的等级价格(一次性取出,避免逐行查询)
$user = $this->optionalUser($request);
$store = $user !== null ? $this->boundStore($user) : null;
$priceRows = collect();
if ($store !== null && $store->level_id > 0) {
$priceRows = ProductPriceModel::query()
->where('level_id', $store->level_id)
->whereIn('product_id', $paginator->getCollection()->pluck('id'))
->get(['product_id', 'price', 'price_type', 'percent'])
->keyBy('product_id');
}
// 用户
$user = $this->optionalUser($request);
if (!$user) return $this->success($data);
// 门店
$store = $this->boundStore($user);
if(!$store) return $this->success($data);
$paginator->getCollection()->transform(
static function (ProductModel $product) use ($priceRows): array {
$row = $product->toArray();
// 实际价(百分比计价行按成本价上浮换算;成本价不随序列化输出)
$priceRow = $priceRows->get($product->id);
$row['price'] = $priceRow !== null
? ProductPriceModel::calcActualPrice(
(int) $priceRow->price_type,
(string) $priceRow->price,
(string) $priceRow->percent,
(string) $product->cost_price,
)
: null;
return $row;
}
);
if ($store->level_id > 0) {
foreach ($data['data'] as &$row) {
$model = ProductPriceModel::where('product_id', $row['id'])->where('level_id', $store->level_id)->first();
return $this->success($paginator->toArray());
}
/**
* 商品详情(免登录浏览;登录门店按等级显示换算价,未登录/未绑店/未设等级 price=null
*/
#[GetRoute('/product/{id}', authorize: false, where: ['id' => '[0-9]+'])]
public function detail(int $id, Request $request): JsonResponse
{
$product = ProductModel::query()
->where('status', ProductModel::STATUS_ON)
->with('category:id,name')
->find($id);
if ($product === null) {
throw new RepositoryException('商品不存在或已下架');
}
$price = null;
$user = $this->optionalUser($request);
$store = $user !== null ? $this->boundStore($user) : null;
if ($store !== null && $store->level_id > 0) {
$priceRow = ProductPriceModel::query()
->forProductLevel($product->id, $store->level_id)
->first(['price', 'price_type', 'percent']);
if ($priceRow !== null) {
$price = ProductPriceModel::calcActualPrice(
$model->price_type,
$model->price,
$model->percent,
$row->cost_price,
(int) $priceRow->price_type,
(string) $priceRow->price,
(string) $priceRow->percent,
(string) $product->cost_price,
);
$row['price'] = $price;
}
}
$data = $product->toArray();
$data['price'] = $price;
return $this->success($data);
}
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Order;
use App\Exceptions\RepositoryException;
use App\Models\BillModel;
use App\Models\NoticeModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
@@ -38,7 +39,8 @@ class StoreOrderController extends BaseController
$query = StoreOrderModel::query()->with([
'store:id,name,address,contact,phone',
'items:id,order_id,product_id,product_name,product_spec,unit,price,quantity,amount,image_ids',
'purchase:id,purchase_no,purchase_date,status'
'purchase:id,purchase_no,purchase_date,status',
'bill:id,bill_no,bill_date,total_amount,status,payment_id,paid_at',
]);
// 按包含的商品名称搜索:任一明细品名包含关键字即命中
@@ -65,6 +67,7 @@ class StoreOrderController extends BaseController
// 明细封面图:从快照 image_ids 批量解析(不再关联商品档案表)
foreach ($data['data'] as &$order) {
app(ItemImageResolver::class)->resolve($order['items']);
$this->appendBillPayState($order);
}
unset($order);
@@ -78,6 +81,7 @@ class StoreOrderController extends BaseController
$order = StoreOrderModel::with([
'store:id,name,address,contact,phone',
'items' => static fn ($query) => $query->with('supplier:id,name'),
'bill',
])->find($id);
if (empty($order)) {
throw new RepositoryException('订单不存在');
@@ -90,6 +94,8 @@ class StoreOrderController extends BaseController
// 明细首图
app(ItemImageResolver::class)->resolve($data['items']);
// 关联账单详情:补充支付进度
$this->appendBillPayState($data);
return $this->success($data);
}
@@ -234,4 +240,21 @@ class StoreOrderController extends BaseController
]);
}
}
/**
* 订单输出数组的关联账单补充支付进度(待支付/审核中/已支付,与小程序端口径一致)
*
* @param array<string, mixed> $order 订单数组(引用修改)
*/
private function appendBillPayState(array &$order): void
{
if (! is_array($order['bill'] ?? null)) {
return;
}
// 复用模型支付进度推导(已支付 > 审核中 > 待支付)
$bill = new BillModel($order['bill']);
$payState = $bill->payState();
$order['bill']['pay_state'] = $payState;
$order['bill']['pay_state_name'] = BillModel::PAY_STATE_NAMES[$payState];
}
}
+4 -1
View File
@@ -95,7 +95,10 @@ class PaymentModel extends Model
if ($ids === []) {
return [];
}
$urls = SysFileModel::query()->whereIn('id', $ids)->pluck('preview_url', 'id');
$urls = [];
foreach (SysFileModel::query()->whereIn('id', $ids)->get() as $file) {
$urls[$file->id] = $file->preview_url;
}
$result = [];
foreach ($ids as $id) {
if (isset($urls[$id])) {
+9 -5
View File
@@ -14,9 +14,9 @@ class BillDetailService
{
/**
* 合并后的商品明细:按商品聚合账单关联的全部订单明细
* 单价为加权平均口径(Σ金额÷Σ数量),保证 单价×数量=金额
* 单价为加权平均口径(Σ金额÷Σ数量),保证 单价×数量=金额;附商品首图
*
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
*/
public function mergedItems(BillModel $bill): array
{
@@ -33,7 +33,7 @@ class BillDetailService
* 用于账单合并导出,单价同为加权平均口径
*
* @param array<int, int> $billIds 账单ID列表
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
*/
public function mergedItemsOfBills(array $billIds): array
{
@@ -47,10 +47,10 @@ class BillDetailService
/**
* 按商品聚合订单明细:数量累加、重量/金额 bc 累加、单价加权平均,
* 按「分类sort → 商品sort」排序
* 首图取明细快照 image_ids 批量解析,按「分类sort → 商品sort」排序
*
* @param Collection<int, StoreOrderItemModel> $items
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string}>
* @return array<int, array{product_id: int, product_name: string, product_spec: string, unit: string, price: string, quantity: int, weight: string, amount: string, image: string}>
*/
private function aggregateItems(Collection $items): array
{
@@ -85,6 +85,7 @@ class BillDetailService
'quantity' => $quantity,
'weight' => $weight,
'amount' => $amount,
'image_ids' => (array) $first->image_ids,
'category_sort' => (int) ($product->category->sort ?? 9999),
'product_sort' => (int) ($product->sort ?? 9999),
];
@@ -93,6 +94,9 @@ class BillDetailService
[$a['category_sort'], $a['product_sort'], $a['product_id']]
<=> [$b['category_sort'], $b['product_sort'], $b['product_id']]);
// 首图批量解析(写入 image、移除 image_ids
app(ItemImageResolver::class)->resolve($rows);
return array_map(static function (array $row): array {
unset($row['category_sort'], $row['product_sort']);
return $row;
+70
View File
@@ -11,6 +11,7 @@ use App\Models\PurchaseOrderModel;
use App\Models\StoreModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
use Modules\SystemTool\Models\SysFileModel;
/**
* 账单链路与支付:订单状态随业务链自动推进(采购单完成→配送中、生成账单→已完成);
@@ -206,4 +207,73 @@ class BillPaymentTest extends ProcurementTestCase
$this->assertSame(0, $bill->payment_id, '账单释放可重新付款');
$this->assertSame('0.00', (string) $store->fresh()->total_purchase_amount);
}
/** 后台门店订单:列表显示关联账单与支付进度,详情附带完整账单 */
public function test_admin_order_list_and_detail_show_bill_info(): void
{
[$store, $order, $bill] = $this->makeBillViaChain();
$this->actingAsSysUser();
// 列表:账单摘要 + 支付进度(待支付)
$rows = $this->getJson('/order/store')->assertOk()->json('data.data');
$row = collect($rows)->firstWhere('id', $order->id);
$this->assertNotNull($row['bill'], '已出账订单列表应附账单');
$this->assertSame($bill->bill_no, $row['bill']['bill_no']);
$this->assertSame('20.00', $row['bill']['total_amount']);
$this->assertSame(BillModel::PAY_STATE_UNPAID, $row['bill']['pay_state']);
$this->assertSame('待支付', $row['bill']['pay_state_name']);
// 详情:完整账单字段 + 支付进度
$detail = $this->getJson("/order/store/{$order->id}")->assertOk()->json('data');
$this->assertSame($bill->bill_no, $detail['bill']['bill_no']);
$this->assertSame('20.00', $detail['bill']['product_amount']);
$this->assertSame(BillModel::PAY_STATE_UNPAID, $detail['bill']['pay_state']);
// 收款后列表支付进度变为已支付
$this->putJson("/recon/bill/{$bill->id}/pay")->assertJsonPath('success', true);
$rows = $this->getJson('/order/store')->assertOk()->json('data.data');
$row = collect($rows)->firstWhere('id', $order->id);
$this->assertSame(BillModel::PAY_STATE_PAID, $row['bill']['pay_state']);
$this->assertSame('已支付', $row['bill']['pay_state_name']);
}
/** 支付记录详情:凭证图片解析 preview_url(回归:preview_url 为访问器不能 pluck */
public function test_payment_detail_returns_voucher_urls(): void
{
$store = StoreModel::factory()->create();
$user = UserModel::factory()->forStore($store->id)->create();
$makeFile = static function (string $path): int {
return (int) SysFileModel::create([
'group_id' => 4,
'disk' => 'local',
'channel' => 20,
'file_type' => 10,
'file_name' => basename($path),
'file_path' => $path,
'file_size' => 1024,
'file_ext' => 'jpg',
'uploader_id' => 1,
])->id;
};
$fileA = $makeFile('voucher/a.jpg');
$fileB = $makeFile('voucher/b.jpg');
$payment = PaymentModel::create([
'payment_no' => 'ZF202608140003',
'store_id' => $store->id,
'user_id' => $user->id,
'amount' => '100.00',
'pay_method' => PaymentModel::METHOD_BANK,
'voucher_ids' => [$fileA, $fileB],
'status' => PaymentModel::STATUS_PENDING,
]);
$this->actingAsSysUser();
$data = $this->getJson("/recon/payment/{$payment->id}")->assertOk()->json('data');
$this->assertCount(2, $data['payment']['voucher_urls']);
$this->assertStringContainsString('voucher/a.jpg', $data['payment']['voucher_urls'][0]);
$this->assertStringContainsString('voucher/b.jpg', $data['payment']['voucher_urls'][1], '凭证顺序保持提交顺序');
}
}
+20
View File
@@ -9,6 +9,7 @@ use App\Models\StoreModel;
use App\Models\StoreOrderItemModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
use Modules\SystemTool\Models\SysFileModel;
/**
* 小程序账单:支付进度推导(待支付/审核中/已支付)、应结算日期(回款周期)、
@@ -149,6 +150,18 @@ class MiniBillTest extends ProcurementTestCase
[$store, $user] = $this->makeStoreWithUser(0);
$this->actingAsMiniUser($user);
$file = SysFileModel::create([
'group_id' => 1,
'disk' => 'local',
'channel' => 10,
'file_type' => 10,
'file_name' => '白菜.jpg',
'file_path' => 'product/baicai.jpg',
'file_size' => 1024,
'file_ext' => 'jpg',
'uploader_id' => 1,
]);
$bill = $this->makeBill($store);
$product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON]);
$order = StoreOrderModel::factory()->create([
@@ -164,9 +177,12 @@ class MiniBillTest extends ProcurementTestCase
'store_id' => $store->id,
'product_id' => $product->id,
'product_name' => '白菜',
'product_spec' => '30斤/筐',
'unit' => '筐',
'price' => '5.00',
'quantity' => 20,
'amount' => '100.00',
'image_ids' => (string) $file->id,
]);
$data = $this->getJson("/mini/bill/{$bill->id}")->assertOk()->json('data');
@@ -178,9 +194,13 @@ class MiniBillTest extends ProcurementTestCase
$this->assertCount(1, $data['items']);
$this->assertSame('白菜', $data['items'][0]['product_name']);
$this->assertSame('30斤/筐', $data['items'][0]['product_spec'], '明细附规格');
$this->assertSame('筐', $data['items'][0]['unit'], '明细附单位');
$this->assertSame('5.00', $data['items'][0]['price'], '合并明细单价 = Σ金额 ÷ Σ数量');
$this->assertSame(20, $data['items'][0]['quantity']);
$this->assertSame('100.00', $data['items'][0]['amount']);
$this->assertStringContainsString('baicai.jpg', (string) $data['items'][0]['image'], '明细附首图URL');
$this->assertArrayNotHasKey('image_ids', $data['items'][0], 'image_ids 解析后不输出');
$this->assertCount(1, $data['orders']);
$this->assertSame($order->order_no, $data['orders'][0]['order_no']);
+110
View File
@@ -0,0 +1,110 @@
<?php
namespace Tests\Feature;
use App\Models\CustomerLevelModel;
use App\Models\ProductModel;
use App\Models\ProductPriceModel;
use App\Models\StoreModel;
use App\Models\UserModel;
/**
* 小程序商品:商品详情接口(免登录浏览,登录门店按等级显示换算价);
* 商品列表回归:登录门店场景曾数组误用对象访问 + 价格行缺失导致 500
*/
class MiniProductTest extends ProcurementTestCase
{
/**
* 造门店 + 上架商品 + 等级价(固定价 5.00)
*
* @return array{0: StoreModel, 1: ProductModel, 2: UserModel, 3: CustomerLevelModel}
*/
private function makeStoreWithProduct(string $price = '5.00'): array
{
$level = CustomerLevelModel::factory()->create();
$store = StoreModel::factory()->create(['level_id' => $level->id]);
$product = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON]);
ProductPriceModel::factory()->create([
'product_id' => $product->id,
'level_id' => $level->id,
'price' => $price,
]);
return [$store, $product, UserModel::factory()->forStore($store->id)->create(), $level];
}
/** 商品详情:未登录浏览 price=null,基础字段完整 */
public function test_product_detail_guest_sees_null_price(): void
{
[, $product] = $this->makeStoreWithProduct();
$data = $this->getJson("/mini/product/{$product->id}")->assertOk()->json('data');
$this->assertSame($product->name, $data['name']);
$this->assertSame($product->spec, $data['spec']);
$this->assertSame($product->unit, $data['unit']);
$this->assertNull($data['price'], '未登录不显示价格');
$this->assertArrayNotHasKey('cost_price', $data, '成本价不得输出到小程序端');
}
/** 商品详情:登录门店按等级显示固定价 */
public function test_product_detail_store_user_sees_level_price(): void
{
[, $product, $user] = $this->makeStoreWithProduct('6.50');
$this->actingAsMiniUser($user);
$data = $this->getJson("/mini/product/{$product->id}")->assertOk()->json('data');
$this->assertSame('6.50', $data['price']);
}
/** 商品详情:百分比计价按最新成本价上浮换算 */
public function test_product_detail_percent_price_calculated_from_cost(): void
{
[, $product, $user, $level] = $this->makeStoreWithProduct();
ProductPriceModel::where('product_id', $product->id)->where('level_id', $level->id)
->update(['price_type' => ProductPriceModel::PRICE_TYPE_PERCENT, 'percent' => '30']);
$product->update(['cost_price' => '20.00']);
$this->actingAsMiniUser($user);
$data = $this->getJson("/mini/product/{$product->id}")->assertOk()->json('data');
$this->assertSame('26.00', $data['price'], '20 元上浮 30% = 26.00');
}
/** 商品详情:下架/不存在拒绝 */
public function test_product_detail_off_shelf_or_missing_rejected(): void
{
[, $product] = $this->makeStoreWithProduct();
$product->update(['status' => ProductModel::STATUS_OFF]);
$this->getJson("/mini/product/{$product->id}")->assertJsonPath('success', false);
$this->getJson('/mini/product/99999')->assertJsonPath('success', false);
}
/** 商品列表:登录门店显示等级价(回归:曾数组误用对象访问导致 500) */
public function test_product_list_store_user_sees_level_price(): void
{
[, $product, $user] = $this->makeStoreWithProduct('7.00');
$this->actingAsMiniUser($user);
$rows = $this->getJson('/mini/product/list')->assertOk()->json('data.data');
$row = collect($rows)->firstWhere('id', $product->id);
$this->assertNotNull($row);
$this->assertSame('7.00', $row['price']);
$this->assertArrayNotHasKey('cost_price', $row, '成本价不得输出到小程序端');
}
/** 商品列表:未登录 price=null */
public function test_product_list_guest_sees_null_price(): void
{
[, $product] = $this->makeStoreWithProduct();
$rows = $this->getJson('/mini/product/list')->assertOk()->json('data.data');
$row = collect($rows)->firstWhere('id', $product->id);
$this->assertNotNull($row);
$this->assertNull($row['price']);
}
}
+45
View File
@@ -8,6 +8,7 @@ use App\Models\ProductPriceModel;
use App\Models\StoreModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
use Modules\SystemTool\Models\SysFileModel;
/**
* 小程序下单:等级价快照、服务端重算总价、取消限制、门店数据隔离
@@ -321,4 +322,48 @@ class StoreOrderTest extends ProcurementTestCase
])->assertJsonPath('success', false);
$this->assertSame(StoreOrderModel::STATUS_SUMMARIZED, $pending1->fresh()->status);
}
/** 订单列表商品预览:附带首图/规格/单位供小程序端展示 */
public function test_order_list_preview_includes_image_spec_and_unit(): void
{
$file = SysFileModel::create([
'group_id' => 1,
'disk' => 'local',
'channel' => 10,
'file_type' => 10,
'file_name' => '白菜.jpg',
'file_path' => 'product/baicai.jpg',
'file_size' => 1024,
'file_ext' => 'jpg',
'uploader_id' => 1,
]);
$level = CustomerLevelModel::factory()->create();
$store = StoreModel::factory()->create(['level_id' => $level->id]);
$product = ProductModel::factory()->create([
'status' => ProductModel::STATUS_ON,
'spec' => '30斤/筐',
'unit' => '筐',
'image_ids' => (string) $file->id,
]);
ProductPriceModel::factory()->create([
'product_id' => $product->id,
'level_id' => $level->id,
'price' => '5.00',
]);
$user = UserModel::factory()->forStore($store->id)->create();
$this->actingAsMiniUser($user);
$this->postJson('/mini/order', ['items' => [['product_id' => $product->id, 'quantity' => 2]]])
->assertJsonPath('success', true);
$rows = $this->getJson('/mini/order')->assertOk()->json('data.data');
$preview = $rows[0]['items'][0];
$this->assertSame($product->name, $preview['product_name']);
$this->assertSame('30斤/筐', $preview['product_spec'], '预览附规格');
$this->assertSame('筐', $preview['unit'], '预览附单位');
$this->assertStringContainsString('baicai.jpg', (string) $preview['image'], '预览附首图URL');
$this->assertArrayNotHasKey('image_ids', $preview, 'image_ids 解析后不输出');
}
}
+38
View File
@@ -38,6 +38,42 @@ export interface IStoreOrderItemUpdate {
remark: string;
}
/** 订单关联账单(列表附带摘要、详情附带完整字段;pay_state 由后端推导) */
export interface IStoreOrderBill {
id: number;
bill_no: string;
bill_date?: string;
/** 商品金额 */
product_amount?: string;
/** 配送费 */
delivery_fee?: string;
box_num?: number;
tray_num?: number;
box_price?: string;
tray_price?: string;
/** 附加金额 = 筐×筐单价 + 托盘×托盘单价 */
added_amount?: string;
/** 账单总金额 */
total_amount: string;
/** 支付状态:0未支付 1已支付 */
status: number;
/** 关联支付记录ID(0=未发起支付) */
payment_id?: number;
/** 支付进度:0待支付 1审核中 2已支付 */
pay_state?: number;
pay_state_name?: string;
paid_at?: string | null;
pay_remark?: string;
created_at?: string;
}
/** 账单支付进度映射(与小程序端口径一致) */
export const BILL_PAY_STATE_MAP: Record<number, { text: string; color: string }> = {
0: { text: '待支付', color: 'warning' },
1: { text: '审核中', color: 'processing' },
2: { text: '已支付', color: 'success' },
};
/** 门店订单 */
export default interface IStoreOrder {
id?: number;
@@ -46,6 +82,8 @@ export default interface IStoreOrder {
purchase_id?: number;
/** 关联账单ID(采购单完成后按门店生成账单时回写) */
bill_id?: number;
/** 关联账单(生成账单后由接口附带) */
bill?: IStoreOrderBill | null;
store?: {
id: number;
name: string;
+48 -3
View File
@@ -23,7 +23,7 @@ import type {
XinTableProps,
} from '@/components/XinTable/typings.ts';
import type IStoreOrder from '@/domain/iStoreOrder.ts';
import { STORE_ORDER_STATUS_MAP } from '@/domain/iStoreOrder.ts';
import { BILL_PAY_STATE_MAP, STORE_ORDER_STATUS_MAP } from '@/domain/iStoreOrder.ts';
import {
getStoreOrder,
updateOrderStatus,
@@ -312,10 +312,29 @@ const StoreOrderPage: React.FC = () => {
) : '-'
},
{
title: '账单ID',
title: '账单信息',
dataIndex: 'bill_id',
valueType: 'digit',
hideInForm: true,
hideInSearch: true,
width: 240,
render: (_, record) => record.bill ? (
<Space orientation={'vertical'}>
<div>
<Text type={'secondary'}></Text>
{record.bill.bill_no}
</div>
<div>
<Text type={'secondary'}></Text>
<Tag color={BILL_PAY_STATE_MAP[record.bill.pay_state ?? 0]?.color}>
{record.bill.pay_state_name ?? BILL_PAY_STATE_MAP[record.bill.pay_state ?? 0]?.text}
</Tag>
</div>
<div>
<Text type={'secondary'}></Text>
<span className={'text-[red]'}>{record.bill.total_amount} </span>
</div>
</Space>
) : '-'
},
{
title: '操作栏',
@@ -495,6 +514,32 @@ const StoreOrderPage: React.FC = () => {
) : null}
</Descriptions>
{/* 关联账单信息(生成账单后展示) */}
{detail.bill ? (
<Descriptions title="账单信息" column={3} size="small" bordered className="mt-4!">
<Descriptions.Item label="账单号">{detail.bill.bill_no}</Descriptions.Item>
<Descriptions.Item label="账单日期">{detail.bill.bill_date ?? '-'}</Descriptions.Item>
<Descriptions.Item label="支付状态">
<Tag color={BILL_PAY_STATE_MAP[detail.bill.pay_state ?? 0]?.color}>
{detail.bill.pay_state_name ?? BILL_PAY_STATE_MAP[detail.bill.pay_state ?? 0]?.text}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="商品金额">¥{detail.bill.product_amount ?? '-'}</Descriptions.Item>
<Descriptions.Item label="配送费">¥{detail.bill.delivery_fee ?? '-'}</Descriptions.Item>
<Descriptions.Item label="附加金额">
¥{detail.bill.added_amount ?? '0.00'}
<Text type={'secondary'} className={'ml-1 text-[12px]'}>
{detail.bill.box_num ?? 0}/{detail.bill.tray_num ?? 0}
</Text>
</Descriptions.Item>
<Descriptions.Item label="账单总金额">
<Text strong className={'text-[red]'}>¥{detail.bill.total_amount}</Text>
</Descriptions.Item>
<Descriptions.Item label="付款时间">{detail.bill.paid_at ?? '-'}</Descriptions.Item>
<Descriptions.Item label="付款备注">{detail.bill.pay_remark || '-'}</Descriptions.Item>
</Descriptions>
) : null}
{/* 商品明细(商城模式:首图 + 单价 × 订货量 + 金额) */}
<Title level={5} className="mt-6! mb-3!">