Compare commits
No commits in common. "075054a6c17920eb77cde179b6c7488ee5ca3f19" and "f22d2a81e1971a409947c477569d95523ac2a157" have entirely different histories.
075054a6c1
...
f22d2a81e1
112
App.vue
112
App.vue
|
|
@ -19,52 +19,52 @@
|
||||||
console.log(options)
|
console.log(options)
|
||||||
|
|
||||||
// 2. 注意:scene 返回的是数字类型,不是字符串!原生代码中写 '1038' 会导致判断失败
|
// 2. 注意:scene 返回的是数字类型,不是字符串!原生代码中写 '1038' 会导致判断失败
|
||||||
// if (options.scene === 1038 &&
|
if (options.scene === 1038 &&
|
||||||
// options.referrerInfo?.appId === 'wxef277996acc166c3') {
|
options.referrerInfo?.appId === 'wxef277996acc166c3') {
|
||||||
|
|
||||||
// // 从收银台小程序返回的逻辑
|
// 从收银台小程序返回的逻辑
|
||||||
// const extraData = options.referrerInfo.extraData;
|
const extraData = options.referrerInfo.extraData;
|
||||||
// console.log("extraData",extraData)
|
console.log("extraData",extraData)
|
||||||
|
|
||||||
// if (!extraData) {
|
if (!extraData) {
|
||||||
// uni.showToast({
|
uni.showToast({
|
||||||
// title: '当前通过物理按键返回,未接收到返参,建议自行查询交易结果',
|
title: '当前通过物理按键返回,未接收到返参,建议自行查询交易结果',
|
||||||
// icon: 'none',
|
icon: 'none',
|
||||||
// duration: 3000
|
duration: 3000
|
||||||
// });
|
});
|
||||||
// } else {
|
} else {
|
||||||
// if (extraData.code === 'success') {
|
if (extraData.code === 'success') {
|
||||||
// // 有返回成功标记后,启动轮询查询订单状态
|
// 有返回成功标记后,启动轮询查询订单状态
|
||||||
// // 1. 优先使用收银台回传的订单号
|
// 1. 优先使用收银台回传的订单号
|
||||||
// const orderNumberFromExtra =
|
const orderNumberFromExtra =
|
||||||
// extraData.orderNumber || extraData.reqsn || extraData.orderNo;
|
extraData.orderNumber || extraData.reqsn || extraData.orderNo;
|
||||||
// // 2. 如果对方没有回传,则使用我们在跳转前自己缓存到本地的订单号
|
// 2. 如果对方没有回传,则使用我们在跳转前自己缓存到本地的订单号
|
||||||
// const storedOrderNumber = uni.getStorageSync("lastOrderNumber");
|
const storedOrderNumber = uni.getStorageSync("lastOrderNumber");
|
||||||
// const orderNumber = orderNumberFromExtra || storedOrderNumber;
|
const orderNumber = orderNumberFromExtra || storedOrderNumber;
|
||||||
|
|
||||||
// if (orderNumber) {
|
if (orderNumber) {
|
||||||
// this.startOrderStatusPolling(orderNumber);
|
this.startOrderStatusPolling(orderNumber);
|
||||||
// } else {
|
} else {
|
||||||
// uni.showToast({
|
uni.showToast({
|
||||||
// title: '支付返回缺少订单号,请稍后在服务记录中查看',
|
title: '支付返回缺少订单号,请稍后在服务记录中查看',
|
||||||
// icon: 'none',
|
icon: 'none',
|
||||||
// duration: 3000
|
duration: 3000
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// } else if (extraData.code === 'cancel') {
|
} else if (extraData.code === 'cancel') {
|
||||||
// uni.showToast({
|
uni.showToast({
|
||||||
// title: '支付已取消',
|
title: '支付已取消',
|
||||||
// icon: 'none'
|
icon: 'none'
|
||||||
// });
|
});
|
||||||
// } else {
|
} else {
|
||||||
// uni.showToast({
|
uni.showToast({
|
||||||
// title: `支付失败:${extraData.errmsg || '未知错误'}`,
|
title: `支付失败:${extraData.errmsg || '未知错误'}`,
|
||||||
// icon: 'none',
|
icon: 'none',
|
||||||
// duration: 3000
|
duration: 3000
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
},
|
},
|
||||||
onHide: function() {
|
onHide: function() {
|
||||||
console.log('App Hide')
|
console.log('App Hide')
|
||||||
|
|
@ -102,31 +102,38 @@
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 启动轮询支付状态:回到小程序立马查一次,失败则每隔 3 秒再查,最多再查 3 次(共 4 次)
|
// 启动轮询支付状态
|
||||||
startOrderStatusPolling(orderNumber) {
|
startOrderStatusPolling(orderNumber) {
|
||||||
|
// 避免重复轮询
|
||||||
if (this._orderStatusTimer) {
|
if (this._orderStatusTimer) {
|
||||||
clearInterval(this._orderStatusTimer);
|
clearInterval(this._orderStatusTimer);
|
||||||
this._orderStatusTimer = null;
|
this._orderStatusTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let times = 0;
|
let times = 0;
|
||||||
const maxTimes = 4; // 立即 1 次 + 最多再查 3 次
|
const maxTimes = 5; // 最多轮询 20 次,大约 1 分钟
|
||||||
|
|
||||||
const doCheck = async () => {
|
this._orderStatusTimer = setInterval(async () => {
|
||||||
times++;
|
times++;
|
||||||
try {
|
try {
|
||||||
const res = await updateLuOrderPayStatus({ orderNumber });
|
const res = await updateLuOrderPayStatus({ orderNumber });
|
||||||
|
// 约定:接口有返回数据即认为支付成功
|
||||||
if (res) {
|
if (res) {
|
||||||
clearInterval(this._orderStatusTimer);
|
clearInterval(this._orderStatusTimer);
|
||||||
this._orderStatusTimer = null;
|
this._orderStatusTimer = null;
|
||||||
|
// 成功后清理本地缓存的订单号
|
||||||
uni.removeStorageSync("lastOrderNumber");
|
uni.removeStorageSync("lastOrderNumber");
|
||||||
uni.showToast({ title: '支付成功', icon: 'success' });
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '支付成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳转到服务记录页面,默认展示「待核销」tab
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/profileSub/serviceRecords?tab=pending_verification'
|
url: '/pages/profileSub/serviceRecords?tab=pending_verification'
|
||||||
});
|
});
|
||||||
return;
|
} else if (times >= maxTimes) {
|
||||||
}
|
|
||||||
if (times >= maxTimes) {
|
|
||||||
clearInterval(this._orderStatusTimer);
|
clearInterval(this._orderStatusTimer);
|
||||||
this._orderStatusTimer = null;
|
this._orderStatusTimer = null;
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|
@ -142,10 +149,7 @@
|
||||||
this._orderStatusTimer = null;
|
this._orderStatusTimer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}, 3000);
|
||||||
|
|
||||||
doCheck(); // 回到小程序立马查一次
|
|
||||||
this._orderStatusTimer = setInterval(doCheck, 3000); // 失败则每 3 秒再查,最多再查 3 次
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
api/index.js
13
api/index.js
|
|
@ -4,8 +4,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 基础URL配置(注意:末尾不要加斜杠)
|
// 基础URL配置(注意:末尾不要加斜杠)
|
||||||
const BASE_URL = 'https://guangsh.manage.hschengtai.com'
|
// const BASE_URL = 'https://guangsh.manage.hschengtai.com'
|
||||||
// const BASE_URL = 'http://192.168.5.134:48085'
|
const BASE_URL = 'http://192.168.5.134:48085'
|
||||||
// 是否正在刷新token(防止并发刷新)
|
// 是否正在刷新token(防止并发刷新)
|
||||||
let isRefreshing = false
|
let isRefreshing = false
|
||||||
// 等待刷新完成的请求队列
|
// 等待刷新完成的请求队列
|
||||||
|
|
@ -366,15 +366,12 @@ export function request(options = {}) {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 网络错误处理(真机/预览时域名未配置会报 domain 相关错误)
|
// 网络错误处理
|
||||||
let errorMsg = '网络请求失败'
|
let errorMsg = '网络请求失败'
|
||||||
if (err.errMsg) {
|
if (err.errMsg) {
|
||||||
const em = err.errMsg
|
if (err.errMsg.includes('timeout')) {
|
||||||
if (em.includes('timeout')) {
|
|
||||||
errorMsg = '请求超时,请检查网络'
|
errorMsg = '请求超时,请检查网络'
|
||||||
} else if (em.includes('domain') || em.includes('url not in')) {
|
} else if (err.errMsg.includes('fail')) {
|
||||||
errorMsg = '请在小程序后台配置服务器域名'
|
|
||||||
} else if (em.includes('fail')) {
|
|
||||||
errorMsg = '网络连接失败,请检查网络设置'
|
errorMsg = '网络连接失败,请检查网络设置'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,16 +161,11 @@ export function getMyOrderPage(params = {}){
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除订单(id 为 Query 参数,拼在 URL 上)
|
// 删除订单
|
||||||
export function deleteOrder(params = {}) {
|
export function deleteOrder(id){
|
||||||
const id = params.id
|
|
||||||
const url = id !== undefined && id !== ''
|
|
||||||
? `/app-api/member/lu-order/delete?id=${encodeURIComponent(id)}`
|
|
||||||
: '/app-api/member/lu-order/delete'
|
|
||||||
return request({
|
return request({
|
||||||
url,
|
url: '/app-api/member/lu-order/delete?id='+id,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
data: {},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
{{ item.discount }}折
|
{{ item.discount }}折
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- <text class="menu-desc">{{ item.description }}</text> -->
|
<text class="menu-desc">{{ item.description }}</text>
|
||||||
<view class="menu-price-row">
|
<view class="menu-price-row">
|
||||||
<view class="current-price">
|
<view class="current-price">
|
||||||
<view class="price-label">现价¥</view>
|
<view class="price-label">现价¥</view>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,11 @@
|
||||||
<!-- 用户资料卡片 -->
|
<!-- 用户资料卡片 -->
|
||||||
<view
|
<view
|
||||||
class="user-card"
|
class="user-card"
|
||||||
:style="{ backgroundImage: userCardBgImage }"
|
:style="{
|
||||||
|
backgroundImage: userInfo.level.backgroundUrl
|
||||||
|
? `url(${userInfo.level.backgroundUrl})`
|
||||||
|
: 'url(/static/profile/member-card-bg.png)',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<view class="user-info">
|
<view class="user-info">
|
||||||
<view class="user-level">{{ userInfo.level.name }}</view>
|
<view class="user-level">{{ userInfo.level.name }}</view>
|
||||||
|
|
@ -19,7 +23,7 @@
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:src="avatarSrc"
|
:src="userInfo.avatar || '/static/tabbar/profile.png'"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -28,7 +32,7 @@
|
||||||
<view class="avatar-wrapper" @click="handleChooseAvatar">
|
<view class="avatar-wrapper" @click="handleChooseAvatar">
|
||||||
<image
|
<image
|
||||||
class="avatar"
|
class="avatar"
|
||||||
:src="avatarSrc"
|
:src="userInfo.avatar || '/static/tabbar/profile.png'"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -39,26 +43,14 @@
|
||||||
class="avatar-hg"
|
class="avatar-hg"
|
||||||
></image>
|
></image>
|
||||||
<view class="user-details">
|
<view class="user-details">
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<text class="login-method">{{
|
||||||
<input
|
userInfo.nickname || "微信登录"
|
||||||
type="nickname"
|
}}</text>
|
||||||
class="nickname-input"
|
|
||||||
:value="userInfo.nickname || ''"
|
|
||||||
placeholder="点击设置微信昵称"
|
|
||||||
@blur="handleNicknameBlur"
|
|
||||||
/>
|
|
||||||
<!-- #endif -->
|
|
||||||
<!-- #ifndef MP-WEIXIN -->
|
|
||||||
<text
|
|
||||||
class="login-method"
|
|
||||||
@click="handleNicknameClickNonWeixin"
|
|
||||||
>{{ userInfo.nickname || "微信登录" }}</text>
|
|
||||||
<!-- #endif -->
|
|
||||||
<text class="user-id">NO.{{ userInfo.id }}</text>
|
<text class="user-id">NO.{{ userInfo.id }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="member-benefits-btn" @click="goToMemberBenefits">
|
<view class="member-benefits-btn" @click="goToMemberBenefits">
|
||||||
<image :src="memberLevelIcon" mode="aspectFill"></image>
|
<image :src="userInfo.level.icon" mode="aspectFill"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="user-notice">
|
<view class="user-notice">
|
||||||
<!-- <text class="user-notice-text">{{ noticeNum }}</text> -->
|
<!-- <text class="user-notice-text">{{ noticeNum }}</text> -->
|
||||||
|
|
@ -136,22 +128,6 @@ export default {
|
||||||
uploading: false, // 是否正在上传头像
|
uploading: false, // 是否正在上传头像
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
avatarSrc() {
|
|
||||||
const v = this.userInfo.avatar;
|
|
||||||
return (v && typeof v === "string") ? v : "/static/tabbar/profile.png";
|
|
||||||
},
|
|
||||||
memberLevelIcon() {
|
|
||||||
const icon = this.userInfo.level && this.userInfo.level.icon;
|
|
||||||
return (icon && typeof icon === "string") ? icon : "/static/tabbar/profile.png";
|
|
||||||
},
|
|
||||||
userCardBgImage() {
|
|
||||||
const url = this.userInfo.level && this.userInfo.level.backgroundUrl;
|
|
||||||
return (url && typeof url === "string")
|
|
||||||
? `url(${url})`
|
|
||||||
: "url(/static/profile/member-card-bg.png)";
|
|
||||||
},
|
|
||||||
},
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.getSystemInfo();
|
this.getSystemInfo();
|
||||||
this.updateTime();
|
this.updateTime();
|
||||||
|
|
@ -288,10 +264,12 @@ export default {
|
||||||
// 选择头像(微信小程序使用 chooseAvatar,其他平台使用 chooseImage)
|
// 选择头像(微信小程序使用 chooseAvatar,其他平台使用 chooseImage)
|
||||||
handleChooseAvatar(e) {
|
handleChooseAvatar(e) {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
|
// 微信小程序新版本使用 chooseAvatar
|
||||||
if (e.detail && e.detail.avatarUrl) {
|
if (e.detail && e.detail.avatarUrl) {
|
||||||
const avatarUrl = typeof e.detail.avatarUrl === "string" ? e.detail.avatarUrl : String(e.detail.avatarUrl || "");
|
const avatarUrl = e.detail.avatarUrl;
|
||||||
if (!avatarUrl) return;
|
// 先显示本地预览
|
||||||
this.userInfo.avatar = avatarUrl;
|
this.userInfo.avatar = avatarUrl;
|
||||||
|
// 上传头像
|
||||||
this.uploadAvatar(avatarUrl);
|
this.uploadAvatar(avatarUrl);
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
@ -304,43 +282,22 @@ export default {
|
||||||
sourceType: ["album", "camera"],
|
sourceType: ["album", "camera"],
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
const tempFilePath = res.tempFilePaths[0];
|
const tempFilePath = res.tempFilePaths[0];
|
||||||
|
// 先显示本地预览
|
||||||
this.userInfo.avatar = tempFilePath;
|
this.userInfo.avatar = tempFilePath;
|
||||||
|
// 上传头像
|
||||||
this.uploadAvatar(tempFilePath);
|
this.uploadAvatar(tempFilePath);
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.error("选择图片失败:", err);
|
console.error("选择图片失败:", err);
|
||||||
uni.showToast({ title: "选择图片失败", icon: "none" });
|
uni.showToast({
|
||||||
|
title: "选择图片失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
// 微信内:昵称输入框失焦时保存昵称(input type="nickname" 会弹出微信昵称选项)
|
|
||||||
handleNicknameBlur(e) {
|
|
||||||
const nickname = (e.detail && e.detail.value) ? String(e.detail.value).trim() : "";
|
|
||||||
if (nickname) {
|
|
||||||
this.userInfo.nickname = nickname;
|
|
||||||
uni.setStorageSync("userInfo", this.userInfo);
|
|
||||||
this.updateUserNickname(nickname);
|
|
||||||
uni.showToast({ title: "昵称已更新", icon: "success" });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 非微信环境点击昵称提示
|
|
||||||
handleNicknameClickNonWeixin() {
|
|
||||||
uni.showToast({
|
|
||||||
title: "请在微信中打开以修改昵称",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 同步昵称到后端(若后端有更新接口可在此调用)
|
|
||||||
async updateUserNickname(nickname) {
|
|
||||||
try {
|
|
||||||
// 若有更新用户信息接口可在此调用,例如:await updateUserInfo({ nickname });
|
|
||||||
} catch (err) {
|
|
||||||
console.error("更新昵称失败:", err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 上传头像
|
// 上传头像
|
||||||
uploadAvatar(filePath) {
|
uploadAvatar(filePath) {
|
||||||
if (this.uploading) {
|
if (this.uploading) {
|
||||||
|
|
@ -408,10 +365,11 @@ export default {
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
console.error("上传头像失败:", err);
|
console.error("上传头像失败:", err);
|
||||||
const msg = (err && err.errMsg && err.errMsg.indexOf("ENOENT") !== -1)
|
uni.showToast({
|
||||||
? "模拟器暂不支持更换头像,请使用真机预览"
|
title: "上传失败,请检查网络",
|
||||||
: "上传失败,请检查网络";
|
icon: "none",
|
||||||
uni.showToast({ title: msg, icon: "none", duration: 2500 });
|
});
|
||||||
|
// 上传失败,恢复原头像
|
||||||
this.loadUserInfo();
|
this.loadUserInfo();
|
||||||
},
|
},
|
||||||
complete: () => {
|
complete: () => {
|
||||||
|
|
@ -543,19 +501,6 @@ export default {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nickname-input {
|
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #333333;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
height: 44rpx;
|
|
||||||
line-height: 44rpx;
|
|
||||||
background: transparent;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-id {
|
.user-id {
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
font-family: PingFang-SC, PingFang-SC;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
|
||||||
|
|
@ -90,37 +90,20 @@
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
<view class="goods-info">
|
<view class="goods-info">
|
||||||
<text class="goods-title">{{
|
<text class="goods-title">{{ goods.couponName || goods.name }}</text>
|
||||||
goods.couponName || goods.name
|
|
||||||
}}</text>
|
|
||||||
<!-- <text class="goods-subtitle">
|
<!-- <text class="goods-subtitle">
|
||||||
订单号:{{ item.orderNumber }}
|
订单号:{{ item.orderNumber }}
|
||||||
</text> -->
|
</text> -->
|
||||||
<view class="goods-meta-row">
|
<view class="goods-meta-row">
|
||||||
<text class="goods-price"
|
<text class="goods-price">¥{{ formatFen(goods.salePrice) }}</text>
|
||||||
>¥{{ formatFen(goods.salePrice) }}</text
|
|
||||||
>
|
|
||||||
<text
|
<text
|
||||||
class="goods-count"
|
class="goods-count"
|
||||||
v-if="
|
v-if="(goods.num || goods.count || goods.quantity || goods.qty) > 1"
|
||||||
(goods.num || goods.count || goods.quantity || goods.qty) >
|
|
||||||
1
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
×{{ goods.num || goods.count || goods.quantity || goods.qty }}
|
×{{ goods.num || goods.count || goods.quantity || goods.qty }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view
|
|
||||||
class="qr-code-icon-wrapper"
|
|
||||||
@click.stop="handleQrCode(item, goods)"
|
|
||||||
>
|
|
||||||
<image
|
|
||||||
src="/static/home/qr_code_icon.png"
|
|
||||||
mode="aspectFill"
|
|
||||||
class="qr-code-icon"
|
|
||||||
></image>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
@ -128,9 +111,7 @@
|
||||||
<view class="record-footer">
|
<view class="record-footer">
|
||||||
<view class="total-info">
|
<view class="total-info">
|
||||||
<text class="total-label">实付款:</text>
|
<text class="total-label">实付款:</text>
|
||||||
<text class="total-amount"
|
<text class="total-amount">¥{{ formatFen(item.payableAmount) }}</text>
|
||||||
>¥{{ formatFen(item.payableAmount) }}</text
|
|
||||||
>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 操作按钮区域 -->
|
<!-- 操作按钮区域 -->
|
||||||
|
|
@ -170,7 +151,7 @@
|
||||||
<view class="record-actions" v-else-if="item.status === 4">
|
<view class="record-actions" v-else-if="item.status === 4">
|
||||||
<button
|
<button
|
||||||
class="action-btn detail-btn"
|
class="action-btn detail-btn"
|
||||||
@click.stop="handleDelete(item)"
|
@click.stop="handleViewDetail(item)"
|
||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -185,44 +166,12 @@
|
||||||
<text v-else class="load-more-text">上拉加载更多</text>
|
<text v-else class="load-more-text">上拉加载更多</text>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 券码二维码弹窗 -->
|
|
||||||
<view
|
|
||||||
class="qr-modal-mask"
|
|
||||||
v-if="qrModalVisible"
|
|
||||||
@click="closeQrModal"
|
|
||||||
></view>
|
|
||||||
<view class="qr-modal-wrap" v-if="qrModalVisible">
|
|
||||||
<view class="qr-modal" @click.stop>
|
|
||||||
<view class="qr-modal-header">
|
|
||||||
<text class="qr-modal-title">核销码</text>
|
|
||||||
<view
|
|
||||||
class="qr-modal-status"
|
|
||||||
:class="getQrUseStatusClass(qrModalData.useStatus)"
|
|
||||||
>
|
|
||||||
{{ getQrUseStatusText(qrModalData.useStatus) }}
|
|
||||||
</view>
|
|
||||||
<view class="qr-modal-close" @click="closeQrModal">×</view>
|
|
||||||
</view>
|
|
||||||
<view class="qr-modal-body">
|
|
||||||
<view class="qr-code-box" v-if="qrModalData.couponCode">
|
|
||||||
<image
|
|
||||||
class="qr-code-image"
|
|
||||||
:src="qrCodeImageUrl"
|
|
||||||
mode="aspectFit"
|
|
||||||
></image>
|
|
||||||
<!-- <text class="qr-code-text">{{ qrModalData.couponCode }}</text> -->
|
|
||||||
</view>
|
|
||||||
<text v-else class="qr-code-empty">暂无券码</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
||||||
import { getLuMyOrderPage, cancelOrder, getPaySign,deleteOrder } from "@/api/service";
|
import { getLuMyOrderPage, cancelOrder, getPaySign } from "@/api/service";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -244,22 +193,12 @@ export default {
|
||||||
completed: [],
|
completed: [],
|
||||||
cancelled: [],
|
cancelled: [],
|
||||||
},
|
},
|
||||||
qrModalVisible: false,
|
|
||||||
qrModalData: {
|
|
||||||
useStatus: 0,
|
|
||||||
couponCode: "",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentList() {
|
currentList() {
|
||||||
return this.recordsMap[this.currentTab] || [];
|
return this.recordsMap[this.currentTab] || [];
|
||||||
},
|
},
|
||||||
qrCodeImageUrl() {
|
|
||||||
const code = this.qrModalData.couponCode || "";
|
|
||||||
if (!code) return "";
|
|
||||||
return `https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(code)}`;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
// 如果通过参数传入 tab,优先使用传入的 tab 值
|
// 如果通过参数传入 tab,优先使用传入的 tab 值
|
||||||
|
|
@ -299,7 +238,7 @@ export default {
|
||||||
getStatusValue() {
|
getStatusValue() {
|
||||||
const map = {
|
const map = {
|
||||||
pending_payment: 0, // 待支付
|
pending_payment: 0, // 待支付
|
||||||
pending_verification: 1, // 已完成
|
pending_verification: 1, // 已完成
|
||||||
chargeback: 3, // 已退款
|
chargeback: 3, // 已退款
|
||||||
cancelled: 4, // 已取消
|
cancelled: 4, // 已取消
|
||||||
};
|
};
|
||||||
|
|
@ -347,7 +286,7 @@ export default {
|
||||||
? "status-cancelled"
|
? "status-cancelled"
|
||||||
: "";
|
: "";
|
||||||
},
|
},
|
||||||
// 加载数据(真机/预览无数据时请检查:1. 小程序后台「服务器域名」已配置接口域名 2. 真机已登录)
|
// 加载数据
|
||||||
async loadData(append = false) {
|
async loadData(append = false) {
|
||||||
if (this.loading) return;
|
if (this.loading) return;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
@ -358,13 +297,7 @@ export default {
|
||||||
pageSize: this.pageSize,
|
pageSize: this.pageSize,
|
||||||
status,
|
status,
|
||||||
});
|
});
|
||||||
// 兼容多种后端返回结构:list / records / data.list
|
const list = res.list || [];
|
||||||
const rawList =
|
|
||||||
res.list ||
|
|
||||||
res.records ||
|
|
||||||
(res.data && (res.data.list || res.data.records)) ||
|
|
||||||
[];
|
|
||||||
const list = Array.isArray(rawList) ? rawList : [];
|
|
||||||
|
|
||||||
const currentList = this.recordsMap[this.currentTab] || [];
|
const currentList = this.recordsMap[this.currentTab] || [];
|
||||||
this.recordsMap = {
|
this.recordsMap = {
|
||||||
|
|
@ -375,12 +308,10 @@ export default {
|
||||||
// 是否还有更多
|
// 是否还有更多
|
||||||
this.hasMore = list.length >= this.pageSize;
|
this.hasMore = list.length >= this.pageSize;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = (e && e.message) ? String(e.message) : "";
|
|
||||||
console.error("加载服务记录失败:", e);
|
console.error("加载服务记录失败:", e);
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: msg ? `加载失败:${msg}` : "加载服务记录失败",
|
title: "加载服务记录失败",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
duration: 2500,
|
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
@ -430,27 +361,6 @@ export default {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 删除订单
|
|
||||||
handleDelete(item) {
|
|
||||||
uni.showModal({
|
|
||||||
title: "提示",
|
|
||||||
content: "确定要删除该订单吗?",
|
|
||||||
success: async (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
const resData = await deleteOrder({
|
|
||||||
id: item.id,
|
|
||||||
});
|
|
||||||
if (resData) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "订单已删除",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 立即支付(与店铺详情页 handlePay 逻辑一致,跳转收银台小程序)
|
// 立即支付(与店铺详情页 handlePay 逻辑一致,跳转收银台小程序)
|
||||||
async handlePay(item) {
|
async handlePay(item) {
|
||||||
if (!item || !item.orderNumber) {
|
if (!item || !item.orderNumber) {
|
||||||
|
|
@ -538,33 +448,6 @@ export default {
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 点击二维码图标:打开弹窗,展示券状态 + 根据 couponCode 生成二维码
|
|
||||||
handleQrCode(item, goods) {
|
|
||||||
const useStatus = goods?.useStatus ?? item?.useStatus ?? 0;
|
|
||||||
const couponCode =
|
|
||||||
(goods && (goods.couponCode || goods.couponNo)) ||
|
|
||||||
item?.couponCode ||
|
|
||||||
item?.couponNo ||
|
|
||||||
"";
|
|
||||||
this.qrModalData = { useStatus, couponCode };
|
|
||||||
this.qrModalVisible = true;
|
|
||||||
},
|
|
||||||
getQrUseStatusText(useStatus) {
|
|
||||||
const map = { 0: "未使用", 1: "已使用", 3: "已退款", 4: "已取消" };
|
|
||||||
return map[useStatus] ?? "未使用";
|
|
||||||
},
|
|
||||||
getQrUseStatusClass(useStatus) {
|
|
||||||
const map = {
|
|
||||||
0: "status-unused",
|
|
||||||
1: "status-used",
|
|
||||||
3: "status-refund",
|
|
||||||
4: "status-cancelled",
|
|
||||||
};
|
|
||||||
return map[useStatus] ?? "status-unused";
|
|
||||||
},
|
|
||||||
closeQrModal() {
|
|
||||||
this.qrModalVisible = false;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -834,16 +717,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.qr-code-icon-wrapper {
|
|
||||||
flex-shrink: 0;
|
|
||||||
padding: 12rpx;
|
|
||||||
margin-left: 8rpx;
|
|
||||||
}
|
|
||||||
.qr-code-icon {
|
|
||||||
width: 44rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -914,122 +787,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 券码二维码弹窗 */
|
|
||||||
.qr-modal-mask {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
z-index: 900;
|
|
||||||
}
|
|
||||||
.qr-modal-wrap {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 901;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 36rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.qr-modal {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 720rpx;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 28rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
.qr-modal-header {
|
|
||||||
position: relative;
|
|
||||||
padding: 40rpx 32rpx 28rpx;
|
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 16rpx;
|
|
||||||
}
|
|
||||||
.qr-modal-title {
|
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 36rpx;
|
|
||||||
color: #1a1819;
|
|
||||||
}
|
|
||||||
.qr-modal-status {
|
|
||||||
padding: 8rpx 20rpx;
|
|
||||||
border-radius: 24rpx;
|
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 24rpx;
|
|
||||||
&.status-unused {
|
|
||||||
background: rgba(0, 66, 148, 0.1);
|
|
||||||
color: #004294;
|
|
||||||
}
|
|
||||||
&.status-used {
|
|
||||||
background: rgba(158, 158, 158, 0.15);
|
|
||||||
color: #9e9e9e;
|
|
||||||
}
|
|
||||||
&.status-refund {
|
|
||||||
background: rgba(76, 175, 80, 0.1);
|
|
||||||
color: #4caf50;
|
|
||||||
}
|
|
||||||
&.status-cancelled {
|
|
||||||
background: rgba(158, 158, 158, 0.15);
|
|
||||||
color: #9e9e9e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.qr-modal-close {
|
|
||||||
position: absolute;
|
|
||||||
right: 20rpx;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
width: 56rpx;
|
|
||||||
height: 56rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 44rpx;
|
|
||||||
color: #999999;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
.qr-modal-body {
|
|
||||||
padding: 48rpx 32rpx 56rpx;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.qr-code-box {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.qr-code-image {
|
|
||||||
width: 520rpx;
|
|
||||||
height: 520rpx;
|
|
||||||
background: #fff;
|
|
||||||
border: 2rpx solid #e8e8e8;
|
|
||||||
border-radius: 20rpx;
|
|
||||||
margin-bottom: 28rpx;
|
|
||||||
}
|
|
||||||
.qr-code-text {
|
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 26rpx;
|
|
||||||
color: #333333;
|
|
||||||
word-break: break-all;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 20rpx;
|
|
||||||
}
|
|
||||||
.qr-code-empty {
|
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #999999;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.4 KiB |
Loading…
Reference in New Issue