refactor(me): 重构我的页面代码结构

移除未使用的订单相关页面和组件
优化用户信息展示和余额显示逻辑
调整页面布局和样式
This commit is contained in:
dzq 2025-11-03 17:02:19 +08:00
parent cb445624e6
commit 71993d9a77
9 changed files with 349 additions and 1974 deletions

View File

@ -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": []

View File

@ -5,6 +5,6 @@
。仅参考语法api需要使用原ProductList.vue中已经移植到本项目的相应apistores也需要使用移植后的pinia。生成的代码写到
@src\pages\home\ 文件夹下
参考已迁移至本项目的代码 @src\pages\index\ 。将 @doc\thirdParty\src\pages\product\components\
下的另外两个component也迁移到本项目。注意thirdParty下的是H5项目现在需要改为微信小程序uni-app。api需要使用原Product
List.vue中已经移植到本项目的相应apistores也需要使用移植后的pinia。
参考已迁移至本项目的代码 @src\pages\index\ 。将 @doc\thirdParty\src\pages\me\index.vue
“我的”页面也迁移到本项目。注意thirdParty下的是H5项目现在需要改为微信小程序uni-app。api需要使用原Product
List.vue中已经移植到本项目的相应apistores也需要使用移植后的pinia。生成的代码写到 @src\pages\me\ 文件夹下

View File

@ -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": []

View File

@ -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>

View File

@ -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: {
// H5Content-Typemultipart
// #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>

View File

@ -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>

View File

@ -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>

View File

@ -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()
}
})
// @querypaging.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>

View File

@ -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>