refactor(me): 重构我的页面代码结构
移除未使用的订单相关页面和组件 优化用户信息展示和余额显示逻辑 调整页面布局和样式
This commit is contained in:
parent
cb445624e6
commit
71993d9a77
|
|
@ -8,7 +8,11 @@
|
|||
"Bash(mkdir -p 'E:\\code\\智柜宝\\wx\\src\\pages\\home\\components')",
|
||||
"Bash(cp 'E:\\code\\智柜宝\\wx\\doc\\thirdParty\\src\\pages\\product\\components\\checkout.vue' 'E:\\code\\智柜宝\\wx\\src\\pages\\index\\components\\checkout.vue')",
|
||||
"Bash(cp 'E:\\code\\智柜宝\\wx\\doc\\thirdParty\\src\\pages\\product\\components\\RentingCabinetContainer.vue' 'E:\\code\\智柜宝\\wx\\src\\pages\\index\\components\\renting-cabinet-container.vue')",
|
||||
"Bash(test -f 'E:\\code\\智柜宝\\wx\\src\\pages\\index\\components\\product-container.vue')"
|
||||
"Bash(test -f 'E:\\code\\智柜宝\\wx\\src\\pages\\index\\components\\product-container.vue')",
|
||||
"Bash(ls -la 'E:\\\\code\\\\智柜宝\\\\wx\\\\src\\\\pages\\\\me')",
|
||||
"Bash(mkdir -p 'E:\\\\code\\\\智柜宝\\\\wx\\\\src\\\\pages\\\\me')",
|
||||
"Bash(ls -la 'E:\\\\code\\\\智柜宝\\\\wx\\\\static')",
|
||||
"Bash(ls -la 'E:\\\\code\\\\智柜宝\\\\wx\\\\src\\\\static')"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
。仅参考语法,api需要使用原ProductList.vue中已经移植到本项目的相应api,stores也需要使用移植后的pinia。生成的代码写到
|
||||
@src\pages\home\ 文件夹下
|
||||
|
||||
参考已迁移至本项目的代码 @src\pages\index\ 。将 @doc\thirdParty\src\pages\product\components\
|
||||
下的另外两个component也迁移到本项目。注意thirdParty下的是H5项目,现在需要改为微信小程序uni-app。api需要使用原Product
|
||||
List.vue中已经移植到本项目的相应api,stores也需要使用移植后的pinia。
|
||||
参考已迁移至本项目的代码 @src\pages\index\ 。将 @doc\thirdParty\src\pages\me\index.vue
|
||||
“我的”页面也迁移到本项目。注意thirdParty下的是H5项目,现在需要改为微信小程序uni-app。api需要使用原Product
|
||||
List.vue中已经移植到本项目的相应api,stores也需要使用移植后的pinia。生成的代码写到 @src\pages\me\ 文件夹下
|
||||
|
|
@ -63,10 +63,7 @@
|
|||
},
|
||||
{
|
||||
"path": "pages/index/checkout",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单结算"
|
||||
}
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "pages/login/faceLogin",
|
||||
|
|
@ -98,13 +95,6 @@
|
|||
"navigationBarTitleText": "我的"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/order/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/QrScanner/index",
|
||||
"type": "page",
|
||||
|
|
@ -112,36 +102,6 @@
|
|||
"navigationBarTitleText": "扫码",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/me/personal-profile/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人资料"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/me/promote-with-courtesy/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "推广有礼",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/order/detail/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单详情",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/order/refund-confirmation/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "退款确认"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": []
|
||||
|
|
|
|||
|
|
@ -1,381 +1,413 @@
|
|||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { ICOBalanceRecharge,ICOMyCoupon,ICOMyRights,ICOMyOrder } from '@/components/icons'
|
||||
import { generateQRCode, getCurrentPagePath } from '@/utils/qrcode'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { useWxStore } from '@/pinia/stores/wx'
|
||||
import { useAb98UserStore } from '@/pinia/stores/ab98-user'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '我的',
|
||||
// navigationStyle: 'custom',
|
||||
},
|
||||
})
|
||||
const userStore = useUserStore();
|
||||
/** 登录用户信息 */
|
||||
const loginUser:any = computed(() => userStore.info ?? {});
|
||||
|
||||
console.log(loginUser.value,'用户信息')
|
||||
const wxStore = useWxStore()
|
||||
const ab98UserStore = useAb98UserStore()
|
||||
|
||||
const itemClick = (url:string) => {
|
||||
uni.navigateTo({
|
||||
url: url,
|
||||
const { balance, useBalance, balanceLimit, name: qyName, ab98User } = storeToRefs(wxStore)
|
||||
const { name: userName, sex: userSex, face_img } = storeToRefs(ab98UserStore)
|
||||
|
||||
const name = computed(() => {
|
||||
return userName.value || qyName.value || '未知用户'
|
||||
})
|
||||
|
||||
const userAvatar = computed(() => face_img.value ? face_img.value : '/static/logo.png')
|
||||
|
||||
const ab98BalanceInYuan = computed(() => {
|
||||
if (ab98User.value && ab98User.value.ab98Balance !== undefined) {
|
||||
return (ab98User.value.ab98Balance / 100).toFixed(2)
|
||||
}
|
||||
return '0.00'
|
||||
})
|
||||
|
||||
const handleLogout = () => {
|
||||
uni.showModal({
|
||||
title: '退出登录',
|
||||
content: '确定要退出当前账号吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
ab98UserStore.clearUserInfo()
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const showQrcode = ref(false)
|
||||
const qrcodeData = ref('')
|
||||
|
||||
// 生成二维码
|
||||
const generateUserQRCode = async () => {
|
||||
console.log('开始生成二维码');
|
||||
// 统一的页面跳转函数
|
||||
const navigateToPage = (pagePath: string, options: { type?: 'navigateTo' | 'switchTab' | 'redirectTo' } = {}) => {
|
||||
const { type = 'navigateTo' } = options
|
||||
|
||||
try {
|
||||
// 生成包含用户ID和页面路径的二维码
|
||||
const qrContent = `${loginUser.value?.idnum || 'guest'}`;
|
||||
console.log('二维码内容:', qrContent);
|
||||
|
||||
// 调用二维码生成工具
|
||||
const qrDataUrl = await generateQRCode(qrContent, {
|
||||
size: 200,
|
||||
margin: 1,
|
||||
color: {
|
||||
dark: '#000000',
|
||||
light: '#FFFFFF'
|
||||
}
|
||||
});
|
||||
|
||||
console.log('二维码生成成功:', qrDataUrl.substring(0, 100) + '...');
|
||||
qrcodeData.value = qrDataUrl;
|
||||
showQrcode.value = true;
|
||||
switch (type) {
|
||||
case 'switchTab':
|
||||
uni.switchTab({ url: pagePath })
|
||||
break
|
||||
case 'redirectTo':
|
||||
uni.redirectTo({ url: pagePath })
|
||||
break
|
||||
default:
|
||||
uni.navigateTo({ url: pagePath })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('生成二维码失败:', error);
|
||||
console.error('页面跳转失败:', error)
|
||||
uni.showToast({
|
||||
title: '生成二维码失败',
|
||||
title: '页面跳转失败',
|
||||
icon: 'none'
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
wxStore.refreshBalance()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="profile-container">
|
||||
<!-- 二维码 -->
|
||||
<wd-popup v-model="showQrcode" custom-style="border-radius:16rpx; padding: 0;" position="center" >
|
||||
<view class="qrcode-wrapper">
|
||||
<view class="qrcode-header">
|
||||
<view class="qrcode-title">{{ loginUser.name || '用户' }}的二维码</view>
|
||||
<!-- <view class="qrcode-close" @click="showQrcode = false">-->
|
||||
<!-- <wd-icon name="close" size="20px"></wd-icon>-->
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
<view class="qrcode-content">
|
||||
<view class="qrcode-image-container" v-if="qrcodeData">
|
||||
<image :src="qrcodeData" mode="aspectFit" class="qrcode-image"></image>
|
||||
</view>
|
||||
<view class="qrcode-info">
|
||||
<!-- <view class="qrcode-desc">扫描二维码分享给好友</view>-->
|
||||
<view class="qrcode-user">
|
||||
<wd-img :width="40" :height="40" round :src="loginUser.avatar" />
|
||||
<view class="user-name">{{ loginUser.name || '用户' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-popup>
|
||||
<view class="user-info-section">
|
||||
<view class="me-page">
|
||||
<!-- 用户卡片 -->
|
||||
<view class="user-card">
|
||||
<view class="user-info">
|
||||
<view class="avatar-wrapper">
|
||||
<wd-img :width="60" :height="60" round :src="loginUser.avatar" :enable-preview="true" />
|
||||
<view class="user-details">
|
||||
<view class="username">
|
||||
<view style="margin-right: 8px">{{ loginUser.name }}</view>
|
||||
<wd-icon @click="itemClick('/pages/me/personal-profile/index')" name="edit-outline" size="16px"></wd-icon>
|
||||
</view>
|
||||
<view class="user-card">
|
||||
<wd-tag custom-class="space" mark use-icon-slot>
|
||||
<text>普卡会员</text>
|
||||
<template #icon>
|
||||
<wd-icon name="creditcard" />
|
||||
</template>
|
||||
</wd-tag>
|
||||
<!-- <wd-tag >卡号: {{ 10022342348 }}</wd-tag>-->
|
||||
</view>
|
||||
<image
|
||||
class="avatar"
|
||||
:src="userAvatar"
|
||||
mode="aspectFill"
|
||||
@click="handleLogout"
|
||||
/>
|
||||
</view>
|
||||
<view class="user-details">
|
||||
<view class="user-name">{{ name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 余额区域 -->
|
||||
<view class="balance-card">
|
||||
<view class="section-title">借呗信息</view>
|
||||
<view class="balance-content-wrapper">
|
||||
<view class="balance-item">
|
||||
<view class="balance-icon">
|
||||
<wd-icon name="money-circle" size="28px" color="#FFD700"></wd-icon>
|
||||
</view>
|
||||
<view class="user-right" @click="generateUserQRCode">
|
||||
<wd-icon name="qrcode" size="30px"></wd-icon>
|
||||
<view class="balance-content">
|
||||
<view class="balance-label">借呗总额</view>
|
||||
<view class="balance-value">{{ balanceLimit }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="balance-item">
|
||||
<view class="balance-content">
|
||||
<view class="balance-label">未还借呗</view>
|
||||
<view class="balance-value">{{ useBalance }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="balance-item">
|
||||
<view class="balance-content">
|
||||
<view class="balance-label">剩余借呗</view>
|
||||
<view class="balance-value">{{ balance }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="user-bottom">
|
||||
<wd-grid bg-color="#F5F7FA" :column="4">
|
||||
<wd-grid-item custom-class="custom-item" icon="picture" text="余额(元)" >
|
||||
<template #icon>
|
||||
<view class="balance">{{ 0 }}</view>
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item custom-class="custom-item" icon="picture" text="积分" >
|
||||
<template #icon>
|
||||
<view class="balance">{{ 0 }}</view>
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item custom-class="custom-item" icon="picture" text="卡项" >
|
||||
<template #icon>
|
||||
<view class="balance">{{ 0 }}</view>
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item custom-class="custom-item" icon="picture" text="优惠卷" >
|
||||
<template #icon>
|
||||
<view class="balance">{{ 0 }}</view>
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</view>
|
||||
</view>
|
||||
<view class="user-container">
|
||||
<view class="body-card-style-radius-padding" style="padding: 4px">
|
||||
<wd-grid :column="4">
|
||||
<wd-grid-item icon="picture" text="余额充值" >
|
||||
<template #icon>
|
||||
<ICOBalanceRecharge style="width: 35px; height: 35px" />
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item icon="picture" text="我的优惠卷" >
|
||||
<template #icon>
|
||||
<ICOMyCoupon style="width: 35px; height: 35px" />
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item icon="picture" text="我的权益" >
|
||||
<template #icon>
|
||||
<ICOMyRights style="width: 35px; height: 35px" />
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item icon="picture" text="我的订单" >
|
||||
<template #icon>
|
||||
<ICOMyOrder style="width: 35px; height: 35px" />
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</view>
|
||||
<view class="body-card-style-radius-padding">
|
||||
<view class="body-card-style-head">
|
||||
我的订单
|
||||
<view class="right text-right">
|
||||
<wd-icon name="arrow-right" size="16px"></wd-icon>
|
||||
全部
|
||||
</view>
|
||||
|
||||
<!-- 个人中心按钮 -->
|
||||
<view class="button-group">
|
||||
<view class="section-title">个人中心</view>
|
||||
<view class="button-row">
|
||||
<view class="button-item" @click="navigateToPage('/pages/order/index')">
|
||||
<wd-icon name="list" size="20px" color="#fff"></wd-icon>
|
||||
<text>订单列表</text>
|
||||
</view>
|
||||
<wd-grid :column="5">
|
||||
<wd-grid-item icon="wallet" text="待付款" />
|
||||
<wd-grid-item icon="bags" text="待发货" />
|
||||
<wd-grid-item text="待收货" >
|
||||
<template #icon>
|
||||
<view style="width: 26px; height: 26px; color: #000000" class="i-carbon:arrival"></view>
|
||||
</template>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item icon="dong" text="待评价" />
|
||||
<wd-grid-item icon="money-circle" text="退款/售后" />
|
||||
</wd-grid>
|
||||
</view>
|
||||
<view class="body-card-style-radius-padding" style="margin-bottom: 0">
|
||||
<view class="body-card-style-head">
|
||||
我的功能
|
||||
<view class="button-item" @click="navigateToPage('/pages/rental-list/index')">
|
||||
<wd-icon name="star" size="20px" color="#fff"></wd-icon>
|
||||
<text>我的柜子</text>
|
||||
</view>
|
||||
<wd-grid :column="4">
|
||||
<wd-grid-item icon="gift" @click="itemClick('/pages/me/promote-with-courtesy/index')" text="推广有礼" />
|
||||
<wd-grid-item icon="picture" text="我的预约" />
|
||||
<wd-grid-item icon="picture" text="购物车" />
|
||||
<wd-grid-item icon="picture" text="我的地点" />
|
||||
<wd-grid-item icon="picture" text="我的拼团" />
|
||||
<wd-grid-item icon="picture" text="我的表单" />
|
||||
<wd-grid-item icon="picture" text="我的消息" />
|
||||
<wd-grid-item icon="picture" text="服务日志" />
|
||||
<wd-grid-item icon="picture" text="待评价" />
|
||||
<wd-grid-item icon="picture" text="积分商城" />
|
||||
<wd-grid-item icon="picture" text="我的会员卡" />
|
||||
<wd-grid-item icon="picture" text="公众号通知" />
|
||||
</wd-grid>
|
||||
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/cabinet/index')">
|
||||
<wd-icon name="tools" size="20px" color="#fff"></wd-icon>
|
||||
<text>柜机管理</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="button-row">
|
||||
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approval/list/index')">
|
||||
<wd-icon name="secured" size="20px" color="#fff"></wd-icon>
|
||||
<text>审批中心</text>
|
||||
</view>
|
||||
<view v-if="wxStore.isCabinetAdmin" class="button-item" @click="navigateToPage('/pages/approvalAsset/list/index')">
|
||||
<wd-icon name="edit-1" size="20px" color="#fff"></wd-icon>
|
||||
<text>耗材核销</text>
|
||||
</view>
|
||||
<view class="button-placeholder"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.qrcode-wrappe{
|
||||
|
||||
<style scoped lang="scss">
|
||||
.me-page {
|
||||
background: #f7f8fa;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* 二维码弹框样式 */
|
||||
.qrcode-wrapper {
|
||||
width: 560rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
.user-card {
|
||||
margin: 12px;
|
||||
padding: 20px 16px;
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
|
||||
.qrcode-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 32rpx 32rpx 16rpx;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
|
||||
.qrcode-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.qrcode-close {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:active {
|
||||
background-color: #e8e8e8;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, rgba(64, 158, 255, 0.02) 0%, rgba(102, 126, 234, 0.02) 100%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.qrcode-content {
|
||||
padding: 32rpx;
|
||||
&:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.qrcode-image-container {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1);
|
||||
margin-bottom: 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.qrcode-image {
|
||||
width: 360rpx;
|
||||
height: 360rpx;
|
||||
}
|
||||
.avatar-wrapper {
|
||||
margin-right: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.qrcode-info {
|
||||
width: 100%;
|
||||
.avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid rgba(64, 158, 255, 0.2);
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.qrcode-desc {
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.avatar:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.qrcode-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 50rpx;
|
||||
.user-details {
|
||||
flex: 1;
|
||||
|
||||
.user-name {
|
||||
margin-left: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 基础样式 */
|
||||
.profile-container {
|
||||
overflow-y: auto;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
|
||||
|
||||
.user-info-section{
|
||||
background: #ffffff;
|
||||
|
||||
.avatar-wrapper{
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.user-details{
|
||||
margin-left: 16px;
|
||||
flex: 1;
|
||||
|
||||
.username{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-card-number{
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-right{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.user-bottom{
|
||||
padding: 0 9px 15px 9px;
|
||||
|
||||
.balance-card {
|
||||
margin: 12px;
|
||||
padding: 20px 16px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
padding-left: 8px;
|
||||
position: relative;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 16px;
|
||||
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.balance-content-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.user-container{
|
||||
padding: 12px;
|
||||
.balance-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0 8px;
|
||||
font-weight: 500;
|
||||
|
||||
.text-right{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #cccccc;
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.body-card-style-radius-padding {
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.body-card-style-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.balance-icon {
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.balance-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
|
||||
.balance-label {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 6px;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.balance-value {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 16px;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
color: #409EFF;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 移除:deep()选择器,直接使用类名 */
|
||||
:deep(.custom-item) {
|
||||
border-radius: 12px;
|
||||
margin: 0 6px;
|
||||
width: calc(100% / 4 - 12px) !important;
|
||||
height: 70px !important;
|
||||
.button-group {
|
||||
margin: 12px;
|
||||
padding: 16px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.balance{
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
padding-left: 8px;
|
||||
position: relative;
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 3px;
|
||||
height: 16px;
|
||||
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.button-row {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.button-item {
|
||||
flex: 1;
|
||||
height: 80px;
|
||||
background: linear-gradient(135deg, #409EFF 0%, #66B1FF 100%);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 12px;
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
&:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.4);
|
||||
}
|
||||
|
||||
wd-icon {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 13px;
|
||||
color: white;
|
||||
margin-top: 8px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.button-placeholder {
|
||||
flex: 1;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,279 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted ,nextTick, ref, computed } from 'vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { updateUserInfo } from '@/api/me'
|
||||
import { uploadFileUrl } from '@/utils/uploadFile'
|
||||
import {getToken} from "@/utils/token-util";
|
||||
import {API_BASE_URL} from "@/config/setting";
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '个人资料',
|
||||
},
|
||||
})
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
/** 登录用户信息 */
|
||||
const loginUser:any = computed(() => userStore.info ?? {});
|
||||
|
||||
//用户信息
|
||||
const form = ref({
|
||||
avatar: loginUser.value.avatar || '',
|
||||
name: loginUser.value.name || '',
|
||||
})
|
||||
|
||||
// 检查用户是否已授权获取用户信息
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
console.log(form,'ppp')
|
||||
|
||||
form.value = {
|
||||
avatar: loginUser.value.avatar || '',
|
||||
name: loginUser.value.name || '',
|
||||
}
|
||||
|
||||
console.log(form.value,'ppp')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 微信头像选择处理
|
||||
const onChooseAvatar = (e: any) => {
|
||||
console.log(e, '选择头像')
|
||||
if (e.detail && e.detail.avatarUrl) {
|
||||
// 微信小程序返回的头像URL
|
||||
form.value.avatar = e.detail.avatarUrl
|
||||
|
||||
// 将微信头像上传到服务器
|
||||
uploadWechatAvatar(e.detail.avatarUrl)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传微信头像到服务器
|
||||
const uploadWechatAvatar = (avatarUrl: string) => {
|
||||
|
||||
// 使用uploadFile直接上传微信头像
|
||||
uni.uploadFile({
|
||||
url: uploadFileUrl.USER_AVATAR,
|
||||
filePath: avatarUrl,
|
||||
name: 'file',
|
||||
formData: {},
|
||||
header: {
|
||||
// H5环境下不需要手动设置Content-Type,让浏览器自动处理multipart格式
|
||||
// #ifndef H5
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Token': getToken(),
|
||||
// #endif
|
||||
},
|
||||
success: (res) => {
|
||||
try {
|
||||
const data = JSON.parse(res.data)
|
||||
form.value.avatar = API_BASE_URL + data.result.url
|
||||
|
||||
} catch (error) {
|
||||
console.error('解析上传结果失败', error)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({
|
||||
title: '头像上传失败',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
complete: () => {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存用户信息
|
||||
*/
|
||||
const saveUserInfo = () => {
|
||||
updateUserInfo({
|
||||
nickName: form.value.name,
|
||||
headImg: form.value.avatar
|
||||
}).then(res => {
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'none'
|
||||
})
|
||||
//全局刷新用户信息
|
||||
userStore.fetchUserInfo()
|
||||
|
||||
}).catch(err => {
|
||||
uni.showToast({
|
||||
title: err.message || '保存失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="profile-container">
|
||||
<!-- 用户头像和昵称区域 -->
|
||||
<view class="user-info">
|
||||
<!-- 微信小程序环境使用button -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<image class="avatar" :src="form.avatar || '/static/images/default-avatar.png'" mode="aspectFill"></image>
|
||||
<view class="upload-overlay" v-if="loading">
|
||||
<wd-loading type="ring" size="20px" />
|
||||
<text class="upload-text">{{ progress }}%</text>
|
||||
</view>
|
||||
<wd-icon name="camera" size="22px" class="camera-icon"></wd-icon>
|
||||
</button>
|
||||
</view>
|
||||
<!-- 用户详细信息 -->
|
||||
<view class="detail-section">
|
||||
<view class="detail-item">
|
||||
<text class="label">昵称:</text>
|
||||
<input type="nickname" class="weui-input" v-model="form.name" placeholder="请输入昵称"/>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 保存按钮区域 -->
|
||||
<view class="save-section">
|
||||
<button class="save-btn" @click="saveUserInfo">保存信息</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.profile-container {
|
||||
background-color: #f5f5f5;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.avatar-wrapper{
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
//z-index: 999;
|
||||
//opacity: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
overflow: hidden;
|
||||
border: 4rpx solid #f0f0f0;
|
||||
background-color: transparent;
|
||||
|
||||
// 微信小程序button样式重置
|
||||
&.button-reset {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
border-radius: 50%;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
background: white;
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx 20rpx;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.upload-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
color: white;
|
||||
font-size: 24rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.camera-icon {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
padding: 8rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
border: 2rpx solid #f0f0f0;
|
||||
transform: translate(30%, 30%);
|
||||
}
|
||||
|
||||
.detail-section {
|
||||
background: white;
|
||||
border-radius: 20rpx;
|
||||
padding: 16rpx 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 20rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.detail-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.save-section {
|
||||
//background: white;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx 20rpx;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.save-btn {
|
||||
background-color: #409EFF;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10rpx;
|
||||
padding: 12rpx 12rpx;
|
||||
font-size: 26rpx;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useUserStore } from '@/store/user'
|
||||
const userStore = useUserStore();
|
||||
const showScanner = ref(false);
|
||||
|
||||
/** 登录用户信息 */
|
||||
const loginUser = computed(() => userStore.info ?? {});
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '推广有礼',
|
||||
navigationStyle: 'custom',
|
||||
},
|
||||
})
|
||||
|
||||
const toScanTheCode = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/QrScanner/index',
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="promote-with-courtesy-container">
|
||||
<view class="promote-with-courtesy-header">
|
||||
<view class="header-content">
|
||||
<view class="avatar-wrapper">
|
||||
<wd-img :width="50" :height="50" round :src="loginUser.avatar" :enable-preview="true" />
|
||||
<view class="username">
|
||||
{{ loginUser.name }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="user-details">
|
||||
<wd-grid style="width: 100%">
|
||||
<wd-grid-item>
|
||||
<view>累计获得奖励(次)</view>
|
||||
<view class="item">{{ 0 }}</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item >
|
||||
<view>累计推广客户</view>
|
||||
<view class="item">{{ 0 }}</view>
|
||||
</wd-grid-item>
|
||||
<wd-grid-item >
|
||||
<view>累计推广订单</view>
|
||||
<view class="item">{{ 0 }}</view>
|
||||
</wd-grid-item>
|
||||
</wd-grid>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<wd-status-tip >
|
||||
<template #image>
|
||||
<wd-icon name="error-circle" color="#F56C6C" size="150px"></wd-icon>
|
||||
<span style="margin-top: 16px">
|
||||
你还不是推广员
|
||||
</span>
|
||||
<wd-button @click="toScanTheCode" icon="scan" style="margin-top: 16px" plain >成为推广员</wd-button>
|
||||
</template>
|
||||
</wd-status-tip>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.promote-with-courtesy-container{
|
||||
.promote-with-courtesy-header{
|
||||
height: 180px;
|
||||
.header-content{
|
||||
height: 120px;
|
||||
background: linear-gradient(to right, #ecf5ff, #d9ecff);
|
||||
.avatar-wrapper{
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.username{
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
.user-details{
|
||||
padding: 4px;
|
||||
background: #ffffff;
|
||||
margin: 0 15px;
|
||||
border-radius: 10px;
|
||||
.item{
|
||||
margin-top: 8px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,590 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, onBeforeUnmount } from 'vue'
|
||||
import {applyRefund, getForecastRefund, getOrderDetail, payOrder} from '@/api/order'
|
||||
import { onPullDownRefresh, onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import {API_BASE_URL} from "@/config/setting";
|
||||
import { getRefundStep,cancelRefund } from "@/api/order";
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '订单详情',
|
||||
enablePullDownRefresh: true
|
||||
},
|
||||
})
|
||||
|
||||
// 订单数据
|
||||
const orderDetail = ref<any>({})
|
||||
const orderNo = ref('')
|
||||
const loading = ref(false)
|
||||
const countdown = ref(0)
|
||||
// 订单状态映射
|
||||
const statusMap = [
|
||||
{ text: '待支付', color: '#e6a23c', value: 0 },
|
||||
{ text: '已支付', color: '#67c23a', value: 2 },
|
||||
{ text: '支付失败', color: '#f56c6c', value: 3 },
|
||||
{ text: '超时未支付', color: '#f56c6c', value: 4 },
|
||||
{ text: '已退款', color: '#909399', value: 5 },
|
||||
{ text: '已取消', color: '#909399', value: 6 },
|
||||
{ text: '待商家审核', color: '#e6a23c', value: 7 }
|
||||
]
|
||||
|
||||
// 计算属性
|
||||
const orderStatus = computed(() => statusMap.find(item => item.value === orderDetail.value.status))
|
||||
|
||||
// 格式化倒计时显示
|
||||
const formatCountdown = computed(() => {
|
||||
if (countdown.value <= 0) return '00:00';
|
||||
|
||||
const minutes = Math.floor(countdown.value / 60);
|
||||
const seconds = countdown.value % 60;
|
||||
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
});
|
||||
|
||||
// 退款步骤
|
||||
// const refundSteps = computed(() => {
|
||||
// const status = orderDetail.value.status
|
||||
// if (status != 7)return []
|
||||
//
|
||||
// const steps = [
|
||||
// { title: '申请退款', time: orderDetail.value.createTime, active: true }
|
||||
// ]
|
||||
//
|
||||
// if (status == 5) {
|
||||
// steps.push({ title: '退款成功', time: orderDetail.value.refundTime, active: true })
|
||||
// } else {
|
||||
// steps.push({ title: '待商家审核', time: '', active: false })
|
||||
// }
|
||||
//
|
||||
// return steps
|
||||
// })
|
||||
|
||||
const active = ref(0)
|
||||
|
||||
const refundSteps = ref<any>([]);
|
||||
// 获取订单详情
|
||||
const fetchOrderDetail = async () => {
|
||||
getOrderDetail({ orderNo: orderNo.value }).then((res) => {
|
||||
orderDetail.value = res.data || {};
|
||||
uni.stopPullDownRefresh()
|
||||
getRefundStep({ orderNo: orderNo.value }).then((res) => {
|
||||
|
||||
refundSteps.value = res.data.map((item:any) => ({
|
||||
title: item.content,
|
||||
time: item.when,
|
||||
}))
|
||||
active.value = refundSteps.value.length
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (time: string) => {
|
||||
if (!time) return '';
|
||||
|
||||
try {
|
||||
const date = new Date(time);
|
||||
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||
} catch (e) {
|
||||
return time;
|
||||
}
|
||||
};
|
||||
|
||||
// 复制订单号
|
||||
const copyOrderNo = () => {
|
||||
if (!orderNo.value) return;
|
||||
|
||||
uni.setClipboardData({
|
||||
data: orderNo.value,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '订单号已复制',
|
||||
icon: 'none'
|
||||
});
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '复制失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 支付订单
|
||||
const handlePayOrder = async () => {
|
||||
payOrder({
|
||||
orderNo: orderDetail.value.orderNo,
|
||||
payType: 'WX_MP',
|
||||
onlinePay: Number(orderDetail.value.money)
|
||||
}).then((res: any) => {
|
||||
// 仅作为示例,非真实参数信息。
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: res.data.timeStamp,
|
||||
nonceStr: res.data.nonceStr,
|
||||
package: res.data.package,
|
||||
signType: res.data.signType,
|
||||
paySign: res.data.paySign,
|
||||
success: function (res) {
|
||||
console.log('success:' + JSON.stringify(res));
|
||||
uni.showToast({
|
||||
title:'支付成功',
|
||||
icon: 'none'
|
||||
})
|
||||
fetchOrderDetail()
|
||||
},
|
||||
fail: function (err) {
|
||||
uni.showToast({
|
||||
title:'取消支付',
|
||||
icon: 'none'
|
||||
})
|
||||
console.log('fail:' + JSON.stringify(err));
|
||||
}
|
||||
});
|
||||
}).catch(()=>{
|
||||
uni.showToast({
|
||||
title:'支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
// 申请退款
|
||||
const handleApplyRefund = (item:any) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/refund-confirmation/index?orderNo=' + item.orderNo
|
||||
})
|
||||
};
|
||||
|
||||
// 页面加载
|
||||
onLoad((options: any) => {
|
||||
if (options.orderNo) {
|
||||
orderNo.value = options.orderNo;
|
||||
fetchOrderDetail();
|
||||
}
|
||||
});
|
||||
|
||||
onShow(()=>{
|
||||
fetchOrderDetail();
|
||||
})
|
||||
onPullDownRefresh(()=>{
|
||||
fetchOrderDetail();
|
||||
console.log('pppp')
|
||||
|
||||
})
|
||||
|
||||
//图片渲染
|
||||
const renderImage = (item: any) => {
|
||||
return API_BASE_URL + item.product.pictures[0];
|
||||
}
|
||||
|
||||
const getPrice = (record: any) => {
|
||||
if (!record) return
|
||||
return getSpecificationPrice(record.specificationPrices);
|
||||
};
|
||||
const getSpecificationPrice = (specifications: any[]): number | undefined => {
|
||||
if(!specifications) return
|
||||
const firstSpec = specifications[0];
|
||||
if (!firstSpec) return undefined;
|
||||
if (firstSpec.price != null && firstSpec.price !== 0) return firstSpec.price;
|
||||
if (firstSpec.child) return getSpecificationPrice(firstSpec.child);
|
||||
return undefined;
|
||||
};
|
||||
|
||||
//倒计时结束 改变状态
|
||||
const payTimeLeft = (item:any) => {
|
||||
console.log(item,'倒计时结束')
|
||||
item.status = 4
|
||||
}
|
||||
//根据创建时间 按15分钟。剩余支付时间
|
||||
function getPayTimeLeft(item:any) {
|
||||
//创建时间加15分钟
|
||||
const AddcreateTime:any = new Date(item.createTime).getTime() + 1000 * 60 * 15
|
||||
//减当前时间
|
||||
const diff:any = AddcreateTime - new Date().getTime()
|
||||
if (diff <= 0) {
|
||||
item.status = 4
|
||||
}
|
||||
return diff
|
||||
}
|
||||
//退款状态列表
|
||||
const showPay = (status:any) => {
|
||||
return status == 2 || status == 7;
|
||||
}
|
||||
|
||||
//取消退款
|
||||
const handleCancelRefund = (item:any) => {
|
||||
|
||||
uni.showModal({
|
||||
title: '取消退款',
|
||||
content: '确定要取消退款吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
cancelRefund({
|
||||
orderNo: item.orderNo
|
||||
}).then((res) => {
|
||||
uni.showToast({
|
||||
title:'取消退款成功',
|
||||
icon: 'none'
|
||||
})
|
||||
fetchOrderDetail()
|
||||
}).catch(()=>{
|
||||
uni.showToast({
|
||||
title:'取消退款失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="order-detail-container">
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="loading" class="loading-container">
|
||||
<wd-loading />
|
||||
</view>
|
||||
<!-- 订单详情内容 -->
|
||||
<template v-else>
|
||||
<!-- 订单状态卡片 -->
|
||||
<wd-card>
|
||||
<template #title>
|
||||
<view class="status-header">
|
||||
<view class="status-info">
|
||||
<view class="status-icon" :style="{ color: orderStatus.color }">
|
||||
<!-- <text class="iconfont" :class="orderStatus.icon"></text>-->
|
||||
</view>
|
||||
<view class="status-text" :style="{ color: orderStatus.color }">
|
||||
|
||||
<span v-if="orderDetail.status == 0" style="color: #e6a23c">
|
||||
<wd-count-down @finish="payTimeLeft(orderDetail)" :auto-start="true" format="支付时间 : mm 分 ss 秒" :time="getPayTimeLeft(orderDetail)" >
|
||||
</wd-count-down>
|
||||
</span>
|
||||
<span v-else>{{ orderStatus.text }}</span>
|
||||
</view>
|
||||
</view>
|
||||
<wd-button type="text" size="small" @click="copyOrderNo">
|
||||
<text class="iconfont wd-icon-copy"></text>
|
||||
复制
|
||||
</wd-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view class="order-no">订单号:{{ orderNo }}</view>
|
||||
<view class="status-desc">
|
||||
{{
|
||||
orderDetail.status == 0 ? '订单待支付,请尽快完成支付' :
|
||||
orderDetail.status == 2 ? '订单已完成,感谢您的购买' :
|
||||
orderDetail.status == 6 ? '订单已取消' :
|
||||
orderDetail.status == 5 ? '订单已退款,款项将原路返回' :
|
||||
orderDetail.status == 7 ? '退款申请已提交,请耐心等待' : ''
|
||||
}}
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 退款状态流程 -->
|
||||
<wd-card v-if="refundSteps.length">
|
||||
<!-- <template #title>-->
|
||||
<!-- <view class="section-title">退款流程</view>-->
|
||||
<!-- </template>-->
|
||||
<!-- align-center-->
|
||||
<view class="refund-steps">
|
||||
<wd-steps :active="active" dot style="width: 100%" vertical>
|
||||
<wd-step :status="step.statusText" v-for="(step, index) in refundSteps" :key="index" :title="step.title" :description="step.time" />
|
||||
</wd-steps>
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 商品信息卡片 -->
|
||||
<wd-card>
|
||||
<template #title>
|
||||
<view class="section-title">商品信息</view>
|
||||
</template>
|
||||
|
||||
<view class="product-list">
|
||||
<view class="product-item" v-for="(item, index) in orderDetail?.products" :key="index">
|
||||
<wd-img
|
||||
:width="80"
|
||||
:height="80"
|
||||
:src="renderImage(item)"
|
||||
mode="aspectFill"
|
||||
radius="6"
|
||||
lazy-load
|
||||
>
|
||||
<template #error>
|
||||
<view class="error-wrap">加载失败</view>
|
||||
</template>
|
||||
</wd-img>
|
||||
<view class="product-info">
|
||||
<view class="product-name">{{ item.product.name }}</view>
|
||||
<view class="product-spec" v-if="item.product.spec">{{ item.product.spec }}</view>
|
||||
<view class="product-price-quantity">
|
||||
<text class="product-price">¥{{ item.product.price ? item.product.price : getPrice(item.product)}}</text>
|
||||
<text class="product-quantity">x{{ item.amount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 订单信息卡片 -->
|
||||
<wd-card>
|
||||
<template #title>
|
||||
<view class="section-title">订单信息</view>
|
||||
</template>
|
||||
|
||||
<view class="order-info">
|
||||
<wd-cell title="下单时间" :value="formatTime(orderDetail.createTime)" />
|
||||
<wd-cell title="支付时间" :value="formatTime(orderDetail.payTime)" v-if="orderDetail.payTime" />
|
||||
<wd-cell title="完成时间" :value="formatTime(orderDetail.completeTime)" v-if="orderDetail.completeTime" />
|
||||
<wd-cell title="退款时间" :value="formatTime(orderDetail.refundTime)" v-if="orderDetail.refundTime" />
|
||||
<wd-cell title="支付方式" :value="showPay ? '微信支付' : '未支付'" />
|
||||
<wd-cell title="订单备注" :value="orderDetail.remark || '无'" />
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 费用明细卡片 -->
|
||||
<wd-card>
|
||||
<template #title>
|
||||
<view class="section-title">费用明细</view>
|
||||
</template>
|
||||
|
||||
<view class="cost-detail">
|
||||
<wd-cell title="商品总额" :value="`¥${orderDetail.money || 0}`" />
|
||||
<wd-cell title="退款金额" :value="`-¥${orderDetail.refundAmount || 0}`" v-if="orderDetail.refundAmount" />
|
||||
<wd-cell title="实付金额" :value="`¥${showPay ? orderDetail.money : 0}`" custom-class="total-amount" />
|
||||
</view>
|
||||
</wd-card>
|
||||
<view style="height: 60px"></view>
|
||||
<!-- 底部操作栏 v-if="showCancelButton" v-if="showPayButton || showCancelButton || showConfirmButton || showLogisticsButton || showRefundButton"-->
|
||||
<view class="bottom-actions" >
|
||||
<wd-button type="default" v-if="orderDetail.status == '2'" @click="handleApplyRefund(orderDetail)">申请退款</wd-button>
|
||||
<wd-button type="default" v-if="orderDetail.status == '7'" @click="handleCancelRefund(orderDetail)">取消退款</wd-button>
|
||||
<wd-button type="primary" v-if="orderDetail.status == '0'" @click="handlePayOrder">付款</wd-button>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.order-detail-container {
|
||||
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
|
||||
.status-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.status-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.status-icon {
|
||||
font-size: 24px;
|
||||
//margin-right: 10px;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.wd-count-down){
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #e6a23c !important;
|
||||
}
|
||||
|
||||
.order-no {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
margin-top: 10px;
|
||||
padding: 8px 12px;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.countdown-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
padding: 8px 12px;
|
||||
background-color: #fff8e6;
|
||||
border-radius: 4px;
|
||||
|
||||
.countdown-text {
|
||||
font-size: 13px;
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.countdown-time {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #e6a23c;
|
||||
margin-left: 5px;
|
||||
|
||||
&.countdown-warning {
|
||||
color: #f56c6c;
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.refund-steps {
|
||||
width: 100%;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.address-info {
|
||||
.address-name-phone {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
.product-list {
|
||||
.product-item {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
margin-left: 12px;
|
||||
|
||||
.product-name {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin-bottom: 5px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.product-spec {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.product-price-quantity {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.product-price {
|
||||
font-size: 16px;
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.order-info {
|
||||
:deep(.wd-cell) {
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.cost-detail {
|
||||
|
||||
:deep(.wd-cell) {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
:deep(.total-amount) {
|
||||
.wd-cell__value {
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 10px 15px;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||
z-index: 100;
|
||||
|
||||
.wd-button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import {onShow} from '@dcloudio/uni-app'
|
||||
import {applyRefund, listFinanceOrder} from '@/api/order'
|
||||
import {API_BASE_URL} from "@/config/setting";
|
||||
import {useUserStore} from "@/store";
|
||||
import { payOrder, cancelRefund } from '@/api/order'
|
||||
const userStore = useUserStore();
|
||||
/** 登录用户信息 */
|
||||
const loginUser:any = computed(() => userStore.info ?? {});
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '订单',
|
||||
// navigationStyle: 'custom',
|
||||
},
|
||||
})
|
||||
|
||||
const tab = ref(-1)
|
||||
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全部',
|
||||
value: -1,
|
||||
},
|
||||
{
|
||||
name: '待支付',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '已支付',
|
||||
value: 2,
|
||||
},
|
||||
// {
|
||||
// name: '支付超时',
|
||||
// value: 3,
|
||||
// },
|
||||
// {
|
||||
// name: '退款中',
|
||||
// value: 8,
|
||||
// },
|
||||
{
|
||||
name: '已退款',
|
||||
value: 5,
|
||||
},
|
||||
])
|
||||
const paging = ref(null)
|
||||
// v-model绑定的这个变量不要在分页请求结束中自己赋值,直接使用即可
|
||||
const dataList = ref([])
|
||||
onShow(()=>{
|
||||
if (paging.value){
|
||||
paging.value.reload()
|
||||
}
|
||||
})
|
||||
// @query所绑定的方法不要自己调用!!需要刷新列表数据时,只需要调用paging.value.reload()即可
|
||||
const queryList = (pageNo, pageSize) => {
|
||||
// 此处请求仅为演示,请替换为自己项目中的请求
|
||||
listFinanceOrder({page:pageNo,size:pageSize,status: tab.value == -1 ? null : [tab.value],uid:loginUser.value.pid}).then(res => {
|
||||
console.log(res)
|
||||
paging.value.complete(res.data);
|
||||
}).catch(()=>{
|
||||
paging.value.complete(false);
|
||||
})
|
||||
}
|
||||
const changeTab = () => {
|
||||
paging.value.reload()
|
||||
}
|
||||
|
||||
//根据创建时间 按15分钟。剩余支付时间
|
||||
function getPayTimeLeft(item:any) {
|
||||
//创建时间加15分钟
|
||||
const AddcreateTime:any = new Date(item.createTime).getTime() + 1000 * 60 * 15
|
||||
//减当前时间
|
||||
const diff:any = AddcreateTime - new Date().getTime()
|
||||
if (diff <= 0) {
|
||||
item.status = 4
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
//倒计时结束 改变状态
|
||||
const payTimeLeft = (item:any) => {
|
||||
console.log(item,'倒计时结束')
|
||||
item.status = 4
|
||||
}
|
||||
|
||||
//付款
|
||||
const addPayOrder = (item:any) => {
|
||||
payOrder({
|
||||
orderNo: item.orderNo,
|
||||
payType: 'WX_MP',
|
||||
onlinePay: Number(item.money)
|
||||
}).then((res: any) => {
|
||||
// 仅作为示例,非真实参数信息。
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: res.data.timeStamp,
|
||||
nonceStr: res.data.nonceStr,
|
||||
package: res.data.package,
|
||||
signType: res.data.signType,
|
||||
paySign: res.data.paySign,
|
||||
success: function (res) {
|
||||
console.log('success:' + JSON.stringify(res));
|
||||
uni.showToast({
|
||||
title:'支付成功',
|
||||
icon: 'none'
|
||||
})
|
||||
paging.value.reload()
|
||||
},
|
||||
fail: function (err) {
|
||||
uni.showToast({
|
||||
title:'取消支付',
|
||||
icon: 'none'
|
||||
})
|
||||
console.log('fail:' + JSON.stringify(err));
|
||||
}
|
||||
});
|
||||
}).catch(()=>{
|
||||
uni.showToast({
|
||||
title:'支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//跳转订单详情页面
|
||||
const jumpDetail = (item:any) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/detail/index?orderNo=' + item.orderNo
|
||||
})
|
||||
}
|
||||
|
||||
//退款
|
||||
const addRefundOrder = (item:any) => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/refund-confirmation/index?orderNo=' + item.orderNo
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//取消退款
|
||||
const handleCancelRefund = (item:any) => {
|
||||
|
||||
uni.showModal({
|
||||
title: '取消退款',
|
||||
content: '确定要取消退款吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
cancelRefund({
|
||||
orderNo: item.orderNo
|
||||
}).then((res) => {
|
||||
uni.showToast({
|
||||
title:'取消退款成功',
|
||||
icon: 'none'
|
||||
})
|
||||
paging.value.reload()
|
||||
}).catch(()=>{
|
||||
uni.showToast({
|
||||
title:'取消退款失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<z-paging :show-scrollbar="false" ref="paging" inside-more v-model="dataList" @query="queryList">
|
||||
<template #top>
|
||||
<view style="padding: 6px 0;" >
|
||||
<wd-segmented :options="tabList" v-model:value="tab" customStyle="background: #f7f8fa" @click="changeTab">
|
||||
<template #label="{ option }">
|
||||
<view class="name">{{ option.name }}</view>
|
||||
</template>
|
||||
</wd-segmented>
|
||||
</view>
|
||||
</template>
|
||||
<!-- z-paging默认铺满全屏,此时页面所有view都应放在z-paging标签内,否则会被盖住 -->
|
||||
<!-- 需要固定在页面顶部的view请通过slot="top"插入,包括自定义的导航栏 -->
|
||||
<wd-card v-for="(item,index) in dataList" :key="index">
|
||||
|
||||
<template #title>
|
||||
<wd-cell style="padding: 0" size="large" :title="item.orderNo" >
|
||||
<span v-if="item.status == 0" style="color: #e6a23c">
|
||||
<wd-count-down @finish="payTimeLeft(item)" :auto-start="true" format="支付时间 : mm 分 ss 秒" :time="getPayTimeLeft(item)" >
|
||||
<!-- <template #default="{ current }">-->
|
||||
<!-- <span class="custom-count-down">支付时间:</span>-->
|
||||
<!-- <span class="custom-count-down">{{ current.minutes }} 分</span>-->
|
||||
<!-- <span class="custom-count-down-colon"> : </span>-->
|
||||
<!-- <span class="custom-count-down">{{ current.seconds }} 秒</span>-->
|
||||
<!-- </template>-->
|
||||
</wd-count-down>
|
||||
</span>
|
||||
<!-- <span v-if="item.status == 0" style="color: #e6a23c">待支付</span>-->
|
||||
<span v-if="item.status == 1" style="color: #e6a23c">支付中</span>
|
||||
<span v-if="item.status == 2" style="color: #67c23a">已支付</span>
|
||||
<span v-if="item.status == 3" style="color: #f56c6c">支付失败</span>
|
||||
<span v-if="item.status == 4" style="color: #f56c6c">超时未支付</span>
|
||||
<span v-if="item.status == 5" style="color: #909399">已退款</span>
|
||||
<span v-if="item.status == 6" style="color: #909399">已取消</span>
|
||||
<span v-if="item.status == 7" style="color: #e6a23c">待商家审核</span>
|
||||
</wd-cell>
|
||||
</template>
|
||||
<view class="products-item" v-for="(items,index) in item.products" :key="index">
|
||||
<wd-img radius="6" :width="80" :height="80" :src="API_BASE_URL + items.product.pictures[0]">
|
||||
<template #error>
|
||||
<view class="error-wrap">加载失败</view>
|
||||
</template>
|
||||
<template #loading>
|
||||
<view class="loading-wrap">
|
||||
<wd-loading />
|
||||
</view>
|
||||
</template>
|
||||
</wd-img>
|
||||
<view class="items-baseline">
|
||||
<view class="title"><wd-text color="#000" size="14px" :text="items.product.name"></wd-text></view>
|
||||
<view v-if="items?.type == 0">服务</view>
|
||||
<view v-if="items?.type == 1">商品</view>
|
||||
<view>优惠卷:{{ items?.manualDiscount != '0' ? '手动改价-' + items?.manualDiscount + '元' : '不使用' }}</view>
|
||||
<view>{{ item.createTime }}</view>
|
||||
</view>
|
||||
<view class="price">
|
||||
<view style=" color: #F56C6C;">¥{{ items?.amount * items?.actualPrice }}</view>
|
||||
<view class="items-amount">x{{items.amount}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<template #footer>
|
||||
<view class="item-footer">
|
||||
<view>共{{item.products.length}}件,合计<span style="color:#F56C6C;margin: 0 6px">¥{{item.money}}</span>元</view>
|
||||
<view style="display: flex;align-items: center;">
|
||||
<view style="margin-right: 8px;">
|
||||
<wd-button size="small" @click="addPayOrder(item)" v-if="item.status == 0" plain>付款</wd-button>
|
||||
</view>
|
||||
<view style="margin-right: 8px;">
|
||||
<wd-button size="small" @click="addRefundOrder(item)" v-if="item.status == 2" plain>申请退款</wd-button>
|
||||
</view>
|
||||
<view style="margin-right: 8px;">
|
||||
<wd-button size="small" @click="handleCancelRefund(item)" v-if="item.status == 7" plain>取消退款</wd-button>
|
||||
</view>
|
||||
<view>
|
||||
<wd-button size="small" @click="jumpDetail(item)" plain>详情</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</wd-card>
|
||||
</z-paging>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 移除:deep()选择器,直接使用类名 */
|
||||
:deep(.wd-cell) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
:deep(.wd-count-down){
|
||||
font-size: 12px;
|
||||
color: #e6a23c !important;
|
||||
}
|
||||
|
||||
:deep(.wd-cell__wrapper){
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.products-item{
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
.items-baseline{
|
||||
flex: 1;
|
||||
margin-left: 10px;
|
||||
.items-specification{
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
}
|
||||
.price{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
.items-amount{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-footer{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,364 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import { applyRefund, getForecastRefund, getOrderDetail } from '@/api/order'
|
||||
import { API_BASE_URL } from "@/config/setting";
|
||||
import { useUserStore } from "@/store";
|
||||
|
||||
const userStore = useUserStore();
|
||||
/** 登录用户信息 */
|
||||
const loginUser: any = computed(() => userStore.info ?? {});
|
||||
|
||||
definePage({
|
||||
style: {
|
||||
navigationBarTitleText: '退款确认',
|
||||
},
|
||||
})
|
||||
|
||||
// 订单数据
|
||||
const orderDetail = ref<any>({})
|
||||
const orderNo = ref('')
|
||||
const loading = ref(false)
|
||||
const refundReason = ref('')
|
||||
const refundAmount = ref(0)
|
||||
const isSubmitting = ref(false)
|
||||
|
||||
|
||||
//退款
|
||||
const addRefundOrder = () => {
|
||||
if (!refundReason.value.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入退款原因',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
uni.showModal({
|
||||
title: '申请退款',
|
||||
content: '确定要申请退款吗?',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
isSubmitting.value = true
|
||||
getForecastRefund({
|
||||
orderNo: orderDetail.value.orderNo,
|
||||
}).then((res: any) => {
|
||||
uni.showToast({
|
||||
title: res,
|
||||
icon: 'none'
|
||||
})
|
||||
applyRefund({
|
||||
orderNo: res.data.orderno,
|
||||
enc: res.data.enc,
|
||||
reason: refundReason.value,
|
||||
}).then((res: any) => {
|
||||
uni.showToast({
|
||||
title: '已申请退款',
|
||||
icon: 'none'
|
||||
})
|
||||
isSubmitting.value = false
|
||||
// 延迟跳转,让用户看到成功提示
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}).catch((err) => {
|
||||
uni.showToast({
|
||||
title: err,
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
}).catch((err) => {
|
||||
uni.showToast({
|
||||
title: err,
|
||||
icon: 'none'
|
||||
})
|
||||
isSubmitting.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 获取订单详情
|
||||
const fetchOrderDetail = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getOrderDetail({ orderNo: orderNo.value })
|
||||
orderDetail.value = res.data || {}
|
||||
refundAmount.value = orderDetail.value.money || 0
|
||||
} catch (error) {
|
||||
console.error('获取订单详情失败', error)
|
||||
uni.showToast({
|
||||
title: '获取订单详情失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 页面加载
|
||||
onLoad((options: any) => {
|
||||
if (options.orderNo) {
|
||||
orderNo.value = options.orderNo;
|
||||
fetchOrderDetail();
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="refund-confirmation">
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="loading" class="loading-container">
|
||||
<wd-loading type="ring" size="24px" />
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 退款内容 -->
|
||||
<view v-else-if="orderDetail.orderNo" class="refund-content">
|
||||
<!-- 退款信息卡片 -->
|
||||
<wd-card>
|
||||
<template #title>
|
||||
<view class="section-title">退款信息</view>
|
||||
</template>
|
||||
|
||||
<view class="refund-info">
|
||||
<view class="refund-amount">
|
||||
<text class="label">退款金额:</text>
|
||||
<text class="amount">¥{{ refundAmount }}</text>
|
||||
</view>
|
||||
|
||||
<view class="refund-reason">
|
||||
<text class="label">退款原因:</text>
|
||||
<wd-textarea
|
||||
v-model="refundReason"
|
||||
placeholder="请输入退款原因"
|
||||
rows="3"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</wd-card>
|
||||
|
||||
<!-- 退款提示 -->
|
||||
<view class="refund-tips">
|
||||
<view class="tips-title">退款提示</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">1. 退款申请提交后,将在1-3个工作日内处理</view>
|
||||
<view class="tip-item">2. 退款金额将原路返回到您的支付账户</view>
|
||||
<view class="tip-item">3. 如有疑问,请联系客服</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="bottom-actions">
|
||||
<button
|
||||
class="submit-btn"
|
||||
:disabled="isSubmitting"
|
||||
@click="addRefundOrder"
|
||||
>
|
||||
{{ isSubmitting ? '提交中...' : '申请退款' }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-else class="empty-container">
|
||||
<wd-status-tip image="empty" tip="订单信息不存在" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.refund-confirmation {
|
||||
padding-bottom: 120rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400rpx;
|
||||
color: #999;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.refund-content {
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
// 订单信息
|
||||
.order-info {
|
||||
.order-no, .order-time, .order-status {
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
// 商品列表
|
||||
.product-list {
|
||||
.product-item {
|
||||
display: flex;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.product-name {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.product-spec {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
.product-price-quantity {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.product-price {
|
||||
font-size: 30rpx;
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.product-quantity {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 退款信息
|
||||
.refund-info {
|
||||
.refund-amount {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 32rpx;
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.refund-reason {
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 退款提示
|
||||
.refund-tips {
|
||||
margin-top: 20rpx;
|
||||
padding: 24rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
|
||||
.tips-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
.tip-item {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部操作栏
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
gap: 20rpx;
|
||||
|
||||
.cancel-btn, .submit-btn {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #f5f5f5;
|
||||
color: #666;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background-color: #409EFF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
||||
&:disabled {
|
||||
background-color: #a0cfff;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60vh;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue