完成淘宝购物模块
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<view class="auto-width-input-container" :class="{ 'is-textarea': type === 'textarea' }">
|
||||
<!-- 测量层:用于计算宽度的影藏文本,必须保持与 input 相同的字体样式 -->
|
||||
<text v-if="type !== 'textarea'" class="measure-text" :style="[inputStyle, { visibility: 'hidden', position: 'absolute', whiteSpace: 'nowrap' }]">
|
||||
<text v-if="type !== 'textarea'" class="measure-text"
|
||||
:style="[inputStyle, { visibility: 'hidden', position: 'absolute', whiteSpace: 'nowrap' }]">
|
||||
{{ modelValue || placeholder }}
|
||||
</text>
|
||||
|
||||
|
|
@ -187,9 +188,10 @@ onMounted(() => {
|
|||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
|
||||
// 当父级赋予 flex-1 或手动设置 width: 100% 时,转为标准 flex 布局
|
||||
&.flex-1, &.w100 {
|
||||
&.flex-1,
|
||||
&.w100 {
|
||||
display: flex !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
|
@ -215,7 +217,7 @@ onMounted(() => {
|
|||
height: 1.4em;
|
||||
line-height: 1.4em;
|
||||
flex-shrink: 0;
|
||||
|
||||
|
||||
// 如果容器是撑开的,input 也应该撑开
|
||||
& {
|
||||
flex: 1;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,14 @@
|
|||
"navigationBarTitleText": "淘宝购物详情页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "taobao/add-shopping-order/add-shopping-order",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "新增淘宝购物订单",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<view class="card-wrapper">
|
||||
<view class="card-container" v-for="(item, index) in list" :key="index" @click.stop="clickItem(item)">
|
||||
<view class="card-container" v-for="(item, index) in list" :key="index" @click.stop="clickItem(item)"
|
||||
@touchstart="handleTouchStart($event, item)" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
|
||||
<!-- 顶部店铺和状态 -->
|
||||
<view class="card-header">
|
||||
<view class="shop-info">
|
||||
|
|
@ -25,8 +26,8 @@
|
|||
</image>
|
||||
<view class="goods-info" :id="'goods-info-' + index + '-' + gIdx">
|
||||
<view class="goods-title-row">
|
||||
<view class="good-info-box">
|
||||
<text class="goods-title">{{ goods.title }}</text>
|
||||
<view class="good-info-box" :id="'title-box-' + index + '-' + gIdx">
|
||||
<text class="goods-title">{{ getTruncatedTitle(item, index, goods, gIdx) }}</text>
|
||||
<view class="goods-spec" v-if="goods.specs">{{ goods.specs }}</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -120,7 +121,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, ref, watch, nextTick, getCurrentInstance } from 'vue';
|
||||
import { defineProps, defineEmits, ref, watch, nextTick, getCurrentInstance, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
|
|
@ -129,32 +130,81 @@ const props = defineProps({
|
|||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['action', 'detail', 'click-item']);
|
||||
const emit = defineEmits(['action', 'detail', 'click-item', 'longpress']);
|
||||
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const imgHeights = ref({});
|
||||
const titleMap = ref({}); // key: 'itemIdx-goodsIdx' → 截取后的标题
|
||||
const longPressTimer = ref(null);
|
||||
const touchStartPos = ref({ x: 0, y: 0 });
|
||||
|
||||
/**
|
||||
* 与 shopping-card.vue 对齐的字符权重截断算法
|
||||
*/
|
||||
const calcFitTitle = (originalTitle, containerWidth) => {
|
||||
const fontSize = uni.upx2px(26);
|
||||
let currentWidth = 0;
|
||||
let cutIndex = 0;
|
||||
let found = false;
|
||||
|
||||
for (let i = 0; i < originalTitle.length; i++) {
|
||||
const char = originalTitle[i];
|
||||
const charCode = char.charCodeAt(0);
|
||||
let weight = 1;
|
||||
|
||||
if (charCode <= 255) {
|
||||
if (/[A-Z]/.test(char)) weight = 0.7;
|
||||
else if (/[a-z]/.test(char)) weight = 0.5;
|
||||
else if (/[0-9]/.test(char)) weight = 0.55;
|
||||
else if (char === ' ') weight = 0.25;
|
||||
else weight = 0.5;
|
||||
}
|
||||
|
||||
currentWidth += weight * fontSize;
|
||||
|
||||
if (currentWidth > containerWidth - uni.upx2px(4)) {
|
||||
cutIndex = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found ? originalTitle.slice(0, cutIndex - 1) : originalTitle;
|
||||
};
|
||||
|
||||
/**
|
||||
* 供模板调用:返回截取后的标题
|
||||
*/
|
||||
const getTruncatedTitle = (item, index, goods, gIdx) => {
|
||||
const key = index + '-' + gIdx;
|
||||
return titleMap.value[key] !== undefined ? titleMap.value[key] : (goods.title || '');
|
||||
};
|
||||
|
||||
const calculateHeights = () => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (!instance || !instance.proxy) return;
|
||||
const query = uni.createSelectorQuery().in(instance.proxy);
|
||||
let keys = [];
|
||||
|
||||
if (!props.list || props.list.length === 0) return;
|
||||
|
||||
const heightQuery = uni.createSelectorQuery().in(instance.proxy);
|
||||
const titleQuery = uni.createSelectorQuery().in(instance.proxy);
|
||||
let keys = [];
|
||||
|
||||
props.list.forEach((item, index) => {
|
||||
if (!item.goodsList) return;
|
||||
item.goodsList.forEach((goods, gIdx) => {
|
||||
const key = index + '-' + gIdx;
|
||||
keys.push(key);
|
||||
query.select('#goods-info-' + key).boundingClientRect();
|
||||
heightQuery.select('#goods-info-' + key).boundingClientRect();
|
||||
titleQuery.select('#title-box-' + key).boundingClientRect();
|
||||
});
|
||||
});
|
||||
|
||||
if (keys.length > 0) {
|
||||
query.exec((res) => {
|
||||
// 查询商品信息区高度(用于同步图片高度)
|
||||
heightQuery.exec((res) => {
|
||||
if (res && res.length > 0) {
|
||||
res.forEach((data, i) => {
|
||||
if (data && data.height) {
|
||||
|
|
@ -163,8 +213,23 @@ const calculateHeights = () => {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 查询标题容器宽度,计算最大字符截取
|
||||
titleQuery.exec((res) => {
|
||||
if (res && res.length > 0) {
|
||||
res.forEach((data, i) => {
|
||||
if (data && data.width) {
|
||||
const [li, gi] = keys[i].split('-').map(Number);
|
||||
const goods = props.list[li]?.goodsList?.[gi];
|
||||
if (goods && goods.title) {
|
||||
titleMap.value[keys[i]] = calcFitTitle(goods.title, data.width);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100); // 延迟等待视图完全渲染
|
||||
}, 300); // 延迟等待视图渲染稳定
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -172,6 +237,12 @@ watch(() => props.list, () => {
|
|||
calculateHeights();
|
||||
}, { deep: true, immediate: true });
|
||||
|
||||
// 首次挂载后再做一次延迟校准,覆盖页面转场动画的干扰
|
||||
// 与 shopping-card.vue 的 onMounted 调用保持一致
|
||||
onMounted(() => {
|
||||
setTimeout(calculateHeights, 500);
|
||||
});
|
||||
|
||||
// 状态文案映射
|
||||
const getStatusText = (status) => {
|
||||
const map = {
|
||||
|
|
@ -268,6 +339,47 @@ const clickItem = (item) => {
|
|||
emit('click-item', item);
|
||||
}
|
||||
|
||||
const handleTouchStart = (e, item) => {
|
||||
const touch = e.touches[0];
|
||||
touchStartPos.value = { x: touch.clientX, y: touch.clientY };
|
||||
|
||||
// 清除之前的计时器
|
||||
if (longPressTimer.value) clearTimeout(longPressTimer.value);
|
||||
|
||||
// 开启 800ms 计时器 (可根据需求调整时长)
|
||||
longPressTimer.value = setTimeout(() => {
|
||||
// 触发震动反馈
|
||||
uni.vibrateShort();
|
||||
emit('longpress', {
|
||||
item,
|
||||
x: touch.clientX,
|
||||
y: touch.clientY
|
||||
});
|
||||
longPressTimer.value = null;
|
||||
}, 800);
|
||||
}
|
||||
|
||||
const handleTouchMove = (e) => {
|
||||
const touch = e.touches[0];
|
||||
const offsetX = Math.abs(touch.clientX - touchStartPos.value.x);
|
||||
const offsetY = Math.abs(touch.clientY - touchStartPos.value.y);
|
||||
|
||||
// 如果手指移动距离超过 10px,认为是在滑动,取消长按计时
|
||||
if (offsetX > 10 || offsetY > 10) {
|
||||
if (longPressTimer.value) {
|
||||
clearTimeout(longPressTimer.value);
|
||||
longPressTimer.value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
if (longPressTimer.value) {
|
||||
clearTimeout(longPressTimer.value);
|
||||
longPressTimer.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
const getTotalCount = (goodsList) => {
|
||||
if (!goodsList || !goodsList.length) return 0;
|
||||
return goodsList.reduce((sum, item) => sum + (Number(item.count) || 1), 0);
|
||||
|
|
@ -335,6 +447,8 @@ const goToDetail = (item) => {
|
|||
margin-bottom: 18rpx;
|
||||
|
||||
.goods-img {
|
||||
height: 92px;
|
||||
width: 92px;
|
||||
min-width: 178rpx;
|
||||
min-height: 178rpx;
|
||||
border-radius: 12rpx;
|
||||
|
|
@ -342,6 +456,8 @@ const goToDetail = (item) => {
|
|||
flex-shrink: 0;
|
||||
|
||||
&.refunding {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
min-width: 142rpx;
|
||||
min-height: 142rpx;
|
||||
}
|
||||
|
|
@ -367,9 +483,7 @@ const goToDetail = (item) => {
|
|||
font-size: 26rpx;
|
||||
color: #00032A;
|
||||
line-height: 36rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
margin-right: 18rpx;
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
"key": "refunding"
|
||||
},
|
||||
{
|
||||
"label": "评价",
|
||||
"label": "交易成功",
|
||||
"key": "success"
|
||||
},
|
||||
{
|
||||
"label": "已取消",
|
||||
"label": "交易关闭",
|
||||
"key": "closed"
|
||||
}
|
||||
],
|
||||
|
|
@ -45,11 +45,11 @@
|
|||
"coupons": "",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/lv.png",
|
||||
"title": "【官方正品】路易威登 经典老花手提包",
|
||||
"specs": "经典老花;手提包",
|
||||
"price": "23979.25",
|
||||
"oriPrice": "23979.25",
|
||||
"image": "",
|
||||
"title": "",
|
||||
"specs": "",
|
||||
"price": "",
|
||||
"oriPrice": "",
|
||||
"count": 1,
|
||||
"tags": "七天无理由退换"
|
||||
}
|
||||
|
|
@ -163,37 +163,37 @@
|
|||
"title": "Apple iPhone 17 Pro Max",
|
||||
"specs": "Apple/苹果 iPhone 17 Pro Max 1TB 星宇橙色",
|
||||
"price": "10999.00",
|
||||
"oriPrice": "12999.00",
|
||||
"oriPrice": " ",
|
||||
"count": 1,
|
||||
"tags": "免费上门退换 七天无理由退货"
|
||||
}
|
||||
],
|
||||
"totalPrice": "10999.00",
|
||||
"platformDiscount": "200.00",
|
||||
"platformDiscount": "",
|
||||
"storeDiscount": "",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "发货时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "付款时间",
|
||||
"key": "paymentTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016",
|
||||
"value": "",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
|
|
@ -234,8 +234,8 @@
|
|||
}
|
||||
],
|
||||
"totalPrice": "266.00",
|
||||
"platformDiscount": "30.00",
|
||||
"storeDiscount": "20.00",
|
||||
"platformDiscount": "",
|
||||
"storeDiscount": "",
|
||||
"points": "10.00",
|
||||
"coupons": "5.00",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
|
|
@ -243,31 +243,31 @@
|
|||
{
|
||||
"label": "成交时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "发货时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "付款时间",
|
||||
"key": "paymentTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016",
|
||||
"value": "",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
|
|
@ -311,25 +311,26 @@
|
|||
}
|
||||
],
|
||||
"totalPrice": "8999.00",
|
||||
"platformDiscount": "1000.00",
|
||||
"platformDiscount": "",
|
||||
"storeDiscount": "",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "成交时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016",
|
||||
"value": "",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
|
|
@ -354,6 +355,8 @@
|
|||
"statusDesc": "平台支持退款",
|
||||
"shopType": "taobao",
|
||||
"refundMoney": "199.00",
|
||||
"refundIcon": 1,
|
||||
"productImgUrl": "/static/image/shopping/taobao/detail/refund/product1.png",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "",
|
||||
|
|
@ -371,36 +374,150 @@
|
|||
{
|
||||
"label": "退款原因",
|
||||
"key": "refundReason",
|
||||
"value": "不需要了",
|
||||
"value": "七天无理由退货",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"label": "退款金额",
|
||||
"key": "refunMoney",
|
||||
"value": "199.00",
|
||||
"type": "money"
|
||||
"value": "",
|
||||
"type": "digit"
|
||||
},
|
||||
{
|
||||
"label": "退款完结",
|
||||
"key": "refunTime",
|
||||
"value": "2026-3-11 10:48",
|
||||
"type": "date"
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "申请时间",
|
||||
"key": "applyTime",
|
||||
"value": "2026-3-11 10:48",
|
||||
"type": "date"
|
||||
"value": "",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "退款编号",
|
||||
"key": "refundId",
|
||||
"value": "2026031121001039760581201016",
|
||||
"value": "",
|
||||
"type": "number"
|
||||
}
|
||||
],
|
||||
"statusDesc1": "退回支付宝",
|
||||
"statusDesc2": "您已享受全额保障5.56元"
|
||||
}
|
||||
},
|
||||
// "购物随机产品列表"
|
||||
"shoppingProductList": [
|
||||
{
|
||||
"shopType": "taobao",
|
||||
"shopName": "京东数码自营旗舰店",
|
||||
"totalPrice": "0",
|
||||
"carriage": "0.00",
|
||||
"discount": "0",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/xianka.png",
|
||||
"name": "",
|
||||
"title": "华硕 TUF 5090显卡",
|
||||
"specs": "5090旗舰算力 水冷夜神OC",
|
||||
"tags": "不支持7天无理由退货",
|
||||
"price": "39849.00",
|
||||
"count": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"shopType": "tianmao",
|
||||
"shopName": "Apple 产品京东自营旗舰店",
|
||||
"totalPrice": "",
|
||||
"platformDiscount": "10.00",
|
||||
"storeDiscount": "20.00",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/iphone.png",
|
||||
"name": "Apple iPhone 17 Pro",
|
||||
"title": "Apple/苹果 iPhone 17 Pro Max 1TB 星宇橙色",
|
||||
"specs": "星宇橙色;全网通5G",
|
||||
"tags": "免费上门退换 七天无理由退货",
|
||||
"price": "12999.00",
|
||||
"count": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"shopType": "taobao",
|
||||
"shopName": "路易威登京东官方旗舰店",
|
||||
"totalPrice": "",
|
||||
"platformDiscount": "50.00",
|
||||
"storeDiscount": "8.00",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/lv.png",
|
||||
"name": "LV",
|
||||
"title": "路易威登 经典老花手提包",
|
||||
"specs": "经典老花;手提包",
|
||||
"tags": "次日达",
|
||||
"price": "23979.25",
|
||||
"count": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"shopType": "tianmao",
|
||||
"shopName": "索尼(SONY)数码京东官方旗舰店",
|
||||
"totalPrice": "15499.00",
|
||||
"platformDiscount": "1.32",
|
||||
"storeDiscount": "2.3",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/sony.png",
|
||||
"name": "Sony",
|
||||
"title": "索尼(SONY)Alpha 7 IV 全画幅微单数码相机",
|
||||
"specs": "单机身(不含镜头);约3300万有效像素",
|
||||
"tags": "厂家发货",
|
||||
"price": "15499.00",
|
||||
"count": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"shopType": "tianmao",
|
||||
"shopName": "京东超市-五粮液自营店",
|
||||
"totalPrice": "2198.00",
|
||||
"platformDiscount": "100.00",
|
||||
"storeDiscount": "200.00",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/wuliangye.png",
|
||||
"name": "五粮液",
|
||||
"title": "五粮液 普五 第八代 浓香型白酒 52度 500ml*2瓶",
|
||||
"specs": "500ml*2礼盒装;浓香型",
|
||||
"tags": "211限时达",
|
||||
"price": "1099.00",
|
||||
"count": "2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"shopType": "taobao",
|
||||
"shopName": "戴森Dyson京东自营官方旗舰店",
|
||||
"totalPrice": "3299.00",
|
||||
"platformDiscount": "150.00",
|
||||
"storeDiscount": "200.00",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/dyson_v12.png",
|
||||
"name": "戴森",
|
||||
"title": "戴森(Dyson) V12 Detect Slim 无绳吸尘器",
|
||||
"specs": "轻量版;激光探测;轻量吸尘器",
|
||||
"tags": "次日达",
|
||||
"price": "3299.00",
|
||||
"count": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
],
|
||||
//默认数据
|
||||
"defualtData": [
|
||||
{
|
||||
"id": "202605110001",
|
||||
|
|
@ -576,248 +693,7 @@
|
|||
"statusDesc1": "已签收",
|
||||
"statusDesc2": "【上海市】 您已在上海市浦东新区汤臣一品完成取件",
|
||||
"confirmReceiptCountdown": "9天7小时"
|
||||
},
|
||||
{
|
||||
"id": "202605110008",
|
||||
"orderType": "shopping",
|
||||
"shopName": "Apple 官方旗舰店",
|
||||
"statusType": "wait_recv",
|
||||
"address": "上海市浦东新区汤臣一品",
|
||||
"userName": "张三",
|
||||
"phone": "13812345678",
|
||||
"isSignFor": false,
|
||||
"shopType": "taobao",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "/static/image/shopping/jingdong/product/shopping/iphone.png",
|
||||
"title": "Apple iPhone 17 Pro Max",
|
||||
"specs": "Apple/苹果 iPhone 17 Pro Max 1TB 星宇橙色",
|
||||
"price": "10999.00",
|
||||
"oriPrice": "12999.00",
|
||||
"count": 1,
|
||||
"tags": "免费上门退换 七天无理由退货"
|
||||
}
|
||||
],
|
||||
"totalPrice": "10999.00",
|
||||
"platformDiscount": "200.00",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "发货时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "付款时间",
|
||||
"key": "paymentTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016"
|
||||
},
|
||||
{
|
||||
"label": "交易快照",
|
||||
"key": "transactionSnapshot",
|
||||
"value": "发生交易争执时,可作为判断依据"
|
||||
},
|
||||
{
|
||||
"label": "支付方式",
|
||||
"key": "paymentMethod",
|
||||
"value": "支付宝支付"
|
||||
}
|
||||
],
|
||||
"statusDesc1": "预计明天送达",
|
||||
"statusDesc2": "【上海市】 快件已发往 上海转运中心,下一站浦东新区"
|
||||
},
|
||||
{
|
||||
"id": "202605110005",
|
||||
"orderType": "shopping",
|
||||
"shopName": "三只松鼠旗舰店",
|
||||
"statusType": "success",
|
||||
"shopType": "taobao",
|
||||
"address": "上海市浦东新区汤臣一品",
|
||||
"userName": "张三",
|
||||
"phone": "13812345678",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "",
|
||||
"title": "三只松鼠 坚果大礼包 每日坚果 送礼佳品 1498g",
|
||||
"specs": "颜色分类: 坚果礼盒1498g",
|
||||
"price": "128.00",
|
||||
"oriPrice": "158.00",
|
||||
"count": 2,
|
||||
"tags": "正品保障"
|
||||
}
|
||||
],
|
||||
"totalPrice": "266.00",
|
||||
"platformDiscount": "30.00",
|
||||
"storeDiscount": "20.00",
|
||||
"points": "10.00",
|
||||
"coupons": "5.00",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "成交时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "发货时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "付款时间",
|
||||
"key": "paymentTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016"
|
||||
},
|
||||
{
|
||||
"label": "交易快照",
|
||||
"key": "transactionSnapshot",
|
||||
"value": "发生交易争执时,可作为判断依据"
|
||||
},
|
||||
{
|
||||
"label": "收货信息",
|
||||
"key": "shippingInfo",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"label": "支付方式",
|
||||
"key": "paymentMethod",
|
||||
"value": "支付宝支付"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "202605110006",
|
||||
"orderType": "shopping",
|
||||
"shopName": "Apple Store 官方旗舰店",
|
||||
"statusType": "closed",
|
||||
"shopType": "tianmao",
|
||||
"address": "上海市浦东新区汤臣一品",
|
||||
"userName": "张三",
|
||||
"phone": "13812345678",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "",
|
||||
"title": "Apple iPhone 15 Pro (A3104) 256GB 原色钛金属 5G手机",
|
||||
"specs": "颜色分类: 原色钛金属; 内存容量: 256GB",
|
||||
"price": "8999.00",
|
||||
"oriPrice": "9999.00",
|
||||
"count": 1,
|
||||
"tags": "正品保障"
|
||||
}
|
||||
],
|
||||
"totalPrice": "8999.00",
|
||||
"platformDiscount": "1000.00",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "成交时间",
|
||||
"key": "deliveryTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "创建时间",
|
||||
"key": "createTime",
|
||||
"value": "2026-03-11 09:48:05",
|
||||
"type": "time"
|
||||
},
|
||||
{
|
||||
"label": "支付宝交易号",
|
||||
"key": "alipayTransactionNum",
|
||||
"value": "2026031121001039760581201016"
|
||||
},
|
||||
{
|
||||
"label": "交易快照",
|
||||
"key": "transactionSnapshot",
|
||||
"value": "发生交易争执时,可作为判断依据"
|
||||
},
|
||||
{
|
||||
"label": "收货信息",
|
||||
"key": "shippingInfo",
|
||||
"value": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "202605110007",
|
||||
"orderType": "shopping",
|
||||
"shopName": "优衣库官方旗舰店",
|
||||
"statusType": "refunding",
|
||||
"statusDesc": "平台支持退款",
|
||||
"shopType": "taobao",
|
||||
"refundMoney": "199.00",
|
||||
"goodsList": [
|
||||
{
|
||||
"image": "",
|
||||
"title": "UNIQLO 优衣库 男装/女装 摇粒绒拉链运动开衫(长袖) 463351",
|
||||
"specs": "颜色分类: 藏青色; 尺码: L",
|
||||
"price": "199.00",
|
||||
"count": 1,
|
||||
"tags": "正品保障",
|
||||
"refundStatus": "退款成功"
|
||||
}
|
||||
],
|
||||
"totalPrice": "199.00",
|
||||
"orderId": "2026031121001039760581201016",
|
||||
"orderInfo": [
|
||||
{
|
||||
"label": "退款原因",
|
||||
"key": "refundReason",
|
||||
"value": "不需要了",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"label": "退款金额",
|
||||
"key": "refunMoney",
|
||||
"value": "199.00",
|
||||
"type": "money"
|
||||
},
|
||||
{
|
||||
"label": "退款完结",
|
||||
"key": "refunTime",
|
||||
"value": "2026-3-11 10:48",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"label": "申请时间",
|
||||
"key": "applyTime",
|
||||
"value": "2026-3-11 10:48",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"label": "退款编号",
|
||||
"key": "refundId",
|
||||
"value": "2026031121001039760581201016"
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
// {
|
||||
// "id": "202605110008",
|
||||
// "orderType": "waimai",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<image class="search-icon" src="/static/image/shopping/jingdong/search-icon.png"
|
||||
mode="aspectFit">
|
||||
</image>
|
||||
<input class="input" type="text" placeholder="搜索我的订单" :disabled="true" />
|
||||
<input class="input" type="text" placeholder="搜索我的订单" />
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right>
|
||||
|
|
@ -32,6 +32,9 @@
|
|||
</view>
|
||||
</template>
|
||||
</nav-bar>
|
||||
<nav-bar v-else title="拼图" bgColor="#EFEFEF" noBack @back="closeImage" isRightButton
|
||||
@right-click="confirmImage">
|
||||
</nav-bar>
|
||||
<view class="tab-list">
|
||||
<view class="tab-item" v-for="(item, index) in tabList" :key="index"
|
||||
:class="{ active: currentTab === index }" @click="switchTab(index)">
|
||||
|
|
@ -75,29 +78,141 @@
|
|||
<uni-icons type="right" size="14" color="#5E6367"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<listCard :list="displayList" @click-item="goDetail" />
|
||||
<listCard v-if="displayList.length > 0" :list="displayList" @click-item="goDetail"
|
||||
@longpress="onItemLongPress" />
|
||||
<view v-else class="null-data-box flex-center flex-column">
|
||||
<image style="width: 254rpx;height: 200rpx;" src="/static/image/shopping/taobao/null.png"></image>
|
||||
<text
|
||||
style="font-size: 28rpx;color: #7C8495;line-height: 28rpx;margin-top: 16rpx;font-weight: 500;">您还没有相关的订单</text>
|
||||
</view>
|
||||
<view class="bottom-fixed" style="height: 1000rpx;">
|
||||
<view v-if="!selectedImage" class="upload-screenshot-box" @touchstart="handleTouchStart"
|
||||
@touchend="handleTouchEnd">
|
||||
<view v-if="!screenshotImage" class="upload-screenshot-content">
|
||||
<image class="upload-screenshot" src="/static/image/common/upload-screenshot.png"
|
||||
mode="aspectFit">
|
||||
</image>
|
||||
<view class="upload-screenshot-text">长按替换截图</view>
|
||||
</view>
|
||||
<view v-else class="screenshot-preview-box">
|
||||
<image class="screenshot-preview" :src="screenshotImage" mode="widthFix"></image>
|
||||
</view>
|
||||
<!-- <image v-else class="w100 h100" :src="screenshotImage" mode="widthFix"></image> -->
|
||||
</view>
|
||||
<view v-else class="upload-screenshot-box scroll-image-box">
|
||||
<scroll-view class="image-box" style="width: 100%;height: 100%;" scroll-y :show-scrollbar="false"
|
||||
@scroll="onImageScroll">
|
||||
<image class="crop-image-target" style="width:100%;" :src="selectedImage" mode="widthFix">
|
||||
</image>
|
||||
</scroll-view>
|
||||
<view class="dashed-line-box">
|
||||
<view class="dashed-line-text">我是分割线</view>
|
||||
</view>
|
||||
</view>
|
||||
<canvas canvas-id="crop-canvas"
|
||||
style="position: fixed; left: -9999px; width: 750rpx; height: 100vh; pointer-events: none;"></canvas>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 自定义长按上下文菜单 -->
|
||||
<view v-if="menuState.show" class="menu-mask" @click="menuState.show = false" @touchmove.stop.prevent>
|
||||
<view class="menu-content" :style="{ top: menuState.y + 'px', left: menuState.x + 'px' }">
|
||||
<view class="menu-item" @click.stop="handleMenuAction('edit')">
|
||||
<uni-icons type="compose" size="18" color="#1A1A1A"></uni-icons>
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="menu-line"></view>
|
||||
<view class="menu-item" @click.stop="handleMenuAction('delete')">
|
||||
<uni-icons type="trash" size="18" color="#FF4D4F"></uni-icons>
|
||||
<text style="color: #FF4D4F;">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<!-- <view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_shopping_taobao" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_shopping_taobao')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
</liu-drag-button>
|
||||
</view> -->
|
||||
<!-- 切换底部图片弹窗 -->
|
||||
<uni-popup ref="bottomImgPopup" type="center">
|
||||
<view class="bottom-img-popup-card">
|
||||
<view class="p-header">选择底部商品图</view>
|
||||
<view class="p-content">
|
||||
<view class="option-item" @click="selectBottomImg(1)">
|
||||
<image class="preview-img" src="/static/image/shopping/taobao/bottom-bg-1.png" mode="aspectFill">
|
||||
</image>
|
||||
<view class="info">
|
||||
<text class="name">商品图片 1</text>
|
||||
<text class="desc">默认背景布局</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#C7C7CC"></uni-icons>
|
||||
</view>
|
||||
<view class="option-item" @click="selectBottomImg(2)">
|
||||
<image class="preview-img" src="/static/image/shopping/taobao/bottom-bg-2.png" mode="aspectFill">
|
||||
</image>
|
||||
<view class="info">
|
||||
<text class="name">商品图片 2</text>
|
||||
<text class="desc">备选商品排列</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#C7C7CC"></uni-icons>
|
||||
</view>
|
||||
<text
|
||||
style="color: #949494;font-size: 24rpx;text-align: center;display: block;">*长按底部商品图片区域可上传自定义图片*</text>
|
||||
</view>
|
||||
<view class="p-footer" @click="bottomImgPopup.close()">取消</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, getCurrentInstance } from 'vue';
|
||||
import { ref, computed, onMounted, getCurrentInstance, reactive } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { util } from '@/utils/common.js';
|
||||
import listCard from './components/list-card/list-card.vue';
|
||||
import { defualtData } from './json/order.json'
|
||||
|
||||
const mockList = ref(defualtData);
|
||||
const instance = getCurrentInstance();
|
||||
const mockList = ref([]);
|
||||
const menuState = reactive({
|
||||
show: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
target: null
|
||||
});
|
||||
|
||||
const bottomImgPopup = ref(null);
|
||||
|
||||
const selectBottomImg = (type) => {
|
||||
const path = `/static/image/shopping/taobao/bottom-bg-${type}.png`;
|
||||
screenshotImage.value = path;
|
||||
uni.setStorageSync('taobao_screenshot', path);
|
||||
bottomImgPopup.value.close();
|
||||
uni.showToast({
|
||||
title: '切换成功',
|
||||
icon: 'success'
|
||||
});
|
||||
};
|
||||
|
||||
onShow(() => {
|
||||
// 加载缓存数据
|
||||
let storageData = uni.getStorageSync('taobaoShopping');
|
||||
|
||||
// 如果缓存为空,则初始化默认数据
|
||||
if (!storageData || (Array.isArray(storageData) && storageData.length === 0)) {
|
||||
console.log('检测到淘宝订单缓存为空,注入初始默认数据');
|
||||
storageData = JSON.parse(JSON.stringify(defualtData));
|
||||
uni.setStorageSync('taobaoShopping', storageData);
|
||||
}
|
||||
|
||||
mockList.value = storageData || [];
|
||||
|
||||
// 加载拼图截图缓存 (若不存在则初始化默认底图)
|
||||
let savedScreenshot = uni.getStorageSync('taobao_screenshot');
|
||||
if (!savedScreenshot) {
|
||||
savedScreenshot = '/static/image/shopping/taobao/bottom-bg-1.png';
|
||||
uni.setStorageSync('taobao_screenshot', savedScreenshot);
|
||||
}
|
||||
screenshotImage.value = savedScreenshot;
|
||||
});
|
||||
|
||||
|
||||
//导航栏菜单按钮
|
||||
const buttonGroup = [
|
||||
|
|
@ -105,7 +220,7 @@ const buttonGroup = [
|
|||
name: "新增购物订单",
|
||||
click: () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/shopping/taobao/add-order/add-order'
|
||||
url: '/pages/shopping/taobao/add-shopping-order/add-shopping-order'
|
||||
});
|
||||
}
|
||||
}, {
|
||||
|
|
@ -115,15 +230,17 @@ const buttonGroup = [
|
|||
title: '开发中,敬请期待',
|
||||
icon: 'none'
|
||||
});
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/shopping/jingdong/add-waimai/add-waimai'
|
||||
// });
|
||||
}
|
||||
}, {
|
||||
name: "切换底部商品图片",
|
||||
click: () => {
|
||||
bottomImgPopup.value.open();
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
const displayList = computed(() => {
|
||||
let list = mockList.value;
|
||||
let list = JSON.parse(JSON.stringify(mockList.value));
|
||||
|
||||
// 1. 一级 Tab 过滤 (orderType)
|
||||
if (currentTab.value === 1) { // 购物
|
||||
|
|
@ -135,15 +252,14 @@ const displayList = computed(() => {
|
|||
// 2. 二级分类过滤 (currentFilter)
|
||||
if (currentFilter.value > 0) {
|
||||
const filterName = filterList.value[currentFilter.value]?.name;
|
||||
|
||||
// 统一定义状态映射
|
||||
const statusMap = {
|
||||
'待付款': ['wait_pay'],
|
||||
'待发货': ['wait_send'],
|
||||
'待收货': ['wait_recv'],
|
||||
'退款/售后': ['refunding'],
|
||||
'已关闭': ['closed'],
|
||||
'待评价': ['success'] // 闪购下 success 状态代表已送达可评价
|
||||
'评价': ['success'],
|
||||
'已关闭': ['closed']
|
||||
|
||||
};
|
||||
|
||||
const targetStatus = statusMap[filterName];
|
||||
|
|
@ -152,6 +268,19 @@ const displayList = computed(() => {
|
|||
}
|
||||
}
|
||||
|
||||
// 3. 时间降序排列逻辑 (创建时间 || 申请时间)
|
||||
list.sort((a, b) => {
|
||||
const getTime = (order) => {
|
||||
if (!order.orderInfo) return '';
|
||||
const create = order.orderInfo.find(i => i.key === 'createTime')?.value;
|
||||
const apply = order.orderInfo.find(i => i.key === 'applyTime')?.value;
|
||||
return create || apply || '';
|
||||
};
|
||||
const timeA = getTime(a);
|
||||
const timeB = getTime(b);
|
||||
return timeB.localeCompare(timeA); // 降序
|
||||
});
|
||||
|
||||
return list;
|
||||
});
|
||||
|
||||
|
|
@ -162,6 +291,7 @@ const filterList = ref([
|
|||
{ name: '待发货' },
|
||||
{ name: '待收货' },
|
||||
{ name: '退款/售后' },
|
||||
{ name: '评价' },
|
||||
{ name: '已关闭' }
|
||||
]);
|
||||
|
||||
|
|
@ -173,6 +303,170 @@ const tabList = ref([
|
|||
{ name: '飞猪', icon: '/static/image/shopping/taobao/lvxing.png', disabled: true }
|
||||
]);
|
||||
|
||||
// 长按替换截图相关
|
||||
const screenshotImage = ref('');
|
||||
const selectedImage = ref('');
|
||||
const scrollTop = ref(0);
|
||||
let longPressTimer = null;
|
||||
|
||||
|
||||
// 长按替换截图 - 选择图片
|
||||
const chooseImage = () => {
|
||||
if (selectedImage.value) return;
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: ['album'],
|
||||
success: (res) => {
|
||||
selectedImage.value = res.tempFilePaths[0];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 长按事件
|
||||
const handleTouchStart = (e) => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
if (systemInfo.platform === 'ios' && systemInfo.safeAreaInsets?.bottom) {
|
||||
const clientY = e.touches[0].clientY;
|
||||
const windowHeight = systemInfo.windowHeight;
|
||||
if (clientY > windowHeight - systemInfo.safeAreaInsets.bottom) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
longPressTimer = setTimeout(() => {
|
||||
uni.vibrateShort();
|
||||
chooseImage();
|
||||
}, 1200);
|
||||
};
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
if (longPressTimer) {
|
||||
clearTimeout(longPressTimer);
|
||||
longPressTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 图片滚动
|
||||
const onImageScroll = (e) => {
|
||||
scrollTop.value = e.detail.scrollTop;
|
||||
};
|
||||
// 确认图片裁剪
|
||||
const confirmImage = () => {
|
||||
uni.showLoading({
|
||||
title: '处理中...'
|
||||
})
|
||||
const query = uni.createSelectorQuery().in(instance)
|
||||
|
||||
// 获取容器和图片信息
|
||||
query.select('.image-box').boundingClientRect()
|
||||
query.select('.crop-image-target').boundingClientRect()
|
||||
query.exec(res => {
|
||||
if (!res[0] || !res[1]) {
|
||||
uni.hideLoading()
|
||||
return
|
||||
}
|
||||
|
||||
console.log('rects', res)
|
||||
const container = res[0] // 容器
|
||||
const image = res[1] // 图片实际渲染尺寸
|
||||
|
||||
// 计算缩放比例 (渲染宽度 / 实际宽度 不准确,应该反过来用 图片原始宽/渲染宽?)
|
||||
// 这里更简单的方法是:canvas设为容器大小,把图片画进去
|
||||
// canvas drawImage 参数: img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight
|
||||
|
||||
// 获取图片原始尺寸
|
||||
uni.getImageInfo({
|
||||
src: selectedImage.value,
|
||||
success: (imgInfo) => {
|
||||
const scale = imgInfo.width / image.width // 图片 原始宽 / 渲染宽
|
||||
const sTop = scrollTop.value * scale // 原始图上的裁切起始Y
|
||||
const sHeight = container.height * scale // 原始图上的裁切高度
|
||||
|
||||
// 因为是 widthFix,宽度就是原始图宽度(或裁切全宽)
|
||||
const sWidth = imgInfo.width
|
||||
|
||||
// 设置画布尺寸 (使用像素值)
|
||||
// 注意:canvasContext绘制使用的是逻辑像素还是物理像素?通常需要考虑到 pixelRatio,
|
||||
// 但 uni-app canvas-id 方式通常对应逻辑像素(px)
|
||||
// 我们把 canvas 大小设为和容器显示一致
|
||||
const canvasW = container.width
|
||||
const canvasH = container.height
|
||||
|
||||
const ctx = uni.createCanvasContext('crop-canvas', instance)
|
||||
|
||||
// 清除画布
|
||||
ctx.clearRect(0, 0, canvasW, canvasH)
|
||||
|
||||
// 绘制
|
||||
// drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
||||
ctx.drawImage(
|
||||
imgInfo.path,
|
||||
0, sTop, sWidth, sHeight, // 源图裁剪区域
|
||||
0, 0, canvasW, canvasH // 画布绘制区域
|
||||
)
|
||||
ctx.draw(false, () => {
|
||||
uni.canvasToTempFilePath({
|
||||
canvasId: 'crop-canvas',
|
||||
width: canvasW,
|
||||
height: canvasH,
|
||||
destWidth: sWidth, // 使用原图实际宽度,保持原图清晰度
|
||||
destHeight: sHeight, // 使用原图实际高度,保持原图清晰度
|
||||
success: (res) => {
|
||||
console.log('crop success (temp)', res
|
||||
.tempFilePath)
|
||||
|
||||
// 将临时路径保存为永久路径
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: (saveRes) => {
|
||||
console.log('save success (saved)', saveRes.savedFilePath)
|
||||
screenshotImage.value = saveRes.savedFilePath
|
||||
selectedImage.value = '' // 隐藏编辑模式
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
}, 200)
|
||||
// 保存到缓存
|
||||
uni.setStorageSync('taobao_screenshot', screenshotImage.value)
|
||||
uni.hideLoading()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('saveFile fail', err)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error(err)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '裁剪失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}, instance)
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '图片加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭截图预览
|
||||
const closeImage = () => {
|
||||
selectedImage.value = '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 切换tab
|
||||
* @param index
|
||||
|
|
@ -194,10 +488,10 @@ const updateFilterList = () => {
|
|||
// 根据tab切换不同的筛选项数据
|
||||
switch (currentTab.value) {
|
||||
case 0:
|
||||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "已关闭"];
|
||||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "评价", "已关闭"];
|
||||
break;
|
||||
case 1:
|
||||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "已关闭"];
|
||||
sourceList = ["全部", "待付款", "待发货", "待收货", "退款/售后", "评价", "已关闭"];
|
||||
break;
|
||||
case 2:
|
||||
sourceList = ["全部", "待付款", "待发货", "待收货", "待评价", "已关闭"];
|
||||
|
|
@ -229,6 +523,89 @@ const goDetail = (item) => {
|
|||
util.goPage(`/pages/shopping/taobao/shopping-order-detail/shopping-order-detail?id=${item.id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 长按管理订单 - 记录坐标并显示自定义菜单
|
||||
*/
|
||||
const onItemLongPress = (data) => {
|
||||
const { item, x, y } = data;
|
||||
menuState.target = item;
|
||||
|
||||
// 计算菜单位置,避免手指遮挡(向上偏移 60px,向左偏移 40px)
|
||||
// 并简单处理边界溢出(示例:不超出右边界)
|
||||
const screenWidth = uni.getSystemInfoSync().windowWidth;
|
||||
let posX = x - 40;
|
||||
if (posX + 120 > screenWidth) {
|
||||
posX = screenWidth - 130;
|
||||
}
|
||||
|
||||
menuState.x = Math.max(10, posX);
|
||||
menuState.y = y - 80;
|
||||
menuState.show = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理菜单点击
|
||||
*/
|
||||
const handleMenuAction = (action) => {
|
||||
const item = menuState.target;
|
||||
menuState.show = false;
|
||||
if (!item) return;
|
||||
|
||||
if (action === 'edit') {
|
||||
uni.navigateTo({
|
||||
url: `/pages/shopping/taobao/add-shopping-order/add-shopping-order?id=${item.id}&isEdit=true`
|
||||
});
|
||||
} else if (action === 'delete') {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除该订单吗?',
|
||||
confirmColor: '#FF7824',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
deleteOrder(item.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 从缓存执行删除
|
||||
*/
|
||||
const deleteOrder = (id) => {
|
||||
let list = uni.getStorageSync('taobaoShopping') || [];
|
||||
|
||||
// 1. 物理删除关联图片
|
||||
const target = list.find(item => String(item.id) === String(id));
|
||||
if (target) {
|
||||
const imagesToClear = [];
|
||||
if (target.goodsList?.[0]?.image) imagesToClear.push(target.goodsList[0].image);
|
||||
if (target.productImgUrl) imagesToClear.push(target.productImgUrl);
|
||||
|
||||
imagesToClear.forEach(path => {
|
||||
if (path && (path.includes('_doc') || path.includes('store_'))) {
|
||||
uni.removeSavedFile({
|
||||
filePath: path,
|
||||
success: () => console.log('删除订单关联图片成功:', path),
|
||||
fail: (err) => console.log('图片文件不存在或已删除:', path)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 移除缓存记录
|
||||
list = list.filter(item => String(item.id) !== String(id));
|
||||
// 同步缓存
|
||||
uni.setStorageSync('taobaoShopping', list);
|
||||
// 同步 UI
|
||||
mockList.value = list;
|
||||
|
||||
uni.showToast({
|
||||
title: '已删除',
|
||||
icon: 'success'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
|
@ -450,7 +827,252 @@ const goDetail = (item) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9999;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
position: absolute;
|
||||
width: 240rpx;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
overflow: hidden;
|
||||
animation: menu-show 0.15s ease-out;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx;
|
||||
transition: background 0.2s;
|
||||
|
||||
&:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
margin-left: 16rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-line {
|
||||
height: 1px;
|
||||
background-color: #EEEEEE;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
|
||||
@keyframes menu-show {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.null-data-box {
|
||||
padding: 68rpx;
|
||||
}
|
||||
|
||||
.bottom-fixed {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.upload-screenshot-box {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 540rpx;
|
||||
background-color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.upload-screenshot {
|
||||
width: 92rpx;
|
||||
height: 92rpx;
|
||||
}
|
||||
|
||||
.upload-screenshot-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.upload-screenshot-text {
|
||||
font-size: 36rpx;
|
||||
color: #1777FF;
|
||||
line-height: 50rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.screenshot-preview-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
// flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.screenshot-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-image-box {
|
||||
width: 100%;
|
||||
min-height: 0; // 修复 flex一出问题
|
||||
// overflow: hidden; // scroll-view 需要
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dashed-line-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 4rpx dashed #ffffff;
|
||||
pointer-events: none;
|
||||
|
||||
.dashed-line-text {
|
||||
height: 44rpx;
|
||||
line-height: 44rpx;
|
||||
width: 180rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #1777FF;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
z-index: 999;
|
||||
|
||||
.mask-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 52rpx;
|
||||
transform: translateY(-25%);
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-img-popup-card {
|
||||
width: 600rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 32rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.15);
|
||||
|
||||
.p-header {
|
||||
padding: 40rpx 0 20rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.p-content {
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #F8F9FA;
|
||||
border-radius: 20rpx;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:active {
|
||||
background-color: #F0F2F5;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
margin: 0 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 22rpx;
|
||||
color: #8E8E93;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.p-footer {
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
text-align: center;
|
||||
border-top: 1rpx solid #F0F2F5;
|
||||
font-size: 30rpx;
|
||||
color: #8E8E93;
|
||||
|
||||
&:active {
|
||||
background-color: #F8F9FA;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
|
||||
page {
|
||||
background-color: #F1F5F8;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,30 +2,26 @@
|
|||
<nav-bar title="订单详情" bgColor="#FFFFFF" isBack :buttonGroup="buttonGroup" @button-click="util.clickTitlePopupButton"
|
||||
tipLayerType="taobao-shopping-order-detail-tip" isTipLayer tipLayerText="编辑订单信息">
|
||||
<template v-slot:left>
|
||||
<image @click="util.goBack" class="back-icon"
|
||||
:src="`/static/image/shopping/taobao/detail/${order.statusType == 'refunding' ? 'refund-back' : 'back'}.png`"
|
||||
<image v-if="order" @click="util.goBack" class="back-icon"
|
||||
:src="`/static/image/shopping/taobao/detail/${order?.statusType == 'refunding' ? 'refund-back' : 'back'}.png`"
|
||||
mode="aspectFit"></image>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<view v-if="order.statusType == 'refunding'" class="refunding-title-box">
|
||||
<image class="icon" src="/static/image/shopping/taobao/detail/refund/finish.png">
|
||||
</image>
|
||||
<text>商家处理</text>
|
||||
<image class="next icon" style="width: 20rpx;height: 20rpx;"
|
||||
src="/static/image/shopping/taobao/detail/refund/next.png">
|
||||
</image>
|
||||
<image class="icon" src="/static/image/shopping/taobao/detail/refund/finish.png">
|
||||
</image>
|
||||
<text>寄回商品</text>
|
||||
<image class="icon next" style="width: 20rpx;height: 20rpx;"
|
||||
src="/static/image/shopping/taobao/detail/refund/next.png">
|
||||
</image>
|
||||
<text>3退款结束</text>
|
||||
</view>
|
||||
<view v-else class="title-box">
|
||||
<view class="title">{{ titleList[order.statusType] }}</view>
|
||||
<view v-if="order.statusType == 'wait_recv' && order.isSignFor" class="desc">
|
||||
还剩{{ order.confirmReceiptCountdown }}自动确认</view>
|
||||
<view v-if="order" class="center-content">
|
||||
<view v-if="order.statusType == 'refunding'" class="refunding-title-box">
|
||||
<image class="icon" src="/static/image/shopping/taobao/detail/refund/finish.png"></image>
|
||||
<text>商家处理</text>
|
||||
<image class="next icon" src="/static/image/shopping/taobao/detail/refund/next.png"></image>
|
||||
<image class="icon" src="/static/image/shopping/taobao/detail/refund/finish.png"></image>
|
||||
<text>寄回商品</text>
|
||||
<image class="icon next" src="/static/image/shopping/taobao/detail/refund/next.png"></image>
|
||||
<text>3退款结束</text>
|
||||
</view>
|
||||
<view v-else class="title-box">
|
||||
<view class="title">{{ titleList[order.statusType] }}</view>
|
||||
<view v-if="order.statusType == 'wait_recv' && order.isSignFor" class="desc">
|
||||
还剩{{ order.confirmReceiptCountdown }}自动确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right>
|
||||
|
|
@ -36,7 +32,7 @@
|
|||
</template>
|
||||
</nav-bar>
|
||||
|
||||
<view v-if="order.statusType != 'refunding'">
|
||||
<view v-if="order && order.statusType != 'refunding'">
|
||||
<view v-if="order.statusType == 'wait_recv'" class="card status-box">
|
||||
<image style="width: 34rpx;height: 34rpx;flex-shrink: 0;margin-right: 8rpx;"
|
||||
:src="`/static/image/shopping/taobao/detail/${order.statusType == 'wait_recv' && order.isSignFor ? 'yiqianshou' : 'yunshuzhong'}.png`"
|
||||
|
|
@ -100,7 +96,8 @@
|
|||
<view class="goods-title flex-justify-between flex-align-center">
|
||||
<view class="title-box flex ">
|
||||
<text class="title flex-1">{{ item.title }}</text>
|
||||
<uni-icons class="uni-icon" type="down" size="12" color="#7C8495"></uni-icons>
|
||||
<uni-icons v-if="item.title.length > 15" class="uni-icon" type="down" size="12"
|
||||
color="#7C8495"></uni-icons>
|
||||
</view>
|
||||
|
||||
<text class="price wx-font-medium flex-align-center"><text class="small">¥</text>{{
|
||||
|
|
@ -112,13 +109,14 @@
|
|||
<view class="goods-specs flex-justify-between flex-align-center">
|
||||
<view class="title-box flex ">
|
||||
<text class="title flex-1">{{ item.specs }}</text>
|
||||
<uni-icons class="uni-icon" type="down" size="12" color="#7C8495"></uni-icons>
|
||||
<uni-icons v-if="item.specs.length > 15" class="uni-icon" type="down" size="12"
|
||||
color="#7C8495"></uni-icons>
|
||||
</view>
|
||||
|
||||
<text
|
||||
v-if="item.oriPrice && Number(item.oriPrice) > 0 && Number(item.oriPrice) > Number(item.price)"
|
||||
class="price wx-font-medium flex-align-center"><text class="small">¥</text>{{
|
||||
item.oriPrice }}</text>
|
||||
Number(item.oriPrice).toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="inline-tag flex-justify-between flex-align-center">
|
||||
<text class="desc flex-1">
|
||||
|
|
@ -219,8 +217,18 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card service-card flex-align-center flex-justify-between">
|
||||
<text class="label">服务保障</text>
|
||||
<view class="">
|
||||
<text class="more">查看更多</text>
|
||||
<uni-icons type="right" size="14" color="#EF7518"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top: 16rpx;">
|
||||
<image style="width: 100%;" :src="screenshotImage" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-else>
|
||||
<view v-else-if="order.statusType == 'refunding'">
|
||||
<view class="card refund-box">
|
||||
<view class="card flex-column flex-align-center">
|
||||
<view class="main-text">退款成功</view>
|
||||
|
|
@ -228,8 +236,9 @@
|
|||
<view class="line"></view>
|
||||
</view>
|
||||
<view class="flex-align-center refund-money-box" style="line-height: 34rpx;">
|
||||
<image style="width: 34rpx;height: 34rpx;margin-right: 16rpx;" src=""></image>
|
||||
<text class="label flex-1">退回支付宝小荷包</text>
|
||||
<image style="width: 34rpx;height: 34rpx;margin-right: 16rpx;"
|
||||
:src="`/static/image/shopping/taobao/detail/refund/icon${order.refundIcon}.png`"></image>
|
||||
<text class="label flex-1">{{ order.statusDesc1 }}</text>
|
||||
<text class="wx-font-medium">
|
||||
<text style="font-size: 28rpx;">¥</text>
|
||||
<text style="font-size: 38rpx;">{{ Number(order.refundMoney).toFixed(2).split('.')[0] }}.</text>
|
||||
|
|
@ -241,7 +250,7 @@
|
|||
src="/static/image/shopping/taobao/detail/refund/yunfeibaozhang.png"></image>
|
||||
<view>
|
||||
<view class="label">运费保障</view>
|
||||
<view class="desc">您已享受全额保障5.56元</view>
|
||||
<view class="desc">{{ order.statusDesc2 }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -276,6 +285,11 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="product-img-card">
|
||||
<image :src="order.productImgUrl || '/static/image/shopping/taobao/detail/refund/product1.png'"
|
||||
style="width: 100%;" mode="widthFix">
|
||||
</image>
|
||||
</view>
|
||||
<view class="card help-box">
|
||||
<view class="flex-align-center card-title-box">
|
||||
<image style="width: 34rpx;height: 34rpx;margin-right: 16rpx;"
|
||||
|
|
@ -291,13 +305,14 @@
|
|||
<view class="btn">运费谁承担</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-template">
|
||||
|
||||
</view>
|
||||
<view class="bottom-template">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="bottom-box flex-justify-between flex-align-center">
|
||||
|
||||
<view v-if="order" class="bottom-box flex-justify-between flex-align-center">
|
||||
<view class="left-icons flex">
|
||||
<view class="icon-box" v-for="icon in bottomBtnList[order.statusType].icons" :key="icon.name">
|
||||
<image style="width: 40rpx;height: 40rpx;"
|
||||
|
|
@ -338,6 +353,22 @@ import { onLoad, onShow } from '@dcloudio/uni-app';
|
|||
import { util } from '@/utils/common.js';
|
||||
import { shoppingType, defualtData } from '../json/order.json'
|
||||
|
||||
//导航栏菜单按钮
|
||||
const buttonGroup = [
|
||||
{
|
||||
name: "编辑订单",
|
||||
click: () => {
|
||||
if (order.value && order.value.id) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/shopping/taobao/add-shopping-order/add-shopping-order?id=${order.value.id}&isEdit=true`
|
||||
});
|
||||
} else {
|
||||
uni.showToast({ title: '订单数据未加载', icon: 'none' });
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
const screenshotImage = ref('')
|
||||
const titleList = {
|
||||
"wait_pay": "待付款",
|
||||
"wait_send": "待发货",
|
||||
|
|
@ -533,9 +564,9 @@ const bottomBtnList = {
|
|||
}
|
||||
}
|
||||
|
||||
const isFoldProductCard = ref(true)
|
||||
const isFoldOrderInfoCard = ref(true)
|
||||
const isFoldRefundOrderInfoCard = ref(true)
|
||||
const isFoldProductCard = ref(false)
|
||||
const isFoldOrderInfoCard = ref(false)
|
||||
const isFoldRefundOrderInfoCard = ref(false)
|
||||
|
||||
|
||||
const getGoodsTotalPrice = (list) => {
|
||||
|
|
@ -543,7 +574,6 @@ const getGoodsTotalPrice = (list) => {
|
|||
for (const key in list) {
|
||||
totalPrice = totalPrice + Number(list[key].oriPrice ? list[key].oriPrice : list[key].price) * Number(list[key].count || 1)
|
||||
}
|
||||
console.log("11111111111", totalPrice)
|
||||
return totalPrice.toFixed(2)
|
||||
}
|
||||
|
||||
|
|
@ -554,18 +584,105 @@ const getGoodsTotalCount = (list) => {
|
|||
}
|
||||
return totalCount
|
||||
}
|
||||
let order = ref('')
|
||||
let order = ref(null)
|
||||
|
||||
const currentId = ref(null);
|
||||
let countdownTimer = null;
|
||||
|
||||
const loadOrderDetail = () => {
|
||||
if (!currentId.value) return;
|
||||
// 1. 优先从持久化缓存读取 (用户新增或修改的数据)
|
||||
const storageList = uni.getStorageSync('taobaoShopping') || [];
|
||||
const target = storageList.find(item => String(item.id) === String(currentId.value));
|
||||
|
||||
if (target) {
|
||||
order.value = JSON.parse(JSON.stringify(target));
|
||||
console.log('从缓存加载订单详情成功');
|
||||
// 如果是等待付款状态,启动倒计时
|
||||
if (order.value.statusType === 'wait_pay' && order.value.payCountdown) {
|
||||
initCountdown();
|
||||
}
|
||||
} else {
|
||||
// 2. 兜底从默认 JSON 读取
|
||||
const defaultTarget = defualtData.find((item) => String(item.id) === String(currentId.value));
|
||||
if (defaultTarget) {
|
||||
order.value = JSON.parse(JSON.stringify(defaultTarget));
|
||||
console.log('从默认数据加载订单详情');
|
||||
// 默认数据也需要启动倒计时
|
||||
if (order.value.statusType === 'wait_pay' && order.value.payCountdown) {
|
||||
initCountdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化并启动倒计时
|
||||
*/
|
||||
const initCountdown = () => {
|
||||
if (countdownTimer) clearInterval(countdownTimer);
|
||||
|
||||
// 解析时间字符串 "HH : mm : ss" 或 "HH:mm:ss" 为秒数
|
||||
const parseTimeToSeconds = (timeStr) => {
|
||||
if (!timeStr) return 0;
|
||||
// 统一格式,移除空格并将冒号分隔
|
||||
const parts = timeStr.replace(/\s/g, '').split(':');
|
||||
let seconds = 0;
|
||||
if (parts.length === 3) {
|
||||
seconds = parseInt(parts[0]) * 3600 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
|
||||
} else if (parts.length === 2) {
|
||||
seconds = parseInt(parts[0]) * 60 + parseInt(parts[1]);
|
||||
}
|
||||
return isNaN(seconds) ? 0 : seconds;
|
||||
};
|
||||
|
||||
// 将秒数格式化为 "HH : mm : ss"
|
||||
const formatSecondsToTime = (totalSeconds) => {
|
||||
if (totalSeconds <= 0) return "00:00:00";
|
||||
const h = Math.floor(totalSeconds / 3600);
|
||||
const m = Math.floor((totalSeconds % 3600) / 60);
|
||||
const s = totalSeconds % 60;
|
||||
const pad = (n) => String(n).padStart(2, '0');
|
||||
return `${pad(h)}:${pad(m)}:${pad(s)}`;
|
||||
};
|
||||
|
||||
let remainingSeconds = parseTimeToSeconds(order.value.payCountdown);
|
||||
|
||||
if (remainingSeconds <= 0) return;
|
||||
|
||||
countdownTimer = setInterval(() => {
|
||||
remainingSeconds--;
|
||||
if (remainingSeconds <= 0) {
|
||||
order.value.payCountdown = "00 : 00 : 00";
|
||||
clearInterval(countdownTimer);
|
||||
// 可选:倒计时结束时改变状态为“已取消”
|
||||
// order.value.status = '已取消';
|
||||
} else {
|
||||
order.value.payCountdown = formatSecondsToTime(remainingSeconds);
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
console.log('shoppingType', shoppingType)
|
||||
if (options?.id) {
|
||||
order.value = defualtData.find((item) => item.id == options.id)
|
||||
currentId.value = options.id;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
loadOrderDetail();
|
||||
// 加载拼图截图缓存
|
||||
const savedScreenshot = uni.getStorageSync('taobao_screenshot');
|
||||
if (savedScreenshot) {
|
||||
screenshotImage.value = savedScreenshot;
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (countdownTimer) {
|
||||
clearInterval(countdownTimer);
|
||||
countdownTimer = null;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
@ -1136,6 +1253,7 @@ onShow(() => {
|
|||
|
||||
.help-box {
|
||||
padding: 30rpx 32rpx;
|
||||
margin-bottom: 120rpx;
|
||||
|
||||
.card-title-box {
|
||||
width: 100%;
|
||||
|
|
@ -1201,6 +1319,29 @@ onShow(() => {
|
|||
::v-deep .uni-navbar__header-btns {
|
||||
width: 24px !important;
|
||||
}
|
||||
|
||||
.product-img-card {
|
||||
margin: 16rpx 0;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
padding: 28rpx 32rpx;
|
||||
line-height: 30rpx;
|
||||
|
||||
.label {
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 26rpx;
|
||||
color: #EF7518;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 309 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 932 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 181 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 6.5 KiB |