Files
vpUni/.svn/pristine/39/394fbed4ef08939a43bb105fc58cbaee9695f4c2.svn-base
2026-03-09 16:39:03 +08:00

464 lines
9.2 KiB
Plaintext

<template>
<view class="order-confirm-page">
<!-- 全新方案:纯 CSS 手动构建的骨架屏 -->
<view v-if="loading" class="skeleton-wrapper">
<view class="skeleton-card" style="height: 180rpx;"></view>
<view class="skeleton-card" style="height: 220rpx;"></view>
<view class="skeleton-card" style="height: 150rpx;"></view>
<view class="skeleton-card" style="height: 200rpx;"></view>
</view>
<!-- 页面实际内容 -->
<view v-else class="page-content">
<scroll-view class="page-scroll" scroll-y>
<view class="page-container">
<!-- 1. 收货地址 -->
<view class="card address-card" @click="selectAddress">
<view v-if="orderInfo.address==''" class="no-address">
<up-icon name="plus" color="#fa6400" size="20"></up-icon>
<text>请选择收货地址</text>
</view>
<view v-else class="has-address">
<view class="user-info">
<text class="name">{{ getAddInfo().name}}</text>
<text class="phone">{{ getAddInfo().phone }}</text>
</view>
<text class="address-text">{{ getAddInfo().province}}{{ getAddInfo().city}}{{ getAddInfo().region}}{{ getAddInfo().address}}</text>
</view>
<up-icon name="arrow-right" color="#999" size="16"></up-icon>
</view>
<!-- 2. 商品信息 -->
<view class="card product-card">
<view class="image-placeholder product-image">
<image :src="orderInfo.img" style="width: 100%; height: 100%; border-radius: 10rpx;" mode=""></image>
</view>
<view class="product-info">
<text class="name">{{ orderInfo.goodsName }}</text>
<text class="quantity" style="margin-top: 10rpx;">数量: x{{ orderInfo.count }}</text>
</view>
</view>
<!-- 3. 配送与备注 -->
<!-- <view class="card options-card" style="padding: 20rpx 0;">
<view class="" style="width: 100%; border: solid 1rpx black; height: 40rpx;">
</view>
</view> -->
<!-- 4. 费用明细 -->
<view class="card price-card">
<view class="price-row">
<text class="label">商品总计</text>
<text class="value">{{ orderInfo.amount }} 积分</text>
</view>
</view>
</view>
</scroll-view>
<!-- 底部操作栏 -->
<view class="bottom-bar">
<view class="total-summary">
<text class="total-points">{{ orderInfo.amount }} 积分</text>
</view>
<button class="submit-btn" @click="submitOrder">提交订单</button>
</view>
</view>
<u-popup :show="show" @close="show = false" closeable>
<view class="" style="width: 100%; height: 800rpx;">
<view class=""
style="width: 100; text-align: center; font-size: 28rpx; flex-wrap: 600; height: 80rpx; line-height: 80rpx;">
</view>
<view class="" style="width: 90%; margin: 0 auto; margin-top: 20rpx;">
<view style="width:100%; padding: 5rpx; border: solid 1rpx #e7e7e7; border-radius: 10rpx; margin-bottom: 20rpx; padding: 20rpx;"
v-for="(item, index) in addList" :key="index" :style="addressID==item.addressId?'border: solid 1rpx var(--nav-mian);':''" @click="GxorderAdd(item.addressId)">
<view class="has-address">
<view class="user-info">
<text class="name">{{item.name}}</text>
<text class="phone">{{ item.phone }}</text>
</view>
<text class="address-text">{{ item.province}}{{ item.city}}{{ item.region}}{{ item.address}}</text>
</view>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { Service } from "@/Service/Service";
import { vpGoodsService } from '@/Service/vp/vpGoodsService'
import { vpAddressService } from '@/Service/vp/vpAddressService'
const loading = ref<boolean>(true);
let orderId = ref<string>('')
let orderInfo = ref<any>({
goodsName: '',
img: '',
count: 1,
amount: 0,
address: '',
way: '',
wayName: ''
})
let addList = ref<Array<any>>([])
let addressID = ref<string>('')
let show = ref<boolean>(false)
onLoad((options) => {
orderId.value = options.orderId
GetData()
});
onShow(() => {
getAddList()
});
// 获取收货地址
const getAddList = () => {
vpAddressService.GetUserAddressList().then(res => {
if (res.code == 0) {
addList.value = res.data.list
if(orderInfo.value.address== '' && addList.value.length>0){
GxorderAdd(addList.value[0].addressId)
}
} else {
Service.Msg(res.msg)
}
})
}
// 获取数据
const GetData = () => {
vpGoodsService.GetOrderInfo(orderId.value).then(res => {
if (res.code == 0) {
loading.value = false;
orderInfo.value = res.data.orderInfo
if(orderInfo.value.address != ''){
addressID.value = JSON.parse(orderInfo.value.address).addressId
}
getAddList()
} else {
Service.Msg(res.msg)
}
})
}
// 选择收货地址
const selectAddress = () => {
if(orderInfo.value.address==''){
Service.GoPage('/pages/userFunc/addAddress')
}else{
show.value = true
}
};
// 修改收货地址
const GxorderAdd = (addId:string) =>{
addressID.value = addId
vpGoodsService.UpdateOrderAddress(orderId.value,addId).then(res=>{
if(res.code==0){
orderInfo.value.address = JSON.stringify(addList.value.find(data => data.addressId == addressID.value))
}else{
Service.Msg(res.msg)
}
})
}
const getAddInfo = () =>{
let obj = {
address:'',
province:'',
city:'',
region:'',
name:'',
phone:'',
addressId:''
}
if(orderInfo.value.address != ''){
return JSON.parse(orderInfo.value.address)
}else if(addressID.value!=''){
obj = addList.value.find(data => data.addressId == addressID.value)
return obj
}else{
return obj
}
}
const submitOrder = () => {
vpGoodsService.PayOrder(orderId.value).then(res=>{
if(res.code==0){
Service.Msg('下单成功!')
}else{
Service.Msg(res.msg)
}
})
};
</script>
<style lang="scss" scoped>
@keyframes skeleton-blink {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
.skeleton-item {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-blink 1.5s infinite linear;
}
.skeleton-rect {
border-radius: 12rpx;
}
.skeleton-text {
border-radius: 4rpx;
}
.skeleton-wrapper {
padding: 24rpx;
background-color: #f7f7f7;
.skeleton-card {
background-color: #fff;
padding: 30rpx;
border-radius: 16rpx;
margin-bottom: 24rpx;
}
}
.order-confirm-page {
background-color: #f7f7f7;
height: 100vh;
display: flex;
flex-direction: column;
}
.page-scroll {
flex: 1;
padding-bottom: 140rpx;
}
.page-container {
padding: 24rpx;
}
.card {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 24rpx;
box-shadow: 0 8rpx 30rpx rgba(220, 220, 230, 0.3);
}
.address-card {
display: flex;
align-items: center;
gap: 20rpx;
position: relative;
&::before {
top: 0;
}
&::after {
bottom: 0;
}
.no-address {
flex: 1;
display: flex;
align-items: center;
gap: 16rpx;
font-size: 30rpx;
}
.has-address {
flex: 1;
.user-info {
display: flex;
gap: 24rpx;
.name {
font-size: 32rpx;
font-weight: bold;
}
.phone {
font-size: 28rpx;
color: #666;
}
}
.address-text {
font-size: 26rpx;
color: #333;
margin-top: 12rpx;
line-height: 1.5;
}
}
}
.product-card {
display: flex;
gap: 24rpx;
.product-image {
width: 160rpx;
height: 160rpx;
border-radius: 12rpx;
flex-shrink: 0;
}
.product-info {
display: flex;
flex-direction: column;
.name {
font-size: 28rpx;
color: #333;
font-weight: 500;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.spec,
.quantity {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
}
}
.options-card,
.price-card {
padding: 10rpx 30rpx;
:deep(.up-cell) {
.up-cell__body {
padding: 28rpx 0;
}
.up-cell__title-text {
font-size: 28rpx;
}
}
}
.price-card {
.price-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
font-size: 28rpx;
.label {
color: #666;
}
.value {
color: #333;
font-weight: 500;
}
}
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
padding: 20rpx 30rpx;
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
z-index: 100;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
.total-summary {
display: flex;
align-items: baseline;
gap: 8rpx;
.total-points {
font-size: 36rpx;
font-weight: bold;
color: #fa6400;
}
.total-price {
font-size: 28rpx;
color: #333;
}
}
.submit-btn {
background-color: #fa6400;
color: #fff;
font-weight: bold;
border-radius: 44rpx;
height: 88rpx;
line-height: 88rpx;
font-size: 30rpx;
margin: 0;
padding: 0 80rpx;
&::after {
border: none;
}
}
}
</style>