feat(送礼订单): 完善礼物信息、领取人操作与订单金额展示

- 订单详情新增礼物信息卡:送礼人查看领取人,领取人查看赠送人,含礼物留言与领取时间
- 领取人按订单流程可见确认收货、查看物流、去评价,评价接口权限放开至领取人
- 商品信息卡增加标题,商品金额与商品总额按规格原价(attr_info.price)展示
- 订单列表商品图放大、规格文字与图片底部对齐,修复次级按钮双层边框
This commit is contained in:
吴昊天 2026-10-22 10:45:50 +08:00
parent 000adafb42
commit d5e2f6066a
8 changed files with 318 additions and 53 deletions

View File

@ -2841,11 +2841,33 @@ class CenterOrderController
return app('json')->success($cartProduct);
}
/**
* 判断用户是否可对订单执行用户端操作:下单人本人或送礼订单领取人
* @param array $order 订单数据(含 uid / gift_uid / extra_info)
* @param int $uid 当前用户 ID
* @return bool
*/
protected function canOperateOrder(array $order, int $uid): bool
{
if ((int)($order['uid'] ?? 0) === $uid) {
return true;
}
$giftUid = (int)($order['gift_uid'] ?? 0);
if ($giftUid === 0) {
$extra = $order['extra_info'] ?? [];
if (is_string($extra)) {
$extra = json_decode($extra, true) ?: [];
}
$giftUid = (int)($extra['gift']['gift_uid'] ?? ($extra['gift_uid'] ?? 0));
}
return $giftUid > 0 && $giftUid === $uid;
}
/**
* 按 SKU 唯一码从中台订单快照定位商品行
* 查询订单中台的 extra_info.items,匹配 attr_info.unique(与订单评价 unique 同源)
* @param string $unique SKU 唯一码
* @param int|null $uid 限定用户(评价场景必传防越权),null 不限定
* @param int|null $uid 限定用户(评价场景必传防越权,下单人或送礼领取人),null 不限定
* @return array|null 商品行(附 _order_no/_center_id),未找到返回 null
*/
protected function findOrderItemBySkuUnique(string $unique, ?int $uid = null): ?array
@ -2853,12 +2875,13 @@ class CenterOrderController
if ($unique === '') {
return null;
}
// 不直接按 uid 过滤:送礼订单的领取人也需要能评价(领取人 uid 不等于订单 uid)
$where = [['extra_info', 'like', '%' . $unique . '%']];
if ($uid !== null) {
$where[] = ['uid', '=', $uid];
}
$orders = app()->make(OrderCenterDao::class)->selectList($where, 'id, order_no, extra_info', 0, 0);
$orders = app()->make(OrderCenterDao::class)->selectList($where, 'id, uid, gift_uid, order_no, extra_info', 0, 0);
foreach ($orders as $order) {
if ($uid !== null && !$this->canOperateOrder($order, $uid)) {
continue;
}
$extra = is_string($order['extra_info']) ? json_decode($order['extra_info'], true) : ($order['extra_info'] ?? []);
foreach ($extra['items'] ?? [] as $item) {
if (($item['attr_info']['unique'] ?? '') === $unique) {
@ -2876,7 +2899,7 @@ class CenterOrderController
* 评价必须落到用户指定的那笔订单:同商品重复购买时各订单 unique 相同,仅凭 unique 反查会命中旧订单
* @param string $orderNo 中台订单号
* @param string $unique SKU 唯一码
* @param int|null $uid 限定归属用户
* @param int|null $uid 限定归属用户(下单人或送礼领取人)
* @return array|null
*/
protected function findOrderItemByOrderNo(string $orderNo, string $unique, ?int $uid = null): ?array
@ -2889,7 +2912,7 @@ class CenterOrderController
return null;
}
$order = is_object($order) ? $order->toArray() : (array)$order;
if ($uid !== null && (int)($order['uid'] ?? 0) !== $uid) {
if ($uid !== null && !$this->canOperateOrder($order, $uid)) {
return null;
}
$extra = is_string($order['extra_info'] ?? null) ? json_decode($order['extra_info'], true) : ($order['extra_info'] ?? []);
@ -2951,8 +2974,9 @@ class CenterOrderController
$orderInfo = $orderInfo->toArray();
// ==================== 6. 权限验证 ====================
if ($uid != $orderInfo['uid']) {
return app('json')->fail('不是您自己的订单,无法评价');
// 下单人本人或送礼订单领取人均可评价(领取人评价时 uid 为领取人)
if (!$this->canOperateOrder($orderInfo, $uid)) {
return app('json')->fail('无权评价该订单');
}
// ==================== 7. 调用评价服务(业务逻辑和事件触发都在Service中)===================

View File

@ -449,10 +449,21 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
}
$detail = $detail->toArray();
$detail['extra_info'] = $this->parseExtraInfo($detail['extra_info']);
// 下单用户昵称/绑定电话(eb_user),供详情"用户信息"区展示
$detailUser = User::where('uid', (int)$detail['uid'])->field('nickname,phone')->find();
// 下单用户昵称/绑定电话/头像(eb_user),供详情"用户信息"与送礼信息区展示
$detailUser = User::where('uid', (int)$detail['uid'])->field('nickname,phone,avatar')->find();
$detail['nickname'] = $detailUser['nickname'] ?? '';
$detail['user_phone'] = $detailUser['phone'] ?? '';
$detail['user_avatar'] = set_file_url((string)($detailUser['avatar'] ?? ''));
// 送礼订单:领取人信息(gift_uid 非 0 时),供送礼人查看"谁领取了礼物"
$giftUid = (int)($detail['gift_uid'] ?? $detail['extra_info']['gift']['gift_uid'] ?? ($detail['extra_info']['gift_uid'] ?? 0));
if ($giftUid > 0) {
$receiver = User::where('uid', $giftUid)->field('nickname,avatar')->find();
$detail['gift_receiver'] = [
'uid' => $giftUid,
'nickname' => (string)($receiver['nickname'] ?? ''),
'avatar' => set_file_url((string)($receiver['avatar'] ?? '')),
];
}
// 解析 JSON 字段
if (!empty($detail['custom_form'])) {
$detail['custom_form'] = $this->parseExtraInfo($detail['custom_form']);
@ -621,20 +632,51 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
return (float)($detail['gift_price'] ?? 0) > 0 ? 1 : 0;
}
/**
* 计算订单商品原价总额(规格价 × 数量)
* total_price 为优惠后金额,价格明细中的“商品总额”需使用原价基数,才能与各项优惠对平
* @param array $detail 订单详情数据
* @return string 金额字符串(两位小数)
*/
protected function resolveOriginalGoodsTotal(array $detail): string
{
$total = '0.00';
foreach (($detail['order_items'] ?? []) as $item) {
if (!is_array($item)) {
continue;
}
$price = is_array($item['attr_info'] ?? null) ? ($item['attr_info']['price'] ?? '') : '';
// 订单快照 item.price 可能是商品级价格,规格金额以 attr_info.price 为准
if ($price === '' || $price === null) {
$price = $item['price'] ?? '';
}
if ($price === '' || !is_numeric($price)) {
continue;
}
$num = max(1, (int)($item['cart_num'] ?? 1));
$total = bcadd($total, bcmul((string)$price, (string)$num, 2), 2);
}
if (bccomp($total, '0', 2) <= 0) {
$total = number_format((float)($detail['total_price'] ?? 0), 2, '.', '');
}
return $total;
}
/**
* 组装价格明细数组
* 将金额实体列转为 {label, value, type} 数组格式
* 金额字段为中台实体列(价格链规范固定);插件可通过 OrderPricingExtend 事件追加金额项
* @param array $detail 订单详情数据
* @return array 返回 {items: [...], pay_price: string}
* @return array 返回 {items: [...], pay_price: string, original_total: string}
*/
protected function buildPricingItems(array $detail): array
{
$items = [];
// 商品总额(始终存在)
// 商品总额按规格原价 × 数量汇总(total_price 是优惠后金额,不能作为明细基数)
$originalTotal = $this->resolveOriginalGoodsTotal($detail);
$items[] = [
'label' => '商品总额',
'value' => number_format((float)($detail['total_price'] ?? 0), 2, '.', ''),
'value' => $originalTotal,
'type' => 'subtotal',
];
@ -693,8 +735,9 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
event('OrderPricingExtend', $pricingEvent);
return [
'items' => $items,
'pay_price' => number_format((float)($detail['pay_price'] ?? 0), 2, '.', ''),
'items' => $items,
'pay_price' => number_format((float)($detail['pay_price'] ?? 0), 2, '.', ''),
'original_total' => $originalTotal,
];
}
@ -824,6 +867,16 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
];
}
// 45. 礼物信息(送礼订单):赠送人/领取人展示由查看者身份决定,在 applyGiftViewerPolicy 中填充
$gift = $detail['gift'] ?? null;
$sections[] = [
'key' => 'gift',
'component' => 'gift_info',
'props' => ['gift' => $gift ?? []],
'visible' => !empty($gift),
'order' => 45,
];
// 50. 商品卡片(始终存在)
// product_id 供前端引擎跳转商品详情(goProductDetail)使用
$product = $detail['product'] ?? [];
@ -1083,7 +1136,8 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
$pricing = [
'items' => $pricingData['items'],
'pay_price' => $pricingData['pay_price'],
'total_price' => $detail['total_price'] ?? '0.00',
// 展示口径:商品总额按规格原价 × 数量汇总(原始 total_price 为优惠后金额,保留在详情顶层供业务计算)
'total_price' => $pricingData['original_total'] ?? ($detail['total_price'] ?? '0.00'),
'pay_postage' => $detail['pay_postage'] ?? '0.00',
'refund_price' => $detail['refund_price'] ?? '0.00',
'coupon_price' => $detail['coupon_price'] ?? '0.00',
@ -1232,6 +1286,25 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
// 原始 extra_info(供深度定制用)
$extensions['extra_info'] = $detail['extra_info'] ?? [];
// 送礼订单信息:赠送人 / 领取人 / 留言 / 领取时间,供详情礼物卡片按查看者展示
$gift = null;
if ($this->resolveIsGiftFlag($detail) === 1) {
$extraInfo = $detail['extra_info'] ?? [];
$giftUid = (int)($detail['gift_uid'] ?? $extraInfo['gift']['gift_uid'] ?? ($extraInfo['gift_uid'] ?? 0));
$gift = [
'is_gift' => 1,
'gift_uid' => $giftUid,
'gift_mark' => (string)($extraInfo['gift_mark'] ?? ''),
'gift_time' => (int)($extraInfo['gift']['gift_time'] ?? 0),
'sender' => [
'uid' => (int)($detail['uid'] ?? 0),
'nickname' => (string)($detail['nickname'] ?? ''),
'avatar' => (string)($detail['user_avatar'] ?? ''),
],
'receiver' => $detail['gift_receiver'] ?? null,
];
}
// 返回分组结构:仅输出有值的分组,空分组(null/空数组)不下发,避免响应占位
$result = [
'status' => $status,
@ -1240,6 +1313,9 @@ class OrderCenterServices extends BaseService implements OrderCenterSyncInterfac
'order_info' => $orderInfo,
'extensions' => $extensions,
];
if ($gift !== null) {
$result['gift'] = $gift;
}
if (!empty($buttons)) {
$result['buttons'] = $buttons;
}

View File

@ -93,7 +93,7 @@ class OrderCenterUserServices extends OrderCenterServices
fn($section) => !in_array($section['key'] ?? '', ['pricing', 'payment', 'invoice', 'coupon_gift', 'points_reward'], true)
));
$result['page_config']['extensions']['viewer_role'] = 'gift_receiver';
$visibleActions = ['confirmReceive', 'viewLogistics'];
$visibleActions = ['confirmReceive', 'viewLogistics', 'goComment'];
$hiddenActions = [];
} else {
// 购买者:不展示收货信息与物流轨迹,隐藏确认收货/申请退款/查看物流
@ -105,9 +105,22 @@ class OrderCenterUserServices extends OrderCenterServices
$hiddenActions = ['confirmReceive', 'applyRefund', 'viewLogistics'];
}
// 按查看者身份过滤底部操作按钮
// 按查看者身份处理礼物信息与底部操作按钮
foreach ($sections as &$section) {
if (($section['key'] ?? '') !== 'buttons') {
$sectionKey = (string)($section['key'] ?? '');
// 礼物信息:送礼人展示领取人,领取人展示赠送人
if ($sectionKey === 'gift') {
$gift = $section['props']['gift'] ?? [];
if ($isReceiver) {
$section['props']['role'] = 'receiver';
$section['props']['display'] = $gift['sender'] ?? null;
} else {
$section['props']['role'] = 'sender';
$section['props']['display'] = $gift['receiver'] ?? null;
}
continue;
}
if ($sectionKey !== 'buttons') {
continue;
}
$section['props']['buttons'] = array_values(array_filter(
@ -216,7 +229,7 @@ class OrderCenterUserServices extends OrderCenterServices
if ($item['is_gift_receiver']) {
$item['order_buttons'] = array_values(array_filter(
$item['order_buttons'] ?? [],
fn($button) => ($button['action'] ?? '') === 'viewLogistics'
fn($button) => in_array($button['action'] ?? '', ['confirmReceive', 'viewLogistics', 'goComment'], true)
));
}
}
@ -348,7 +361,8 @@ class OrderCenterUserServices extends OrderCenterServices
}
// 订单大类文案:从 OrderTypeRegistry 动态获取,各适配器注册即生效
if ($orderCategory) {
// 普通商品订单已有「实物商品」角标,不再重复展示“商品订单”占位文案
if ($orderCategory && $orderCategory !== 'goods') {
$categoryMap = OrderTypeRegistry::getCategoryMap();
if (isset($categoryMap[$orderCategory])) {
return $categoryMap[$orderCategory];

View File

@ -192,6 +192,7 @@ class NormalOrderAdapter extends BaseOrderTypeAdapter
])
->userButtons([
Button::primary('去评价', 'goComment'),
Button::make('查看物流', 'viewLogistics'),
Button::make('申请售后', 'applyAfterSale'),
])
->filter([['pt_normal_order.status', '=', self::EXT_STATUS_PENDING_REVIEW]]),
@ -202,6 +203,7 @@ class NormalOrderAdapter extends BaseOrderTypeAdapter
->label('已完成')
->adminButtons([])
->userButtons([
Button::make('查看物流', 'viewLogistics'),
Button::make('申请售后', 'applyAfterSale'),
Button::primary('再次购买', 'repurchase'),
])

View File

@ -0,0 +1,113 @@
<!--
礼物信息卡片(送礼订单专用)
送礼人:展示领取人(未领取时展示等待提示)
领取人:展示赠送人
数据来源:section.props.gift + section.props.role / display
展示对象由后端 applyGiftViewerPolicy 按查看者身份下发,前端不判断用户关系
-->
<template>
<view v-if="gift" class="info-card gift-card">
<view class="card-header acea-row row-between-wrapper">
<view class="card-title">{{ $t('礼物信息') }}</view>
<view v-if="role === 'sender' && hasDisplay && gift.gift_time" class="gift-time">
{{ $t('领取时间') }}:{{ formatTime(gift.gift_time) }}
</view>
</view>
<view class="gift-user acea-row row-middle">
<image v-if="display.avatar" class="avatar" :src="display.avatar" mode="aspectFill" />
<view v-else class="avatar avatar-empty">
<text class="iconfont icon-ic_gift1"></text>
</view>
<view class="user-info">
<view v-if="role === 'receiver'" class="gift-text">
<text class="nickname">{{ displayName }}</text>
<text class="gift-suffix">{{ $t('赠您一份礼物,请查收!') }}</text>
</view>
<view v-else-if="hasDisplay" class="gift-text">
<text class="nickname">{{ displayName }}</text>
<text class="gift-suffix">{{ $t('已领取您的礼物') }}</text>
</view>
<view v-else class="gift-text">
<text class="gift-suffix">{{ $t('等待好友领取') }}</text>
</view>
</view>
</view>
<view v-if="gift.gift_mark" class="gift-mark">
<text class="gift-mark-label">{{ $t('礼物留言') }}:</text>
<text class="gift-mark-text">{{ gift.gift_mark }}</text>
</view>
</view>
</template>
<script>
/**
* 礼物信息卡片
* 送礼订单详情中展示赠送人 / 领取人信息与礼物留言
*/
export default {
name: 'GiftInfoCard',
// DIY 通用化契约:组件唯一标识
componentKey: 'gift_info',
};
</script>
<script setup>
import { computed } from 'vue';
const props = defineProps({
/** section 对象,含 props.gift / props.role / props.display */
section: { type: Object, required: true },
});
/** 后端直填 props */
const p = computed(() => (props.section && props.section.props) || {});
/** 礼物数据 */
const gift = computed(() => p.value.gift || null);
/** 查看者角色:sender=送礼人,receiver=领取人 */
const role = computed(() => p.value.role || 'sender');
/** 需要展示的用户(送礼人看领取人,领取人看赠送人) */
const display = computed(() => p.value.display || {});
/** 是否存在可展示对象:送礼人未领取时为 false */
const hasDisplay = computed(() => !!p.value.display);
/** 展示用户名,缺失时兜底为“好友” */
const displayName = computed(() => display.value.nickname || '好友');
/**
* 时间戳格式化为 YYYY-MM-DD HH:mm
* @param {number} ts 秒级时间戳
* @return {string} 格式化后的时间
*/
function formatTime(ts) {
if (!ts) return '';
const date = new Date(ts * 1000);
const pad = function (n) {
return n < 10 ? '0' + n : '' + n;
};
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate())
+ ' ' + pad(date.getHours()) + ':' + pad(date.getMinutes());
}
</script>
<style scoped>
.info-card { margin: 20rpx; background: #fff; border-radius: 16rpx; padding: 30rpx; }
.card-header { margin-bottom: 20rpx; }
.card-title { font-size: 30rpx; font-weight: bold; color: #333; }
.gift-user { padding: 6rpx 0; }
.avatar { width: 72rpx; height: 72rpx; border-radius: 50%; background: #f5f5f5; flex-shrink: 0; }
.avatar-empty { display: flex; align-items: center; justify-content: center; }
.avatar-empty .iconfont { font-size: 36rpx; color: #e93323; }
.user-info { flex: 1; margin-left: 20rpx; min-width: 0; }
.gift-text { font-size: 28rpx; color: #333; display: flex; align-items: center; flex-wrap: wrap; }
.nickname { font-weight: 600; color: #333; margin-right: 8rpx; }
.gift-suffix { color: #666; }
.gift-mark {
padding: 18rpx 20rpx;
border-radius: 12rpx;
background: #faf7f5;
font-size: 26rpx;
line-height: 1.6;
}
.gift-mark-label { color: #999; }
.gift-mark-text { color: #666; }
.gift-time { flex-shrink: 0; margin-left: 20rpx; font-size: 24rpx; color: #999; }
</style>

View File

@ -6,23 +6,26 @@
-->
<template>
<view class="product-card">
<!-- 多商品模式:遍历 items 渲染每个商品 -->
<view
v-for="(item, idx) in productList"
:key="idx"
class="product-row"
@click="goDetail(item)"
>
<image :src="item.image" mode="aspectFill" class="product-image" />
<view class="product-info">
<text class="product-name">{{ item.store_name || '' }}</text>
<text v-if="getSkuText(item)" class="sku-text">{{ getSkuText(item) }}</text>
<view class="product-meta">
<text v-if="!isGiftReceiver" class="product-price">¥{{ item.true_price || item.price || '0.00' }}</text>
<text class="product-qty">x{{ item.cart_num || 1 }}</text>
<view class="card-title">{{ $t('商品信息') }}</view>
<view class="product-list">
<!-- 多商品模式:遍历 items 渲染每个商品 -->
<view
v-for="(item, idx) in productList"
:key="idx"
class="product-row"
@click="goDetail(item)"
>
<image :src="item.image" mode="aspectFill" class="product-image" />
<view class="product-info">
<text class="product-name">{{ item.store_name || '' }}</text>
<text v-if="getSkuText(item)" class="sku-text">{{ getSkuText(item) }}</text>
<view class="product-meta">
<text v-if="!isGiftReceiver" class="product-price">¥{{ getItemPrice(item) }}</text>
<text class="product-qty">x{{ item.cart_num || 1 }}</text>
</view>
</view>
<view class="arrow-icon"><text class="iconfont icon-xiangyou"></text></view>
</view>
<view class="arrow-icon"><text class="iconfont icon-xiangyou"></text></view>
</view>
</view>
</template>
@ -71,11 +74,24 @@ const productList = computed(() => {
image: product.value.image || '',
store_name: product.value.title || '',
cart_num: product.value.total_num || 0,
true_price: ctx.value.payPrice || '0.00',
price: product.value.price || ctx.value.payPrice || '0.00',
product_id: p.value.product_id || 0,
}];
});
/**
* 商品金额:展示规格原价(true_price 为优惠后单价,不作为商品金额展示)
* @param {object} item 商品项
* @return {string} 金额
*/
function getItemPrice(item) {
var attr = item.attr_info || {};
// 订单快照 item.price 可能是商品级价格,规格金额以 attr_info.price 为准
var val = attr.price || item.price || '0.00';
var num = parseFloat(val);
return isNaN(num) ? String(val) : num.toFixed(2);
}
/**
* 提取规格文本
* @param {object} item 商品项
@ -100,9 +116,11 @@ function goDetail(item) {
</script>
<style scoped>
.product-card { margin: 20rpx; background: #fff; border-radius: 16rpx; padding: 0 24rpx; }
.product-row { display: flex; align-items: center; padding: 24rpx 0; border-bottom: 1rpx solid #f5f5f5; }
.product-row:last-child { border-bottom: none; }
.product-card { margin: 20rpx; background: #fff; border-radius: 16rpx; padding: 30rpx; }
.card-title { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 20rpx; }
.product-row { display: flex; align-items: center; padding: 20rpx 0; border-bottom: 1rpx solid #f5f5f5; }
.product-row:first-child { padding-top: 0; }
.product-row:last-child { border-bottom: none; padding-bottom: 0; }
.product-image { width: 140rpx; height: 140rpx; border-radius: 12rpx; flex-shrink: 0; }
.product-info { flex: 1; margin-left: 20rpx; display: flex; flex-direction: column; }
.product-name { font-size: 28rpx; color: #333; line-height: 1.4; }

View File

@ -17,6 +17,7 @@
<countdown v-else-if="matchedKey === 'countdown'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<custom-form v-else-if="matchedKey === 'custom_form'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<faq-list v-else-if="matchedKey === 'faq_list'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<gift-info-card v-else-if="matchedKey === 'gift_info'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<fulfillment-card v-else-if="fulfillmentKeys.includes(matchedKey)" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<invoice-card v-else-if="matchedKey === 'info_list:invoice'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
<logistics-timeline v-else-if="matchedKey === 'timeline:logistics'" :section="section" @click="emit('click', $event)" @preview="emit('preview', $event)" @action="emit('action', $event)" />
@ -61,6 +62,7 @@ import Countdown from './Countdown.vue';
import CustomForm from './CustomForm.vue';
import FaqList from './FaqList.vue';
import FulfillmentCard from './FulfillmentCard.vue';
import GiftInfoCard from './GiftInfoCard.vue';
import InfoList from './InfoList.vue';
import InvoiceCard from './InvoiceCard.vue';
import LogisticsTimeline from './LogisticsTimeline.vue';

View File

@ -57,10 +57,12 @@
<image :src="item.image" mode="aspectFill" class="goods-img"></image>
<view class="goods-text">
<text class="goods-name line2">{{ item.store_name || '' }}</text>
<text v-if="getItemSkuText(item)" class="goods-sku line1">{{ getItemSkuText(item) }}</text>
<view class="goods-meta">
<text v-if="!order.is_gift_receiver" class="goods-price">¥{{ item.true_price || item.price || '0.00' }}</text>
<text class="goods-num">x{{ item.cart_num || 1 }}</text>
<view class="goods-bottom">
<text v-if="getItemSkuText(item)" class="goods-sku line1">{{ getItemSkuText(item) }}</text>
<view class="goods-meta">
<text v-if="!order.is_gift_receiver" class="goods-price">¥{{ item.true_price || item.price || '0.00' }}</text>
<text class="goods-num">x{{ item.cart_num || 1 }}</text>
</view>
</view>
</view>
</view>
@ -451,26 +453,32 @@ defineExpose({ refresh: refreshList });
border-bottom: none;
}
.my-order .list .item .item-info .multi-goods .goods-img {
width: 120rpx;
height: 120rpx;
width: 140rpx;
height: 140rpx;
border-radius: 6rpx;
flex-shrink: 0;
}
.my-order .list .item .item-info .multi-goods .goods-text {
flex: 1;
margin-left: 20rpx;
height: 140rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.my-order .list .item .item-info .multi-goods .goods-name {
font-size: 28rpx;
color: #333;
line-height: 1.4;
}
.my-order .list .item .item-info .multi-goods .goods-bottom {
display: flex;
flex-direction: column;
}
.my-order .list .item .item-info .multi-goods .goods-sku {
font-size: 24rpx;
color: #999;
margin-top: 4rpx;
margin-top: 0;
}
.my-order .list .item .item-info .multi-goods .goods-meta {
display: flex;
@ -489,8 +497,9 @@ defineExpose({ refresh: refreshList });
}
.my-order .list .item .item-info .pictrue {
width: 120rpx;
height: 120rpx;
width: 140rpx;
height: 140rpx;
flex-shrink: 0;
}
.my-order .list .item .item-info .pictrue image {
@ -500,12 +509,14 @@ defineExpose({ refresh: refreshList });
}
.my-order .list .item .item-info .text {
width: 486rpx;
flex: 1;
margin-left: 20rpx;
height: 140rpx;
font-size: 28rpx;
color: #999;
margin-top: 6rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
line-height: 39rpx;
}
@ -529,7 +540,7 @@ defineExpose({ refresh: refreshList });
.my-order .list .item .item-info .text .sku-text {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
margin-top: 0;
}
.my-order .list .item .extend-text {
@ -572,6 +583,11 @@ defineExpose({ refresh: refreshList });
border: none;
}
/* 去掉 uni-app 按钮默认 ::after 边框,避免与自定义描边叠加成双层边框 */
.my-order .list .item .bottom .bnt::after {
border: 0;
}
.my-order .list .item .bottom .bnt.cancelBnt {
border: 1rpx solid #ddd;
color: #aaa;