完成pdd购物模块

This commit is contained in:
tangxinyue 2026-05-29 18:32:20 +08:00
parent 8eca8cc6ce
commit 43efe376ec
25 changed files with 3467 additions and 242 deletions

View File

@ -21,7 +21,7 @@
<view class="title-box flex-between">
<text class="title">{{ displayTitle(item.title) }}</text>
<text class="time">{{ formatDate(getLastMessage(item.chatList)?.time || item.time)
}}</text>
}}</text>
</view>
<view class="content">
<view v-if="isImageMsg(getLastMessage(item.chatList))"
@ -471,11 +471,15 @@ const editItem = (item) => {
}
.dot {
width: 28rpx;
height: 28rpx;
position: absolute;
padding: 4rpx 10rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #E93A22;
color: #FFFFFF;
line-height: 20rpx;
line-height: 18rpx;
font-size: 20rpx;
border-radius: 16rpx;
right: -8rpx;

View File

@ -29,7 +29,7 @@ export function createApp() {
app.config.globalProperties.$system = plus.os.name;
// #endif
app.config.globalProperties.$systemInfo = systemInfo
uni.setStorageSync('version', '1.0.5.sp13')
uni.setStorageSync('version', '1.0.5.sp15')
app.config.globalProperties.$version = uni.getStorageSync('version')
app.use(globalMethods);
return {

View File

@ -17,7 +17,7 @@
"navigationBarTitleText": "通话记录页面",
"navigationStyle": "custom"
}
},{
}, {
"path": "detail/callDetail",
"style": {
"navigationBarTitleText": "通话记录详情",
@ -138,6 +138,13 @@
"navigationBarTitleText": "拼多多订单详情",
"navigationStyle": "custom"
}
},
{
"path": "pdd/add-order/add-order",
"style": {
"navigationBarTitleText": "pdd添加修改订单信息",
"navigationStyle": "custom"
}
}
]
},

View File

@ -64,8 +64,7 @@ const menuList = ref([{
bgColor: ["#FFE0DF", "#FFFFFF"],
btnBg: "#FF4848",
shadowColor: "#FF4848",
// url: "/pages/shopping/pdd/list-index"
url: ""
url: "/pages/shopping/pdd/list-index"
}, {
name: "快手",
icon: "kuaishou",

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,18 @@
<template>
<view class="list-card-container" v-if="item">
<view class="list-card-container" v-if="item" @click="toDetail(item.id)" @longpress="onLongPress">
<!-- 头部店铺信息和状态 -->
<view class="header-box flex-between flex-align-center">
<view class="shop-info flex-align-center">
<view class="shop-logo-placeholder flex-center" v-if="item.isBrand"><text class="logo-text">正品</text>
<view class="shop-logo-placeholder flex-center" v-if="item.shop.logo">
<image class="brand-img" :src="item.shop.logo">
</image>
</view>
<text class="shop-name">{{ item.shopName }}</text>
<!-- <view class="tag-brand" v-if="item.isBrand">品牌认证</view> -->
<image v-if="item.isBrand" class="brand-img" src="/static/image/shopping/pdd/pinpairenzheng.png">
<text class="shop-name">{{ item.shop?.name }}</text>
<image v-if="item.shop?.hasBrandAuth" class="brand-img"
src="/static/image/shopping/pdd/pinpairenzheng.png">
</image>
<image class="flag-img" v-if="item.shop?.hasFlagship" src="/static/image/shopping/pdd/qijiandian.png">
</image>
<image class="flag-img" v-if="item.isFlagship" src="/static/image/shopping/pdd/qijiandian.png"></image>
<uni-icons style="margin-top: 4rpx;" type="right" color="#999999" size="12"></uni-icons>
</view>
<view class="status-text" v-if="item.orderType === 'wait_pay'">待支付</view>
@ -18,26 +21,26 @@
</view>
<!-- 商品主要内容 -->
<view class="product-box flex">
<view class="product-box flex" v-for="(product, pIndex) in item.products" :key="pIndex">
<view class="product-img-box">
<image class="product-img" :src="item.productImg" mode="aspectFill"></image>
<image class="product-img" :src="product.img" mode="aspectFill"></image>
</view>
<view class="product-content flex-1">
<view class="title-box">
<view class="brand-tag flex-center">品牌</view>
<text class="title-text">{{ item.productTitle }}</text>
<view class="brand-tag flex-center" v-if="item.shop?.hasBrandAuth">品牌</view>
<text class="title-text">{{ product.title }}</text>
</view>
<view class="spec-text text-ellipsis">{{ item.productSpec }}</view>
<view class="spec-text text-ellipsis">{{ product.spec }}</view>
<view class="tags-box flex-align-center">
<view class="green-tag" v-for="(tag, index) in item.tags" :key="index">{{ tag }}</view>
<view class="green-tag" v-for="(tag, index) in product.serviceTags" :key="index">{{ tag }}</view>
</view>
</view>
<view class="price-box flex-column align-end">
<text class="price">¥
<text style="font-size: 30rpx;">{{ Number(item.price).toFixed(1).split('.')[0] + '.' }}</text>
<text style="font-size: 22rpx;">{{ Number(item.price).toFixed(1).split('.')[1] }}</text>
<text style="font-size: 30rpx;">{{ Number(product.price).toFixed(1).split('.')[0] + '.' }}</text>
<text style="font-size: 22rpx;">{{ Number(product.price).toFixed(1).split('.')[1] }}</text>
</text>
<text class="count">x{{ item.quantity }}</text>
<text class="count">x{{ product.count }}</text>
</view>
</view>
@ -52,8 +55,8 @@
<view class="total-price flex-align-center">
<text class="label">{{ item.orderType === 'wait_pay' ? '应付' : '实付' }}:</text>
<text class="symbol">¥</text>
<text class="amount">{{ item.totalAmount }}</text>
<text class="freight">({{ item.freightText }})</text>
<text class="amount">{{ item.payment.totalAmount }}</text>
<text class="freight">{{ item.payment.freightDesc }}</text>
</view>
</view>
@ -84,18 +87,18 @@
</view>
<!-- 物流状态栏 -->
<view class="delivery-box flex-align-center" v-if="item.deliveryStatus">
<view class="delivery-box flex-align-center" v-if="item.deliveryStatus && item.orderType !== 'received'">
<view class="truck-icon flex-center">
<image style="width:32rpx;height: 32rpx;" src="/static/image/shopping/pdd/yunshuzhong.png"></image>
</view>
<view class="delivery-content text-ellipsis flex-1">
<template v-if="item.orderType === 'wait_pay'">
<text class="green-text">{{ item.deliveryStatus }}</text>
<text class="green-text">{{ item.deliveryDetail }}</text>
<text class="green-text">{{ item.statusDesc }}</text>
</template>
<template v-if="item.orderType === 'wait_recv'">
<text class="green-text">{{ item.deliveryStatus }}</text>
<text class="gray-text">{{ item.deliveryDetail }}</text>
<text class="gray-text">{{ item.logistics.desc }}</text>
</template>
</view>
</view>
@ -105,7 +108,7 @@
</template>
<script setup>
import { defineProps } from 'vue';
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
item: {
@ -113,6 +116,18 @@ const props = defineProps({
default: () => ({})
}
});
const emit = defineEmits(['longpress']);
const onLongPress = (e) => {
emit('longpress', e);
};
const toDetail = (id) => {
uni.navigateTo({
url: `/pages/shopping/pdd/order-detail/order-detail?id=${id}`
});
};
</script>
<style lang="less" scoped>
@ -170,17 +185,12 @@ const props = defineProps({
margin-bottom: 24rpx;
.shop-logo-placeholder {
width: 44rpx;
height: 24rpx;
background-color: #E01B13;
border-radius: 20rpx;
margin-right: 8rpx;
.logo-text {
color: #fff;
font-size: 16rpx;
transform: scale(0.8);
}
flex-shrink: 0;
width: 40rpx;
height: 40rpx;
border-radius: 4rpx;
margin-right: 6rpx;
overflow: hidden;
}
.shop-name {

View File

@ -0,0 +1,632 @@
{
// "购物订单分类字段"
"shoppingClassfiy": {
"wait_pay": {
// type: 1,
"id": 1,
"orderType": "wait_pay",
"waitPayTime": "23:59:27",
"shop": {
"name": "",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "",
"title": "",
"price": 0,
"count": 0,
"spec": "",
"serviceTags": []
}
],
"avatars": [],
"activePayIndex": 2,
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": "",
"discountText": "已优惠10元",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 0,
"deliveryStatus": "",
"statusDesc": "预计后天送达",
"logistics": {
"desc": "",
"time": ""
},
"orderInfo": [
{
"label": "订单编号:",
"value": "",
"hasCopy": true
},
{
"label": "下单时间:",
"value": ""
}
]
},
"wait_recv": {
// type: 2,
"id": 2,
"orderType": "wait_recv",
"shop": {
"name": "",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "",
"title": "",
"price": 0,
"count": 0,
"spec": "",
"serviceTags": []
}
],
"avatars": [],
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": "",
"discountText": "",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 0,
"deliveryStatus": "运输中 预计明天送达",
"statusDesc": "商家已早于承诺时间发货",
"logistics": {
"desc": "申通快递:【南京市】快件已发往 上海市浦东新区",
"time": "今天 06:25:21"
},
"orderInfo": [
{
"label": "订单编号:",
"value": "260403-03369586325654",
"hasCopy": true
},
{
"label": "商品快照:",
"value": "发生交易争议时,可作为判断依据",
"hasArrow": true
},
{
"label": "支付方式:",
"value": "支付宝"
},
{
"label": "物流公司:",
"value": "申通快递"
},
{
"label": "快递单号:",
"value": "777445412223333326"
},
{
"label": "下单时间:",
"value": "2026-03-31 08:55:30"
},
{
"label": "拼单时间:",
"value": "2026-03-31 08:55:30",
"hasAvatars": true,
"hasArrow": true
},
{
"label": "发货时间:",
"value": "2026-03-31 11:11:52"
}
]
},
"received": {
// type: 3,
"id": 3,
"orderType": "received",
"shop": {
"name": "",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "",
"title": "",
"price": 0,
"count": 0,
"spec": "",
"serviceTags": []
}
],
"avatars": [],
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": "",
"discountText": "",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 558,
"deliveryStatus": "",
"statusDesc": "商家已早于承诺时间发货",
"logistics": {
"desc": "申通快递:【上海市】订单已签收 上海市浦东新区汤臣一品",
"time": "今天 10:25:21"
},
"orderInfo": [
{
"label": "订单编号:",
"value": "260403-03369586325654",
"hasCopy": true
},
{
"label": "商品快照:",
"value": "发生交易争议时,可作为判断依据",
"hasArrow": true
},
{
"label": "支付方式:",
"value": "支付宝"
},
{
"label": "物流公司:",
"value": "申通快递"
},
{
"label": "快递单号:",
"value": "77735698745526"
},
{
"label": "下单时间:",
"value": "2026-03-31 08:55:30"
},
{
"label": "拼单时间:",
"value": "2026-03-31 08:55:30",
"hasAvatars": true,
"hasArrow": true
},
{
"label": "发货时间:",
"value": "2026-03-31 11:11:52"
}
]
}
},
// "购物类型"
"shoppingType": [
{
"label": "等待付款",
"key": "wait_pay"
},
{
"label": "待收货",
"key": "wait_recv"
},
{
"label": "完成-已签收",
"key": "received"
}
],
// "购物随机产品列表"
"shoppingProductList": [
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "多多数码旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/xianka.png",
"name": "",
"title": "华硕 TUF 5090显卡",
"spec": "5090旗舰算力 水冷夜神OC",
"serviceTags": [
"不支持7天无理由退货"
],
"price": "39849.00",
"count": "1"
}
]
},
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "Apple 产品旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/iphone.png",
"name": "Apple iPhone 17 Pro",
"title": "Apple/苹果 iPhone 17 Pro Max 1TB 星宇橙色",
"spec": "星宇橙色全网通5G",
"serviceTags": [
"免费上门退换",
"七天无理由退货"
],
"price": "12999.00",
"count": "1"
}
]
},
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "路易威登官方旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/lv.png",
"name": "LV",
"title": "路易威登 经典老花手提包",
"spec": "经典老花;手提包",
"serviceTags": [
"次日达",
"七天无理由退货"
],
"price": "23979.25",
"count": "1"
}
]
},
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "索尼SONY数码官方旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/sony.png",
"name": "Sony",
"title": "索尼SONYAlpha 7 IV 全画幅微单数码相机",
"spec": "单机身不含镜头约3300万有效像素",
"serviceTags": [
"厂家发货",
"七天无理由退货"
],
"price": "15499.00",
"count": "1"
}
]
},
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "五粮液自营店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/wuliangye.png",
"name": "五粮液",
"title": "五粮液 普五 第八代 浓香型白酒 52度 500ml*2瓶",
"spec": "500ml*2礼盒装浓香型",
"serviceTags": [
"七天无理由退货",
"假一赔十"
],
"price": "1099.00",
"count": "2"
}
]
},
{
"payment": {
"totalAmount": "35.9",
"discountText": "立省 6.59",
"freightDesc": "(免运费)"
},
"shop": {
"name": "戴森Dyson官方旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/dyson_v12.png",
"name": "戴森",
"title": "戴森(Dyson) V12 Detect Slim 无绳吸尘器",
"spec": "轻量版;激光探测;轻量吸尘器",
"serviceTags": [
"厂家发货",
"七天无理由退货"
],
"price": "3299.00",
"count": "1"
}
]
}
],
//
"defaultDataList": [
{
"id": "1780046536767",
"orderType": "received",
"shop": {
"name": "五粮液自营店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/wuliangye.png",
"title": "五粮液 普五 第八代 浓香型白酒 52度 500ml*2瓶",
"price": "1099.00",
"count": "2",
"spec": "500ml*2礼盒装浓香型",
"serviceTags": [
"七天无理由退货",
"假一赔十"
],
"name": "五粮液"
}
],
"avatars": [],
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": 2198,
"discountText": "已优惠10元",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 558,
"deliveryStatus": "",
"statusDesc": "商家已早于承诺时间发货",
"logistics": {
"desc": "申通快递:【上海市】订单已签收 上海市浦东新区汤臣一品",
"time": "昨天 18:35:17"
},
"orderInfo": [
{
"label": "订单编号:",
"value": "265333-63850934463838",
"hasCopy": true
},
{
"label": "商品快照:",
"value": "发生交易争议时,可作为判断依据",
"hasArrow": true
},
{
"label": "支付方式:",
"value": "支付宝"
},
{
"label": "物流公司:",
"value": "申通快递"
},
{
"label": "快递单号:",
"value": "7726047284494359"
},
{
"label": "下单时间:",
"value": "2026-05-29 01:56:29"
},
{
"label": "拼单时间:",
"value": "2026-05-29 01:57:19",
"hasAvatars": true,
"hasArrow": true,
"avatars": []
},
{
"label": "发货时间:",
"value": "2026-05-29 20:57:19"
}
],
"waitPayTime": "22:55:05",
"activePayIndex": 2
},
{
"id": "1780046527800",
"orderType": "wait_recv",
"shop": {
"name": "索尼SONY数码官方旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/sony.png",
"title": "索尼SONYAlpha 7 IV 全画幅微单数码相机",
"price": "15499.00",
"count": "1",
"spec": "单机身不含镜头约3300万有效像素",
"serviceTags": [
"厂家发货",
"七天无理由退货"
],
"name": "Sony"
}
],
"avatars": [],
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": 15499,
"discountText": "已优惠10元",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 0,
"deliveryStatus": "运输中 预计明天送达",
"statusDesc": "商家已早于承诺时间发货",
"logistics": {
"desc": "顺丰快递:【南京市】快件已发往 上海市浦东新区",
"time": "今天 06:25:21"
},
"orderInfo": [
{
"label": "订单编号:",
"value": "262022-17081287841024",
"hasCopy": true
},
{
"label": "商品快照:",
"value": "发生交易争议时,可作为判断依据",
"hasArrow": true
},
{
"label": "支付方式:",
"value": "支付宝"
},
{
"label": "物流公司:",
"value": "申通快递"
},
{
"label": "快递单号:",
"value": "777445412223333326"
},
{
"label": "下单时间:",
"value": "2026-05-28 17:05:56"
},
{
"label": "拼单时间:",
"value": "2026-03-31 08:55:30",
"hasAvatars": true,
"hasArrow": true,
"avatars": []
},
{
"label": "发货时间:",
"value": "2026-03-31 11:11:52"
}
],
"waitPayTime": "01:45:17",
"activePayIndex": 2
},
{
"id": "1780046506911",
"orderType": "wait_pay",
"waitPayTime": "23:49:16",
"shop": {
"name": "Apple 产品旗舰店",
"logo": "",
"hasBrandAuth": true,
"hasFlagship": true
},
"products": [
{
"img": "/static/image/shopping/jingdong/product/shopping/iphone.png",
"title": "Apple/苹果 iPhone 17 Pro Max 1TB 星宇橙色",
"price": "12999.00",
"count": "1",
"spec": "星宇橙色全网通5G",
"serviceTags": [
"免费上门退换",
"七天无理由退货"
],
"name": "Apple iPhone 17 Pro"
}
],
"avatars": [],
"activePayIndex": 2,
"address": {
"name": "张三",
"phone": "13888888888",
"province": "上海市浦东新区汤臣一品1号楼",
"detail": ""
},
"payment": {
"totalAmount": 12999,
"discountText": "已优惠10元",
"freightDesc": "(免运费)"
},
"totalAmount": 0,
"freightText": "",
"collectCount": 0,
"deliveryStatus": "",
"statusDesc": "预计后天送达",
"logistics": {
"desc": "",
"time": "今天 16:14:06"
},
"orderInfo": [
{
"label": "订单编号:",
"value": "267726-97143795493977",
"hasCopy": true
},
{
"label": "下单时间:",
"value": "2026-05-29 05:52:46"
}
]
}
]
}

View File

@ -1,9 +1,12 @@
<template>
<view class="page-container flex-column">
<view class="nav-bar">
<nav-bar>
<nav-bar v-if="!selectedImage" :buttonGroup="buttonGroup" @button-click="util.clickTitlePopupButton"
tipLayerType="pdd-shopping-list" isTipLayer tipLayerText="添加订单信息">
<template v-slot:left>
<image style="width: 48rpx;height: 48rpx;" src="/static/image/shopping/pdd/back.png"></image>
<image style="width: 48rpx;height: 48rpx;" src="/static/image/shopping/pdd/back.png"
@click="util.goBack()">
</image>
</template>
<template v-slot:center>
<view class="title-box flex-center flex-column">
@ -19,134 +22,498 @@
<image style="width: 48rpx;height: 48rpx;" src="/static/image/shopping/pdd/search.png"></image>
</template>
</nav-bar>
<nav-bar v-else title="拼图" bgColor="#EFEFEF" noBack @back="closeImage" isRightButton
@right-click="confirmImage">
</nav-bar>
</view>
<view class="tab-list flex-align-center">
<view class="tab-item" :class="{ active: tab.id == activeTab }" v-for="(tab, index) in tabList"
:key="index">
<view class="tab-item" :class="{ active: tab.id == activeTab }" v-for="(tab, index) in tabList" :key="index"
@click="activeTab = tab.id">
<text>{{ tab.name }}</text>
</view>
</view>
<scroll-view class="flex-1" style="height: 100px;" scroll-y="true">
<list-card v-for="(item, index) in orderList" :key="index" :item="item"></list-card>
<view v-if="orderList.length == 0" class="null-data-box flex-align-center">
<scroll-view v-if="activeTab === 4" class="tab2-box" scroll-x="true" :show-scrollbar="false">
<view class="tab2-content flex-align-center">
<view class="tab2-item flex-center" :class="{ active: activeTab2 === item.id }"
v-for="(item, index) in displayTab2List" :key="index" @click="handleTab2Click(item)">
<text>{{ item.name }} {{ item.count }}</text>
</view>
</view>
</scroll-view>
<scroll-view class="flex-1" style="height: 100px;" scroll-y="true" :scroll-into-view="scrollIntoId"
scroll-with-animation>
<list-card v-for="(item, index) in filteredOrderList" :key="index" :item="item"
@longpress="handleLongPress($event, item)"></list-card>
<view v-if="filteredOrderList.length == 0" class="null-data-box flex-align-center">
<text>没找到订单试试</text>
<text style="color: #2686E4;">查看全部</text>
<text></text>
<text style="color: #2686E4;">切换账号</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 id="bottom-anchor" style="height: 1px;"></view>
</view>
</scroll-view>
<!-- 上下文菜单和遮罩 -->
<view class="menu-mask" v-if="showMenu" @click="showMenu = false"></view>
<view class="context-menu flex-column" v-if="showMenu" :style="{ left: menuX + 'px', top: menuY + 'px' }">
<view class="menu-item" @click="handleEdit">编辑</view>
<view class="menu-item text-red" @click="handleDelete">删除</view>
</view>
<!-- 水印 -->
<view v-if="$isVip()">
<watermark dark="light" source="uni_alipay_shopping_pdd" />
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_shopping_pdd')">
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
</liu-drag-button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { ref, computed, getCurrentInstance } from 'vue';
import { onShow, onLoad } from '@dcloudio/uni-app';
import ListCard from './components/list-card/list-card.vue';
import { defaultDataList } from '@/pages/shopping/pdd/json/order.json';
import { util } from '@/utils/common.js';
const { proxy } = getCurrentInstance();
const activeTab = ref(0);
const scrollIntoId = ref('');
//
const buttonGroup = [
{
name: "新增购物订单",
click: () => {
uni.navigateTo({
url: '/pages/shopping/pdd/add-order/add-order'
});
}
}, {
name: "切换推荐商品图片",
click: () => {
scrollIntoId.value = '';
setTimeout(() => {
scrollIntoId.value = 'bottom-anchor';
}, 50);
setTimeout(() => {
chooseImage();
}, 400);
}
},
]
onLoad(() => {
proxy.$apiUserEvent('all', {
type: 'event',
key: 'shopping',
prefix: '.uni.other.',
value: '拼多多'
})
})
const tabList = ref([
{
name: '全部',
id: 0
id: 0,
value: 'all'
},
{
name: '待付款',
id: 1
id: 1,
value: 'wait_pay'
},
{
name: '拼团中',
id: 2
id: 2,
value: 'grouping'
},
{
name: '打包中',
id: 3
id: 3,
value: 'packing'
},
{
name: '待收货',
id: 4
id: 4,
value: 'wait_recv'
},
{
name: '评价',
id: 5
id: 5,
value: 'received'
},
]);
const orderList = ref([
{
// type: 1,
orderType: "wait_pay",
shopName: '澳松旗舰店',
isBrand: true,
isFlagship: true,
productImg: 'https://picsum.photos/200/200?random=1',
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
tags: ['坏了包赔', '7天无理由退货'],
price: '35.9',
quantity: 1,
avatars: [
'https://picsum.photos/40/40?random=1',
'https://picsum.photos/40/40?random=2',
'https://picsum.photos/40/40?random=3',
'https://picsum.photos/40/40?random=4'
],
totalAmount: '35.9',
freightText: '免运费',
deliveryStatus: '现在支付预计6小时内发货',
deliveryDetail: '后天送达'
},
{
// type: 2,
orderType: "wait_recv",
shopName: '澳松旗舰店',
isBrand: true,
isFlagship: true,
productImg: 'https://picsum.photos/200/200?random=2',
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
tags: ['7天无理由退货'],
price: '35.9',
quantity: 1,
avatars: [
'https://picsum.photos/40/40?random=5',
'https://picsum.photos/40/40?random=6',
'https://picsum.photos/40/40?random=7',
'https://picsum.photos/40/40?random=8'
],
totalAmount: '35.9',
freightText: '免运费',
collectCount: 558,
deliveryStatus: '运输中 预计明天送达',
deliveryDetail: '申通快递:【洛阳市】快件已发往 新...'
},
{
// type: 3,
orderType: "received",
shopName: '澳松旗舰店',
isBrand: true,
isFlagship: true,
productImg: 'https://picsum.photos/200/200?random=3',
productTitle: '适配哈哈哈哈哈哈哈哈哈哈哈哈头配哈哈哈哈哈哈哈哈哈哈哈哈很好...',
productSpec: '(小头款)哈哈哈哈哈哈哈哈哈哈哈哈很好...',
tags: ['退货包运费保障中'],
price: '35.9',
quantity: 1,
avatars: [
'https://picsum.photos/40/40?random=9',
'https://picsum.photos/40/40?random=10',
'https://picsum.photos/40/40?random=11',
'https://picsum.photos/40/40?random=12'
],
totalAmount: '35.9',
freightText: '免运费',
collectCount: 558
const activeTab2 = ref(0);
const tab2List = ref([
{ name: '全部', count: 1, id: 0 },
{ name: '已签收', count: 0, id: 1 },
{ name: '待取件', count: 0, id: 2 },
{ name: '派件中', count: 0, id: 3 },
{ name: '运输中', count: 1, id: 4 },
{ name: '其他', count: 0, id: 5 },
]);
const displayTab2List = computed(() => {
let sum = 0;
tab2List.value.forEach(item => {
if (item.id !== 0) {
sum += Number(item.count || 0);
}
});
return tab2List.value.map(item => {
if (item.id === 0) {
return { ...item, count: sum };
}
return item;
});
});
const saveTab2List = () => {
uni.setStorageSync('pdd_tab2List', tab2List.value);
uni.showToast({
title: '修改已保存',
icon: 'success'
});
};
const handleTab2Click = (item) => {
if (item.id !== 0) {
//
uni.showModal({
title: `修改[${item.name}]数量`,
editable: true,
placeholderText: '请输入数量',
success: (res) => {
if (res.confirm && res.content) {
const num = parseInt(res.content);
if (!isNaN(num) && num >= 0) {
const target = tab2List.value.find(t => t.id === item.id);
if (target) {
target.count = num;
saveTab2List();
}
}
}
}
});
} else {
//
activeTab2.value = item.id;
}
]);
};
const orderList = ref([]);
const showMenu = ref(false);
const menuX = ref(0);
const menuY = ref(0);
const currentEditItem = ref(null);
const handleLongPress = (e, item) => {
const touch = e.touches && e.touches[0] ? e.touches[0] : (e.changedTouches && e.changedTouches[0] ? e.changedTouches[0] : e);
menuX.value = touch.clientX || touch.pageX || 100;
menuY.value = touch.clientY || touch.pageY || 100;
currentEditItem.value = item;
showMenu.value = true;
};
const handleEdit = () => {
showMenu.value = false;
if (currentEditItem.value) {
uni.navigateTo({
url: `/pages/shopping/pdd/add-order/add-order?isEdit=true&id=${currentEditItem.value.id}`
});
}
};
const removeLocalFile = (filePath) => {
if (!filePath) return;
if (filePath.startsWith('http') || filePath.startsWith('/static')) return;
uni.removeSavedFile({
filePath,
fail: () => { }
});
};
const handleDelete = () => {
showMenu.value = false;
if (currentEditItem.value) {
uni.showModal({
title: '提示',
content: '确定要删除该订单吗?',
success: (res) => {
if (res.confirm) {
const index = orderList.value.findIndex(item => item.id === currentEditItem.value.id);
if (index > -1) {
const deletedOrder = orderList.value[index];
//
if (deletedOrder.shop && deletedOrder.shop.logo) {
removeLocalFile(deletedOrder.shop.logo);
}
if (deletedOrder.products) {
deletedOrder.products.forEach(p => {
if (p.img) removeLocalFile(p.img);
if (p.image) removeLocalFile(p.image);
});
}
if (deletedOrder.avatars) {
deletedOrder.avatars.forEach(av => removeLocalFile(av));
}
orderList.value.splice(index, 1);
//
uni.setStorageSync('pddOrderList', orderList.value);
uni.showToast({ title: '删除成功', icon: 'success' });
}
}
}
});
}
};
const getOrderTime = (order) => {
if (order.orderInfo) {
const timeInfo = order.orderInfo.find(info => info.label && info.label.includes('下单时间'));
if (timeInfo && timeInfo.value) {
const timestamp = new Date(timeInfo.value.replace(/-/g, '/')).getTime();
if (!isNaN(timestamp)) {
return timestamp;
}
}
}
return Number(order.id) || 0;
};
const filteredOrderList = computed(() => {
const currentTab = tabList.value.find(t => t.id === activeTab.value);
let list = orderList.value;
if (currentTab && currentTab.value !== 'all') {
list = list.filter(item => item.orderType === currentTab.value);
}
return list.slice().sort((a, b) => getOrderTime(b) - getOrderTime(a));
});
onShow(() => {
const isInitialized = uni.getStorageSync('isPddOrderListInitialized');
if (!isInitialized) {
uni.setStorageSync('pddOrderList', defaultDataList);
uni.setStorageSync('isPddOrderListInitialized', true);
orderList.value = defaultDataList;
} else {
const cacheList = uni.getStorageSync('pddOrderList');
orderList.value = cacheList || [];
}
// ()
let savedScreenshot = uni.getStorageSync('pdd_screenshot');
if (!savedScreenshot) {
savedScreenshot = '/static/image/shopping/pdd/pdd-bottom-product.png';
uni.setStorageSync('pdd_screenshot', savedScreenshot);
}
screenshotImage.value = savedScreenshot;
//
const cachedTab2 = uni.getStorageSync('pdd_tab2List');
if (cachedTab2) {
tab2List.value = cachedTab2;
}
});
//
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(proxy)
//
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', proxy)
//
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('pdd_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'
})
}
}, proxy)
})
},
fail: () => {
uni.hideLoading()
uni.showToast({
title: '图片加载失败',
icon: 'none'
})
}
})
})
}
//
const closeImage = () => {
selectedImage.value = '';
};
</script>
@ -196,7 +563,47 @@ const orderList = ref([
&.active {
color: #E01B13;
font-weight: 500;
border-bottom: 4rpx solid #E01B13;
box-shadow: inset 0 -4rpx 0 0 #E01B13;
}
}
}
.tab2-box {
height: 78rpx;
background-color: #ffff;
border-bottom: 0.5px solid #D2D2D2;
width: 100%;
white-space: nowrap;
:deep(.uni-scroll-view::-webkit-scrollbar) {
display: none !important;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
.tab2-content {
display: inline-flex;
padding: 0 24rpx;
height: 100%;
}
.tab2-item {
flex-shrink: 0;
height: 52rpx;
padding: 0 16rpx;
background-color: #F8F8F8;
border-radius: 26rpx;
margin-right: 20rpx;
font-size: 26rpx;
color: #1A1A1A;
white-space: nowrap;
&.active {
background-color: #FCEFEF;
font-weight: 500;
color: #E01B13;
}
}
}
@ -208,6 +615,147 @@ const orderList = ref([
line-height: 28rpx;
padding: 42rpx 0;
}
.menu-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 998;
}
.context-menu {
position: fixed;
z-index: 999;
background-color: #fff;
border-radius: 8rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
width: 200rpx;
overflow: hidden;
.menu-item {
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 28rpx;
color: #333;
border-bottom: 1rpx solid #F5F5F5;
&:last-child {
border-bottom: none;
}
&.text-red {
color: #DF2E26;
}
}
}
.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;
}
}
}
}
</style>
<style>
@import '@/common/main.css';

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB