Compare commits
18 Commits
41f6f612fa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6deef6cdce | |||
| e894689918 | |||
| 26e57e4891 | |||
| 32fa3e9bd2 | |||
| 4002f91a54 | |||
| a2fadc57b8 | |||
| b251c899ca | |||
| cdf0bc5a01 | |||
| 7a490f0ffc | |||
| 34148c6084 | |||
| 9b6b76f747 | |||
| 6ea50b824f | |||
| 72e481c6c5 | |||
| 124beb0666 | |||
| 078e0bc8ab | |||
| 1739401cb8 | |||
| 3afa2e8c10 | |||
| 7d1083bf5c |
@ -2,7 +2,7 @@ import request from "../utils/request";
|
||||
import { LOGIN, GET_PHONE, USER_SHARE,USER_WALLET,RECHARGE_WALLET,USER_WXPAY,USER_TRANSACTION,USER_ADDITIONAL,MEMBER_TYPES,
|
||||
USER_RECHARGE,USER_REDEEM,USER_HolderList,USER_MEMBERSHIP,USER_BINDPETS,USER_PETBINDING,USER_DISCOUNTFEE,USER_COUPONLIST,CANCEL_PET_ORDER,
|
||||
GET_VIP_PRICE,POINTS_RECHARGE_LIST,POINTS_DONATE,POINTS_RECORDS,POINTS_RANK,OSS_STS,DONATION_SUMMARY,
|
||||
USER_DISPATCHFEE,CANCEL_MALL_ORDER,DOUY_REVIEW
|
||||
USER_DISPATCHFEE,CANCEL_MALL_ORDER,DOUY_REVIEW,CANCEL_NOMO_ORDER,LOGIN_PHONE
|
||||
} from "./url";
|
||||
// 微信登陆
|
||||
export const getCodeByWxLogin = () => {
|
||||
@ -10,7 +10,7 @@ export const getCodeByWxLogin = () => {
|
||||
tt.login({
|
||||
provider: "toutiao",
|
||||
success: function (loginRes) {
|
||||
// console.log(loginRes,'?1?')
|
||||
console.log(loginRes,'?1?')
|
||||
resolve(loginRes.code);
|
||||
},
|
||||
fail: function (err) {
|
||||
@ -23,7 +23,7 @@ export const getCodeByWxLogin = () => {
|
||||
import Store from "../store";
|
||||
|
||||
// 登录鉴权
|
||||
export const login = (nickName, avatarUrl) => {
|
||||
export const login = ( phone) => {
|
||||
return getCodeByWxLogin().then((code) => {
|
||||
// 从 vuex 中获取 referrerID(如果通过二维码扫描进入)
|
||||
const referrerID = Store.state.user?.referrerID || 0;
|
||||
@ -32,17 +32,11 @@ export const login = (nickName, avatarUrl) => {
|
||||
url: LOGIN,
|
||||
method: "POST",
|
||||
data: {
|
||||
nickName:nickName,
|
||||
avatarUrl:avatarUrl,
|
||||
code: code,
|
||||
phone: phone || null,
|
||||
source: 'douyin',
|
||||
referrerID: 0,
|
||||
referrerType: 'douyin'
|
||||
// // yaoqing_code: inviteCode || null,
|
||||
// phone: phone || null,
|
||||
// source: "wechat",
|
||||
// referrerID: Number(referrerID) || 0,
|
||||
// referrerType: "wechat"
|
||||
},
|
||||
}).then((res) => {
|
||||
// 登录接口使用完 referrerID 后,清除一次,避免重复使用
|
||||
@ -54,12 +48,13 @@ export const login = (nickName, avatarUrl) => {
|
||||
});
|
||||
};
|
||||
// 获取手机号
|
||||
export const getPhone = (code) => {
|
||||
export const getPhone = (phoneCode, loginCode) => {
|
||||
return request({
|
||||
url: GET_PHONE,
|
||||
method: "POST",
|
||||
data: {
|
||||
code: code
|
||||
code: phoneCode,
|
||||
loginCode: loginCode
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -74,6 +69,18 @@ export const userShare = (id) => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const login_phone = (phone) => {
|
||||
return request({
|
||||
url: LOGIN_PHONE,
|
||||
method: "POST",
|
||||
data: {
|
||||
phone
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 用户钱包
|
||||
export const userWllet = (id) => {
|
||||
return request({
|
||||
@ -164,10 +171,11 @@ export const getDonationSummary = () => {
|
||||
};
|
||||
|
||||
// 抖音审核
|
||||
export const getdouyReview = () => {
|
||||
export const getdouyReview = (data) => {
|
||||
return request({
|
||||
url: DOUY_REVIEW,
|
||||
method: "GET"
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
@ -225,6 +233,15 @@ export const cancelPetOrderMall = (data) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 未支付取消商城订单
|
||||
export const cancelUnpaid = (data) => {
|
||||
return request({
|
||||
url: CANCEL_NOMO_ORDER,
|
||||
method: "POST",
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 绑定宠物列表
|
||||
export const bindPets = (data) => {
|
||||
return request({
|
||||
|
||||
@ -115,12 +115,12 @@ export const updateCartSelect = ({ is_select,cart_id }) => {
|
||||
};
|
||||
|
||||
// 删除购物车
|
||||
export const deleteCart = ({ cart_id }) => {
|
||||
export const deleteCart = ({ id }) => {
|
||||
return request({
|
||||
url: DELETE_CART,
|
||||
method: "post",
|
||||
data: {
|
||||
cart_id,
|
||||
id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -56,8 +56,13 @@ export const CANCEL_PET_ORDER = '/order/pet/cancel'
|
||||
// 抖音审核接口
|
||||
export const DOUY_REVIEW = '/douyin/goods/order/appointment'
|
||||
|
||||
// 抖音未支付订单取消接口
|
||||
export const CANCEL_NOMO_ORDER = '/douyin/goods/order/cancel'
|
||||
|
||||
export const LOGIN_PHONE = '/api/v1/auth/login'
|
||||
|
||||
// 取消商城接口
|
||||
export const CANCEL_MALL_ORDER = '/douyin/goods/order/cancel'
|
||||
export const CANCEL_MALL_ORDER = '/douyin/goods/order/refund'
|
||||
|
||||
// 卡包列表接口
|
||||
export const USER_HolderList = '/membership/instances'
|
||||
@ -198,7 +203,7 @@ export const GET_GOODS_CATEGORY = "/product/type/list";
|
||||
// 商品列表
|
||||
export const GET_GOODS_LIST = "/douyin/goods/product/online/query";
|
||||
// 商品详情
|
||||
export const GET_GOODS_DETAIL = "/product/detail";
|
||||
export const GET_GOODS_DETAIL = "/douyin/goods/product/detail";
|
||||
|
||||
// 获取优惠券列表
|
||||
export const GET_COUPON_LIST = "/app/coupon/coupon_list";
|
||||
@ -227,7 +232,7 @@ export const UPDATE_CART_NUM = "/cart/update";
|
||||
// 选择购物车商品
|
||||
export const UPDATE_CART_SELECT = "/cart/select/all";
|
||||
// 删除购物车
|
||||
export const DELETE_CART = "/product/cart/delete";
|
||||
export const DELETE_CART = "/douyin/goods/order/refund";
|
||||
|
||||
// 创建订单
|
||||
export const CREATE_ORDER_NEW = "/product/order/create";
|
||||
@ -238,7 +243,7 @@ export const PAY_ORDER_NEW = "/ttpay/jsapi";
|
||||
// 订单列表
|
||||
export const SHOP_ORDER_LIST = "/douyin/goods/order/list";
|
||||
// 订单详情
|
||||
export const SHOP_ORDER_DETAILS = "/product/order/show";
|
||||
export const SHOP_ORDER_DETAILS = "/douyin/goods/order/show";
|
||||
// 取消订单
|
||||
export const SHOP_ORDER_CANCEL = '/app/order/order_quxiao'
|
||||
// 提醒发货
|
||||
|
||||
@ -3,8 +3,8 @@ export default {
|
||||
appName: "Wagoo",
|
||||
appShareName: "Wagoo",
|
||||
appId: "wx00e2dcdc7c02b23a",
|
||||
apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址
|
||||
// apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
|
||||
// apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址
|
||||
apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
|
||||
// apiBaseUrl: "http:192.168.30.79", //本地接口
|
||||
tencentMapKey: "WSBBZ-7OXK4-46QUC-KFB7B-4N3W7-M2BXM",
|
||||
tencentSecret: "vb7D0PGj7xUvmOLuJz2Jd7ykTMpjiWRJ",
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="payBtn" @click.stop="writeOff">
|
||||
核销
|
||||
预约
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -147,6 +147,12 @@ export default {
|
||||
components: {
|
||||
InfoCell,
|
||||
},
|
||||
props: {
|
||||
orderId: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgPrefix,
|
||||
@ -156,7 +162,7 @@ export default {
|
||||
ORDER_TYPE_RESERVATION,
|
||||
ORDER_TYPE_SITE,
|
||||
orderType: ORDER_TYPE_RESERVATION,
|
||||
selectedPetType: PET_TYPE_CAT, // 默认选中“猫”
|
||||
selectedPetType: PET_TYPE_CAT, // 默认选中"猫"
|
||||
petInfo: {}, // 兼容下游,取 selectedPets[0]
|
||||
selectedPets: [], // 多选宠物列表
|
||||
parkState: "",
|
||||
@ -168,11 +174,24 @@ export default {
|
||||
address: null,
|
||||
catHtmlData: "",
|
||||
dogHtmlData: "",
|
||||
tip: ''
|
||||
tip: '',
|
||||
localOrderId: null, // 本地存储的 orderId
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initData();
|
||||
// 如果有传入的 orderId,保存到本地
|
||||
if (this.orderId) {
|
||||
this.localOrderId = this.orderId;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听 orderId 变化
|
||||
orderId(newVal) {
|
||||
if (newVal) {
|
||||
this.localOrderId = newVal;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 展示价格:discount_price 数组相加的总和
|
||||
@ -186,25 +205,86 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 用于接收从父页面传递的数据
|
||||
onShowFun(orderId) {
|
||||
if (orderId) {
|
||||
this.localOrderId = orderId;
|
||||
}
|
||||
},
|
||||
// 核销按钮点击处理
|
||||
async writeOff () {
|
||||
// 校验必填项
|
||||
if (Object.keys(this.reservationTime).length === 0) {
|
||||
uni.showToast({
|
||||
title: "请选择预约时间",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!this.address) {
|
||||
uni.showToast({
|
||||
title: "请选择服务地址",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!this.parkState) {
|
||||
uni.showToast({
|
||||
title: "请选择停车状况",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!this.localOrderId) {
|
||||
uni.showToast({
|
||||
title: "订单ID缺失",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
goods_order_id:1, //抖音商品订单id(整数)
|
||||
order_date:'2026-03-01', //预约日期(‘2026-03-01’格式)
|
||||
period_id:1, //预约时间段id(整数)
|
||||
address_id:1, //地址id(整数)
|
||||
recipient_name:'用户姓名', //用户姓名
|
||||
phone:123, //用户手机
|
||||
park_desc:123, //停车描述
|
||||
note:'哈哈' // 备注
|
||||
goods_order_id: Number(this.localOrderId), //抖音商品订单id(整数)
|
||||
order_date: this.reservationTime.date, //预约日期('2026-03-01'格式)
|
||||
period_id: Number(this.reservationTime.id), //预约时间段id(整数)
|
||||
address_id: Number(this.address.id), //地址id(整数)
|
||||
recipient_name: this.address.name || '用户姓名', //用户姓名
|
||||
phone: this.address.phone || '', //用户手机
|
||||
park_desc: this.parkState || '', //停车描述
|
||||
note: this.otherParkState || '' // 备注
|
||||
};
|
||||
|
||||
uni.showLoading({
|
||||
title: "处理中",
|
||||
mask: true,
|
||||
});
|
||||
|
||||
getdouyReview(data).then((res) => {
|
||||
uni.hideLoading();
|
||||
if (res.code == 0) {
|
||||
uni.showToast({
|
||||
title: "预约成功",
|
||||
icon: "none",
|
||||
});
|
||||
// 预约成功后清空数据并跳转
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: "/pages/client/index/index?activePageId=homePage",
|
||||
});
|
||||
}, 1500);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg || "预约失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
console.error("预约失败:", err);
|
||||
uni.showToast({
|
||||
title: "预约失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@ -322,7 +322,7 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "商城订单",
|
||||
"usingComponents": {
|
||||
"pay-button-sdk": "tta5a3d31e3aecfb9b11://pay-button"
|
||||
"pay-button": "tta5a3d31e3aecfb9b11://pay-button"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,17 +1,28 @@
|
||||
<template>
|
||||
<view class="loginContainer">
|
||||
<view class="body">
|
||||
<image class="login-ground-img" :src="`${imgPrefix}loginGroundImg.png`" mode="widthFix" />
|
||||
<image
|
||||
class="login-ground-img"
|
||||
:src="`${imgPrefix}loginGroundImg.png`"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<view class="btnConent">
|
||||
<button v-show="!checked" class="loginBtn" @click="unCheckAndGetPhoneNumber">
|
||||
<button
|
||||
v-show="!checked"
|
||||
class="loginBtn"
|
||||
@click="unCheckAndGetPhoneNumber"
|
||||
>
|
||||
抖音用户信息授权登录
|
||||
</button>
|
||||
<button v-show="checked" class="loginBtn" @tap="getPhoneNumber" >
|
||||
<button
|
||||
v-show="checked"
|
||||
class="loginBtn"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
>
|
||||
抖音用户信息授权登录
|
||||
</button>
|
||||
<view class="notLoginBtn" @click="goBack">
|
||||
暂不登录
|
||||
</view>
|
||||
<view class="notLoginBtn" @click="goBack"> 暂不登录 </view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -19,7 +30,11 @@
|
||||
<view class="radioWrapper">
|
||||
<view class="checkbox-wrapper" @click.stop="changeChecked">
|
||||
<view class="checkbox" :class="{ 'checkbox-checked': checked }">
|
||||
<image v-if="checked" class="check-icon" :src="require('@/static/images/y.png')" />
|
||||
<image
|
||||
v-if="checked"
|
||||
class="check-icon"
|
||||
:src="require('@/static/images/y.png')"
|
||||
/>
|
||||
</view>
|
||||
<!-- <view v-if="uncheckMessageDialog" class="tooltip">
|
||||
<view class="tooltip-content">请先勾选,同意后再进行登录</view>
|
||||
@ -28,7 +43,9 @@
|
||||
</view>
|
||||
<text class="radioText">
|
||||
请阅读并同意
|
||||
<text class="color" @click.stop="ptfwxy">《帮宠到家平台服务协议》</text>
|
||||
<text class="color" @click.stop="ptfwxy"
|
||||
>《帮宠到家平台服务协议》</text
|
||||
>
|
||||
<text class="color" @click.stop="ysxy">《隐私协议》</text>
|
||||
</text>
|
||||
</view>
|
||||
@ -54,6 +71,16 @@ export default {
|
||||
},
|
||||
onLoad(options) {
|
||||
this.yaoqing_code = options.yaoqing_code
|
||||
tt.login({
|
||||
provider: "toutiao",
|
||||
success: function (loginRes) {
|
||||
|
||||
console.log('获取 login code 成功:', loginRes);
|
||||
},
|
||||
fail: function (err) {
|
||||
console.log('获取 login code 失败:', err);
|
||||
},
|
||||
});
|
||||
},
|
||||
mounted() { },
|
||||
methods: {
|
||||
@ -81,14 +108,14 @@ export default {
|
||||
duration: 2000
|
||||
});
|
||||
},
|
||||
getmembeInfo(nickName,avatarUrl) {
|
||||
getmembeInfo(phone) {
|
||||
const inviteCode = this.yaoqing_code ? this.yaoqing_code : getApp().globalData.inviteCode
|
||||
uni.showLoading({
|
||||
title: "登录中...",
|
||||
icon: "none",
|
||||
mask: true,
|
||||
});
|
||||
login(nickName,avatarUrl).then((res) => {
|
||||
login(phone).then((res) => {
|
||||
uni.hideLoading()
|
||||
this.$store.dispatch("user/setToken", res?.data?.token || "");
|
||||
this.$store.dispatch("user/setUserInfo", res?.data || {});
|
||||
@ -143,77 +170,128 @@ export default {
|
||||
// });
|
||||
// }),
|
||||
async getPhoneNumber(e) {
|
||||
// console.log(e,'?')
|
||||
// return
|
||||
// 检查是否有 code
|
||||
// if (!e.detail.code) {
|
||||
console.log('获取手机号事件:', e);
|
||||
this.getmembeInfo(e.detail.code)
|
||||
|
||||
// // 检查是否有 code
|
||||
// if (!e.detail || !e.detail.code) {
|
||||
// uni.showToast({
|
||||
// title: "获取手机号失败,请重试",
|
||||
// title: "用户取消授权或获取手机号失败",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// uni.showLoading({
|
||||
// title: "获取手机号中...",
|
||||
// title: "登录中...",
|
||||
// icon: "none",
|
||||
// mask: true,
|
||||
// });
|
||||
|
||||
try {
|
||||
let that = this
|
||||
tt.getUserProfile({
|
||||
// try {
|
||||
// const that = this;
|
||||
// let loginCode = null;
|
||||
|
||||
success(res) {
|
||||
console.log(res,'???')
|
||||
// this.nickName = res.res.userInfo.nickName
|
||||
// this.avatarUrl = res.userInfo.avatarUrl
|
||||
that.getmembeInfo(res.userInfo.nickName,res.userInfo.avatarUrl)
|
||||
// console.log(res,'--=')
|
||||
},
|
||||
fail(res) {
|
||||
console.log("getUserProfile 调用失败", res);
|
||||
},
|
||||
// // 先获取 login code
|
||||
// try {
|
||||
// loginCode = await new Promise((resolve, reject) => {
|
||||
// tt.login({
|
||||
// provider: "toutiao",
|
||||
// success: function (loginRes) {
|
||||
// console.log('获取 login code 成功:', loginRes);
|
||||
// resolve(loginRes.code);
|
||||
// },
|
||||
// fail: function (err) {
|
||||
// console.log('获取 login code 失败:', err);
|
||||
// reject(err);
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// } catch (loginErr) {
|
||||
// throw new Error('获取登录凭证失败');
|
||||
// }
|
||||
|
||||
});
|
||||
|
||||
|
||||
// const inviteCode = this.yaoqing_code ? this.yaoqing_code : getApp().globalData.inviteCode
|
||||
// console.log('获取到邀请码----->', inviteCode)
|
||||
// 手机号登录
|
||||
|
||||
// 拿着code获取手机号
|
||||
// const codeRes = await getPhone(e.detail.code);
|
||||
// const phone = codeRes?.data?.phoneNumber || "";
|
||||
// // 拿着 phone code 和 login code 获取手机号
|
||||
// let phone = null;
|
||||
// try {
|
||||
// const codeRes = await getPhone(e.detail.code, loginCode);
|
||||
// phone = codeRes?.data?.phoneNumber || "";
|
||||
// console.log('获取手机号成功:', phone);
|
||||
// } catch (phoneErr) {
|
||||
// console.error('获取手机号失败:', phoneErr);
|
||||
// throw new Error('获取手机号失败');
|
||||
// }
|
||||
|
||||
// if (!phone) {
|
||||
// throw new Error('获取手机号失败,请重试');
|
||||
// }
|
||||
|
||||
// 获取用户信息
|
||||
// tt.getUserProfile({
|
||||
// success: async (profileRes) => {
|
||||
// console.log('获取用户信息成功:', profileRes);
|
||||
// const nickName = profileRes.userInfo?.nickName || '';
|
||||
// const avatarUrl = profileRes.userInfo?.avatarUrl || '';
|
||||
|
||||
// try {
|
||||
// const inviteCode = that.yaoqing_code ? that.yaoqing_code : getApp().globalData.inviteCode;
|
||||
|
||||
// // 登录
|
||||
// const loginRes = await login(nickName, avatarUrl, phone);
|
||||
// uni.hideLoading();
|
||||
// uni.showToast({
|
||||
// title: "获取手机号失败,请重试",
|
||||
// icon: "none",
|
||||
|
||||
// that.$store.dispatch("user/setToken", loginRes?.data?.token || "");
|
||||
// that.$store.dispatch("user/setUserInfo", loginRes?.data || {});
|
||||
|
||||
// var pages = getCurrentPages();
|
||||
// if (inviteCode) {
|
||||
// uni.reLaunch({
|
||||
// url: "/pages/client/index/index",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error("获取手机号失败:", error);
|
||||
// 检查是否是 access_token 相关错误
|
||||
const errorMsg = error?.message || error || "";
|
||||
if (errorMsg.includes("access_token") || errorMsg.includes("invalid credential")) {
|
||||
uni.showToast({
|
||||
title: "服务暂时不可用,请稍后重试",
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: errorMsg || "获取手机号失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (pages.length === 1) {
|
||||
// uni.reLaunch({
|
||||
// url: "/pages/client/index/index",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// uni.navigateBack();
|
||||
// } catch (loginErr) {
|
||||
// uni.hideLoading();
|
||||
// console.error('登录失败:', loginErr);
|
||||
// uni.showToast({
|
||||
// title: loginErr || "登录失败,请重试",
|
||||
// icon: "none",
|
||||
// });
|
||||
// }
|
||||
// },
|
||||
// fail: (profileErr) => {
|
||||
// uni.hideLoading();
|
||||
// console.log("getUserProfile 调用失败", profileErr);
|
||||
// uni.showToast({
|
||||
// title: "获取用户信息失败",
|
||||
// icon: "none",
|
||||
// });
|
||||
// },
|
||||
// });
|
||||
// } catch (error) {
|
||||
// uni.hideLoading();
|
||||
// console.error("获取手机号失败:", error);
|
||||
// const errorMsg = error?.message || error || "";
|
||||
// if (errorMsg.includes("access_token") || errorMsg.includes("invalid credential")) {
|
||||
// uni.showToast({
|
||||
// title: "服务暂时不可用,请稍后重试",
|
||||
// icon: "none",
|
||||
// duration: 3000,
|
||||
// });
|
||||
// } else {
|
||||
// uni.showToast({
|
||||
// title: errorMsg || "获取手机号失败,请重试",
|
||||
// icon: "none",
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
},
|
||||
loginAction() {
|
||||
if (!this.checked) {
|
||||
@ -300,8 +378,8 @@ export default {
|
||||
|
||||
.notLoginBtn {
|
||||
background-color: #fff;
|
||||
color: #FF19A0;
|
||||
border: 1rpx solid #FF19A0;
|
||||
color: #ff19a0;
|
||||
border: 1rpx solid #ff19a0;
|
||||
border-radius: 300rpx;
|
||||
padding: 26rpx 0rpx;
|
||||
text-align: center;
|
||||
@ -333,13 +411,13 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #FFFFFF;
|
||||
background: #ffffff;
|
||||
transition: all 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.checkbox-checked {
|
||||
border-color: #FF19A0;
|
||||
background: #FF19A0;
|
||||
border-color: #ff19a0;
|
||||
background: #ff19a0;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
@ -362,7 +440,7 @@ export default {
|
||||
|
||||
.tooltip-content {
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
color: #ffffff;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@ -385,7 +463,7 @@ export default {
|
||||
color: #9b939a;
|
||||
|
||||
.color {
|
||||
color: #FF19A0;
|
||||
color: #ff19a0;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,35 +1,33 @@
|
||||
<template>
|
||||
<view class="flex-row-start goods-item" @click.stop="$emit('clickCard', data)">
|
||||
<image class="goods-img" :src="data.product_pic" mode="aspectFill" />
|
||||
<view class="goods-content">
|
||||
<view class="text-multi-ellipse fs-28 app-fc-main app-font-bold goods-name">
|
||||
<view class="goods-item" >
|
||||
<image @click.stop="handleBuyNow" class="goods-img" :src="data.product_pic" mode="aspectFill" />
|
||||
<view class="fs-24 app-fc-main goods-name">
|
||||
{{ data.product_name || "" }}
|
||||
</view>
|
||||
<!-- <view class="flex-row-start label">
|
||||
<view class="flex-row-start label">
|
||||
<image class="hot-icon" :src="`${imgPrefix}mall-hot.png`"></image>
|
||||
<view class="fs-20 app-fc-main label-name">{{data.sales}}人买过</view>
|
||||
</view> -->
|
||||
<view class="price-row">
|
||||
<view class="flex-row-start">
|
||||
<text class="fs-28 price-text">
|
||||
<view class="fs-20 app-fc-main label-name">32人买过</view>
|
||||
</view>
|
||||
<view class="flex-row-between" style="margin-top: 12rpx; align-items: baseline;">
|
||||
<view class="price-wrapper">
|
||||
<text class="fs-28" style="color: #FF19A0;">
|
||||
¥
|
||||
<text class="fs-28">{{data.prices[0].original_price / 100 || 0 }}</text>
|
||||
</text>
|
||||
<!-- <text class="fs-20 price-label">到手价</text> -->
|
||||
</view>
|
||||
<text class="fs-24 origin-price" v-if="minPrice.price_shichang">
|
||||
¥{{ minPrice.price_shichang || 0 }}
|
||||
<text class="fs-28">{{
|
||||
data.prices[0].original_price / 100 || 0
|
||||
}}</text>
|
||||
</text>
|
||||
</view>
|
||||
<view class="buy-now-btn-wrapper" @click.stop="handleBuyNow">
|
||||
<text class="buy-now-btn">立即购买</text>
|
||||
<view class="buy-now-btn" @click.stop="handleBuyNow">
|
||||
立即购买
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { imgPrefix } from '@/utils/common';
|
||||
import {
|
||||
imgPrefix
|
||||
} from '@/utils/common';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -45,38 +43,22 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
imgPrefix,
|
||||
isAnimating: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// minPrice() {
|
||||
// let minPrice = {};
|
||||
// let minPriceValue = 0;
|
||||
// this.data.price_list.map((v) => {
|
||||
// if (!minPriceValue || minPriceValue > +v.price) {
|
||||
// minPriceValue = +v.price;
|
||||
// minPrice = { ...v };
|
||||
// }
|
||||
// });
|
||||
// return minPrice;
|
||||
// },
|
||||
labelList() {
|
||||
return this.data.label.split(",").filter((v) => !!v);
|
||||
return (this.data?.label || "").split(",").filter((v) => !!v);
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
// 触发添加购物车动画
|
||||
triggerAddCartAnimation() {
|
||||
this.isAnimating = true;
|
||||
setTimeout(() => {
|
||||
this.isAnimating = false;
|
||||
}, 600);
|
||||
},
|
||||
// 立即购买
|
||||
handleBuyNow() {
|
||||
this.$emit('buyNow', this.data);
|
||||
// 触发购买事件,通知父组件
|
||||
this.$emit('addToCar', this.data);
|
||||
},
|
||||
triggerAddCartAnimation() {
|
||||
// 保留方法以兼容父组件调用
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -84,28 +66,35 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
.goods-item {
|
||||
background: #fff;
|
||||
border-radius: 40rpx;
|
||||
width: 100%;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20rpx;
|
||||
margin-bottom: 22rpx;
|
||||
position: relative;
|
||||
border-bottom: 1rpx solid #F5F5F5;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.goods-img {
|
||||
border-radius: 20rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.goods-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 20rpx;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 260rpx;
|
||||
border-radius: 16rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
margin: 0 0 12rpx;
|
||||
margin: 16rpx 0 12rpx 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
font-size: 24rpx;
|
||||
color: #3D3D3D;
|
||||
}
|
||||
|
||||
.label {
|
||||
@ -113,84 +102,45 @@ export default {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 12rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
|
||||
.hot-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.label-name {
|
||||
padding: 4rpx 8rpx;
|
||||
padding-left: 4rpx;
|
||||
color: #FF19A0;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.price-row {
|
||||
margin-top: 12rpx;
|
||||
.flex-row-between {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price-text {
|
||||
color: #3D3D3D;
|
||||
}
|
||||
|
||||
.price-label {
|
||||
color: #999;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.origin-price {
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.add-cart-icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
right: 20rpx;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&.add-cart-icon-animate {
|
||||
animation: addCartBounce 0.6s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.buy-now-btn-wrapper {
|
||||
margin-top: 16rpx;
|
||||
.flex-row-start {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price-wrapper {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.buy-now-btn {
|
||||
background: linear-gradient(90deg, #FF19A0, #FF4DB8);
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
padding: 12rpx 32rpx;
|
||||
border-radius: 24rpx;
|
||||
background: #FF19A0;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 30rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes addCartBounce {
|
||||
0% {
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.2) rotate(-10deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.3) rotate(10deg);
|
||||
}
|
||||
75% {
|
||||
transform: scale(1.1) rotate(-5deg);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1) rotate(0deg);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -70,8 +70,14 @@
|
||||
<scroll-view class="category-right" scroll-y :refresher-enabled="true"
|
||||
:refresher-triggered="refreshTriggered" @refresherrefresh="onRefresh" @scrolltolower="onLoadMore">
|
||||
<view class="goods-list">
|
||||
<good-item v-for="good in goodsList" :key="good.product_id" :ref="`goodItem_${good.product_id}`"
|
||||
:data="good" @addToCar="addToCar" @clickCard="jumpToDetail" />
|
||||
<view class="goods-list-item left">
|
||||
<good-item v-for="(good, i) in leftColumnGoods" :key="2 * i" :ref="`goodItem_${good.product_id}`"
|
||||
:data="good" @addToCar="addToCar" />
|
||||
</view>
|
||||
<view class="goods-list-item right">
|
||||
<good-item v-for="(good, i) in rightColumnGoods" :key="2 * i + 1" :ref="`goodItem_${good.product_id}`"
|
||||
:data="good" @addToCar="addToCar" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@ -109,6 +115,7 @@ import CategoryModal from "./components/CategoryModal.vue";
|
||||
import {
|
||||
getGoodsListData
|
||||
} from "../../../api/shop";
|
||||
import { getCategoryGoodsWithCache } from "@/utils/goodsCache";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -152,6 +159,8 @@ export default {
|
||||
total: 0,
|
||||
page: 1,
|
||||
size: 10,
|
||||
nextCursor: '',
|
||||
hasMore: true,
|
||||
refreshTriggered: false,
|
||||
isLoading: false,
|
||||
petOrderId: '',
|
||||
@ -179,6 +188,12 @@ export default {
|
||||
) || {}
|
||||
);
|
||||
},
|
||||
leftColumnGoods() {
|
||||
return this.goodsList.filter((v, i) => i % 2 === 0);
|
||||
},
|
||||
rightColumnGoods() {
|
||||
return this.goodsList.filter((v, i) => i % 2 === 1);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getCategoryList();
|
||||
@ -195,6 +210,10 @@ export default {
|
||||
},
|
||||
onShow() {
|
||||
this.getCartListData();
|
||||
// 页面显示时检查是否需要刷新商品数据
|
||||
if (this.selectCategoryId) {
|
||||
this.getShopList(false);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectCategoryId(val) {
|
||||
@ -227,29 +246,72 @@ export default {
|
||||
changeCateg(item) {
|
||||
this.changeId = item.id
|
||||
this.selectCategoryId = item.id;
|
||||
this.page = 1; // 切换分类时重置分页
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.goodsList = []; // 清空当前商品列表
|
||||
this.showAllCategory = false;
|
||||
// console.log(item,'--')
|
||||
|
||||
this.getShopList(true); // 切换分类时强制刷新
|
||||
},
|
||||
// 商品列表
|
||||
getShopList() {
|
||||
getGoodsListData({
|
||||
getShopList(forceRefresh = false) {
|
||||
// 如果不是第一页且没有更多数据,直接返回
|
||||
if (this.page > 1 && !this.hasMore) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
type: this.changeId,
|
||||
p: this.page,
|
||||
num: this.size,
|
||||
keyword: "",
|
||||
is_tui: 0,
|
||||
})
|
||||
cursor: this.nextCursor,
|
||||
};
|
||||
|
||||
// 第一页使用缓存,后续页直接请求
|
||||
if (this.page > 1) {
|
||||
getGoodsListData(params)
|
||||
.then((res) => {
|
||||
const list = res?.data || [];
|
||||
this.goodsList =
|
||||
this.page === 1 ? list : [...this.goodsList, ...list];
|
||||
const list = res?.data.data?.products || res?.data || [];
|
||||
const hasMore = res?.data.data?.has_more;
|
||||
const nextCursor = res?.data.data?.next_cursor || '';
|
||||
|
||||
this.goodsList = [...this.goodsList, ...list];
|
||||
this.hasMore = hasMore;
|
||||
this.nextCursor = nextCursor;
|
||||
this.total = res?.count || 0;
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
this.refreshTriggered = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 第一页使用缓存
|
||||
getCategoryGoodsWithCache(params, forceRefresh)
|
||||
.then((res) => {
|
||||
const list = res?.data?.products || res?.data || [];
|
||||
const hasMore = res?.data?.has_more;
|
||||
const nextCursor = res?.data?.next_cursor || '';
|
||||
|
||||
// 只有当数据有变化时才更新商品列表,避免不必要的刷新
|
||||
if (res.hasChanged !== false || this.goodsList.length === 0) {
|
||||
this.goodsList = list;
|
||||
}
|
||||
|
||||
this.hasMore = hasMore;
|
||||
this.nextCursor = nextCursor;
|
||||
this.total = res?.count || list.length || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取商品列表失败', err);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
this.refreshTriggered = false;
|
||||
});
|
||||
},
|
||||
changeCategory(data) {
|
||||
console.log(data, '--=')
|
||||
@ -354,10 +416,12 @@ export default {
|
||||
this.page = 1;
|
||||
this.size = 10;
|
||||
this.total = 0;
|
||||
this.getShopList();
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.getShopList(true); // 下拉刷新时强制刷新
|
||||
},
|
||||
onLoadMore() {
|
||||
if (!this.isLoading && this.total > this.goodsList.length) {
|
||||
if (!this.isLoading && this.hasMore) {
|
||||
this.page++;
|
||||
this.getShopList();
|
||||
}
|
||||
@ -385,7 +449,7 @@ export default {
|
||||
height: 100%;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
padding-top: calc(var(--status-bar-height, 0px) + 88rpx + 20rpx);
|
||||
padding-top: 0;
|
||||
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
@ -394,7 +458,7 @@ export default {
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
background: #ff19a0;
|
||||
border-radius: 0px 0px 16px 16px;
|
||||
border-radius: 0px;
|
||||
|
||||
.status-bar {
|
||||
background: #ff19a0;
|
||||
@ -589,6 +653,24 @@ export default {
|
||||
.category-right {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
|
||||
.goods-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
margin-top: 20rpx;
|
||||
padding: 0 20rpx 120rpx;
|
||||
|
||||
.goods-list-item {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
&.left {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
|
||||
|
||||
<scroll-view class="homeContainer" scroll-y :show-scrollbar="false" :enhanced="true">
|
||||
<scroll-view class="homeContainer" scroll-y :show-scrollbar="false" :enhanced="true" @scrolltolower="onLoadMore" :refresher-enabled="true" :refresher-triggered="refreshTriggered" @refresherrefresh="onRefresh">
|
||||
<view class="swiperWrapper">
|
||||
<swiper indicator-dots="true" autoplay="true" interval="3000" duration="500" circular="true"
|
||||
class="swiper">
|
||||
@ -48,6 +48,9 @@
|
||||
<view class="loginBtn" @click="toLogin" v-if="!userInfo.userID">
|
||||
注册/登陆
|
||||
</view>
|
||||
<view class="logoutBtn" @click="logout" v-if="userInfo.userID">
|
||||
退出登录
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="shadowBackground" />
|
||||
@ -59,11 +62,11 @@
|
||||
</view> -->
|
||||
<view class="goods-list">
|
||||
<view class="goods-list-item left">
|
||||
<good-item v-for="(good, i) in leftColumnGoods" :index="2 * i" :key="2 * i" :data="good"
|
||||
<good-item v-for="(good, i) in leftColumnGoods" :index="2 * i" :key="2 * i" :data="good" :isHome="true"
|
||||
@addToCar="addToCar" />
|
||||
</view>
|
||||
<view class="goods-list-item right">
|
||||
<good-item v-for="(good, i) in rightColumnGoods" :index="2 * i + 1" :key="2 * i + 1" :data="good"
|
||||
<good-item v-for="(good, i) in rightColumnGoods" :index="2 * i + 1" :key="2 * i + 1" :data="good" :isHome="true"
|
||||
@addToCar="addToCar" />
|
||||
</view>
|
||||
</view>
|
||||
@ -85,6 +88,9 @@ import {
|
||||
import {
|
||||
userWllet
|
||||
} from "../../../api/login";
|
||||
import {
|
||||
loginOut,
|
||||
} from "../../../api/user";
|
||||
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
|
||||
import GoodItem from "../shop/components/GoodItem.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
@ -92,6 +98,7 @@ import {
|
||||
getGoodsClassify,
|
||||
getGoodsListData
|
||||
} from "@/api/shop";
|
||||
import { getHomeGoodsWithCache } from "@/utils/goodsCache";
|
||||
|
||||
export default {
|
||||
name: "HomePage",
|
||||
@ -107,6 +114,8 @@ export default {
|
||||
goodsList: [], // 商品列表
|
||||
goodsTotal: 0, // 商品总数
|
||||
goodPage: 1, // 当前页码
|
||||
nextCursor: '', // 下一页游标
|
||||
hasMore: true, // 是否还有更多数据
|
||||
isLoadingGoods: false, // 是否正在加载商品
|
||||
refreshTriggered: false, // 刷新是否已触发
|
||||
cartCount: 0, // 购物车数量
|
||||
@ -172,22 +181,68 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.goodPage = 1;
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.goodsList = [];
|
||||
this.getGoodsList()
|
||||
},
|
||||
onShow() {
|
||||
// 页面显示时检查是否需要刷新商品数据
|
||||
this.getGoodsList(false);
|
||||
},
|
||||
methods: {
|
||||
getGoodsList() {
|
||||
getGoodsList(forceRefresh = false) {
|
||||
if (this.isLoadingGoods) return;
|
||||
if (!this.hasMore && this.goodPage > 1) return;
|
||||
this.isLoadingGoods = true;
|
||||
const params = {
|
||||
type: 0
|
||||
type: 0,
|
||||
cursor: this.nextCursor
|
||||
}
|
||||
|
||||
// 加载更多时直接请求,不使用缓存
|
||||
if (this.goodPage > 1) {
|
||||
getGoodsListData(params)
|
||||
.then((res) => {
|
||||
const list = res?.data.data.products || [];
|
||||
this.goodsList = list;
|
||||
console.log(this.goodsList,'???')
|
||||
const list = res?.data.data?.products || res?.data || [];
|
||||
const hasMore = res?.data.data?.has_more;
|
||||
const nextCursor = res?.data.data?.next_cursor || '';
|
||||
|
||||
this.goodsList = [...this.goodsList, ...list];
|
||||
this.hasMore = hasMore;
|
||||
this.nextCursor = nextCursor;
|
||||
this.goodsTotal = res?.count || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取商品列表失败', err);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoadingGoods = false;
|
||||
this.refreshTriggered = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 第一页使用缓存
|
||||
getHomeGoodsWithCache(params, forceRefresh)
|
||||
.then((res) => {
|
||||
const list = res?.data.data?.products || res?.data.data || [];
|
||||
const hasMore = res?.data.data?.has_more;
|
||||
const nextCursor = res?.data.data?.next_cursor || '';
|
||||
|
||||
// 只有当数据有变化时才更新商品列表,避免不必要的刷新
|
||||
if (res.hasChanged !== false || this.goodsList.length === 0) {
|
||||
this.goodsList = list;
|
||||
}
|
||||
|
||||
this.hasMore = hasMore;
|
||||
this.nextCursor = nextCursor;
|
||||
this.goodsTotal = res?.count || list.length || 0;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('获取商品列表失败', err);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoadingGoods = false;
|
||||
this.refreshTriggered = false;
|
||||
@ -198,6 +253,17 @@ export default {
|
||||
url: "/pages/client/auth/index",
|
||||
});
|
||||
},
|
||||
logout() {
|
||||
loginOut();
|
||||
// 清除Vuex中的用户状态
|
||||
this.$store.dispatch('user/deleteToken');
|
||||
this.$store.dispatch('user/clearUserInfo');
|
||||
// 清除本地缓存
|
||||
uni.clearStorageSync();
|
||||
uni.reLaunch({
|
||||
url: "/pages/client/auth/index",
|
||||
});
|
||||
},
|
||||
// 统一的 token 检查方法,未登录时弹窗让用户自主选择
|
||||
async checkTokenAndExecute(callback) {
|
||||
const token = uni.getStorageSync('token');
|
||||
@ -335,24 +401,23 @@ export default {
|
||||
console.error('Error parsing image_list:', e);
|
||||
}
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/order/create`,
|
||||
success: (res) => {
|
||||
// 通过eventChannel向被打开页面传送数据
|
||||
res.eventChannel.emit("createOrder", {
|
||||
goodList: [{
|
||||
...this.goodsData,
|
||||
goods_id:goodsData.product.out_id,
|
||||
// price_id:goodsData.prices[0].price_id,
|
||||
product_pic: firstImageUrl,
|
||||
number:1,
|
||||
goods_name: goodsData.product.product_name,
|
||||
price_name: goodsData?.product.product_name,
|
||||
goods_price: goodsData.sku.actual_amount / 100
|
||||
}, ],
|
||||
});
|
||||
},
|
||||
url: `/pages/client/order/create?product_id=${goodsData.product.product_id}`,
|
||||
// success: (res) => {
|
||||
// // 通过eventChannel向被打开页面传送数据
|
||||
// res.eventChannel.emit("createOrder", {
|
||||
// goodList: [{
|
||||
// ...this.goodsData,
|
||||
// goods_id:goodsData.product.out_id,
|
||||
// // price_id:goodsData.prices[0].price_id,
|
||||
// product_pic: firstImageUrl,
|
||||
// number:1,
|
||||
// goods_name: goodsData.product.product_name,
|
||||
// price_name: goodsData?.product.product_name,
|
||||
// goods_price: goodsData.sku.actual_amount / 100
|
||||
// }, ],
|
||||
// });
|
||||
// },
|
||||
});
|
||||
|
||||
},
|
||||
@ -376,6 +441,19 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
onLoadMore() {
|
||||
if (!this.isLoadingGoods && this.hasMore) {
|
||||
this.goodPage++;
|
||||
this.getGoodsList();
|
||||
}
|
||||
},
|
||||
onRefresh() {
|
||||
this.refreshTriggered = true;
|
||||
this.goodPage = 1;
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.getGoodsList(true);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -384,6 +462,7 @@ export default {
|
||||
.home-page {
|
||||
height: 100vh;
|
||||
background-color: #ffecf3;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.recommand-goods-wrapper {
|
||||
@ -396,7 +475,8 @@ export default {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
margin-top: 40rpx;
|
||||
margin-top: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.goods-list-item {
|
||||
flex: 1;
|
||||
@ -442,10 +522,13 @@ export default {
|
||||
|
||||
.swiperWrapper {
|
||||
position: relative;
|
||||
margin-top: -88rpx;
|
||||
|
||||
.swiper {
|
||||
height: 552rpx;
|
||||
width: 100%;
|
||||
padding-top: 88rpx;
|
||||
box-sizing: content-box;
|
||||
|
||||
.swiper-img {
|
||||
width: 100%;
|
||||
@ -587,6 +670,16 @@ export default {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.logoutBtn {
|
||||
background: #FF19A0;
|
||||
border-radius: 218px;
|
||||
color: #fff;
|
||||
font-size: 23rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.shadowBackground {
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
<reservation
|
||||
v-show="activePageId === 'reservationPage'"
|
||||
ref="reservationPage"
|
||||
:orderId="orderId"
|
||||
/>
|
||||
</view>
|
||||
<tab-bar
|
||||
@ -60,6 +61,7 @@ export default {
|
||||
path: "/pages/client/index/index",
|
||||
},
|
||||
getUserInfoPromise: null, // 用于防止重复调用 getUserInfo
|
||||
orderId: null, // 存储从订单页面传递过来的 orderId
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@ -165,12 +167,17 @@ export default {
|
||||
this.$store.dispatch('user/setReferrerID', Number(option.referrerID) || 0);
|
||||
}
|
||||
|
||||
// 处理从订单页面传递的 orderId
|
||||
if (option?.orderId) {
|
||||
this.orderId = option.orderId;
|
||||
}
|
||||
|
||||
// 处理页面跳转参数
|
||||
if (option?.activePageId) {
|
||||
const targetPageId = option.activePageId;
|
||||
// 如果目标页面与当前页面不同,触发切换
|
||||
if (this.activePageId !== targetPageId) {
|
||||
this.handleTabChange([targetPageId]);
|
||||
this.handleTabChange([targetPageId], option.orderId);
|
||||
} else {
|
||||
this.activePageId = targetPageId;
|
||||
}
|
||||
|
||||
@ -14,12 +14,18 @@
|
||||
{{ userInfo.userID && userInfo.username ? userInfo.username : '嗨,你好呀' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="userPhone" v-if="userInfo.phone">
|
||||
{{ userInfo.phone }}
|
||||
</view>
|
||||
<!-- <view class="vipWrapper">
|
||||
<image class="lableImg" :src="`${imgPrefix}home-vipLabel.png`" mode=""></image>
|
||||
v{{ userInfo.vipLevel || 1 }}会员
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="logoutBtn" @click="showLogoutModal = true">
|
||||
退出登录
|
||||
</view>
|
||||
<!-- <view class="userRight">
|
||||
<view class="userRgihtItemView" @click="jumpTo('/pages/client/recharge/index?tab=points')">
|
||||
<view class="num">
|
||||
@ -300,6 +306,10 @@ components: {
|
||||
logout() {
|
||||
loginOut();
|
||||
this.showLogoutModal = false;
|
||||
// 清除Vuex中的用户状态
|
||||
this.$store.dispatch('user/deleteToken');
|
||||
this.$store.dispatch('user/clearUserInfo');
|
||||
// 清除本地缓存
|
||||
uni.clearStorageSync();
|
||||
uni.reLaunch({
|
||||
url: "/pages/client/auth/index",
|
||||
@ -330,13 +340,17 @@ title: '请添加客服号',
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
height: calc(100vh - #{$app_tabbar_height + 26});
|
||||
padding-top: 0;
|
||||
|
||||
.mineGroundImgView {
|
||||
position: relative;
|
||||
margin-top: -88rpx;
|
||||
|
||||
.groundImg {
|
||||
width: 100%;
|
||||
height: 552rpx;
|
||||
padding-top: 88rpx;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,6 +400,21 @@ title: '请添加客服号',
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.userPhone {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.logoutBtn {
|
||||
background: #FF19A0;
|
||||
color: #fff;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.userRight {
|
||||
@ -460,7 +489,7 @@ title: '请添加客服号',
|
||||
width: calc(100vw - 40rpx);
|
||||
background-color: #fff;
|
||||
margin: auto;
|
||||
margin-top: 20rpx;
|
||||
margin-top:46rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 26rpx;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<view class="edit-content">
|
||||
<view class="flex-row-between edit-cell">
|
||||
<text class="title">头像</text>
|
||||
<button class="flex-row-end user-avator" open-type="chooseAvatar" @chooseavatar="chooseavatar">
|
||||
<button class="flex-row-end user-avator" @click="chooseavatar">
|
||||
<image class="avator-icon" :src="userInfo.head_pic_url" />
|
||||
<!-- <image class="arrow-icon" :src="`${imgPrefix}right-arrow.png`" /> -->
|
||||
</button>
|
||||
@ -174,22 +174,27 @@ export default {
|
||||
});
|
||||
},
|
||||
// 更新头像
|
||||
async chooseavatar(e) {
|
||||
const {
|
||||
avatarUrl
|
||||
} = e.detail;
|
||||
chooseavatar() {
|
||||
let that = this;
|
||||
|
||||
uni.showLoading({
|
||||
title: "上传中..."
|
||||
});
|
||||
|
||||
uni.chooseImage({
|
||||
count: 1, // 只选一张图片
|
||||
sourceType: ['album', 'camera'], // 来源:相册、相机
|
||||
success: async function(res) {
|
||||
try {
|
||||
const { url, objectKey } = await uploadImageToOSS_PUT(avatarUrl);
|
||||
console.log(url, objectKey, 'url, objectKey')
|
||||
this.userInfo.head_pic_url = url; // 同时更新 head_pic_url,因为模板使用的是这个字段
|
||||
this.userInfo.head_pic = objectKey;
|
||||
this.$forceUpdate();
|
||||
const { url, objectKey } = await uploadImageToOSS_PUT(res.tempFilePaths[0]);
|
||||
that.userInfo.head_pic_url = url; // 同时更新 head_pic_url,因为模板使用的是这个字段
|
||||
that.userInfo.head_pic = objectKey;
|
||||
that.$forceUpdate();
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: "上传成功",
|
||||
icon: "success",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('头像上传失败:', error);
|
||||
uni.hideLoading();
|
||||
@ -199,6 +204,12 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: function(err) {
|
||||
console.log('选择图片失败:', err.errMsg);
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
},
|
||||
onChange(value, key) {
|
||||
this.userInfo[key] = value;
|
||||
this.$forceUpdate();
|
||||
|
||||
@ -5,14 +5,11 @@
|
||||
<view class="good-content" @click="$emit('clickGoodInfo', data[0])">
|
||||
<view class="goods-row-first">
|
||||
<view class="goods-name">{{ data[0].goods_name || "" }}</view>
|
||||
<text class="goods-price">¥{{ data[0].goods_price || actual_price }}</text>
|
||||
<view class="fs-28 app-fc-main goods-price">
|
||||
¥{{ data[0].goods_price || data[0].product_actual_price }}
|
||||
</view>
|
||||
<view class="goods-row-second">
|
||||
<view class="goods-spec">
|
||||
{{ data[0].shuxing_name || "" }}{{ data[0].shuxing_name && data[0].price_name ? ";" : "" }}{{ data[0].price_name || "" }}
|
||||
</view>
|
||||
<text class="goods-count">共{{ data[0].number || 1 }}件</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-normal">共{{ data[0].number || 1 }}件</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -24,7 +21,7 @@
|
||||
<view class="good-info-right">
|
||||
<text class="good-total-price">¥{{ actual_price }}</text>
|
||||
<text class="fs-24 app-fc-normal good-num">
|
||||
共1件
|
||||
共{{ totalCount }}件
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
@ -56,6 +53,11 @@
|
||||
return sum + price * number;
|
||||
}, 0).toFixed(2);
|
||||
},
|
||||
totalCount() {
|
||||
return this.data.reduce((sum, item) => {
|
||||
return sum + parseInt(item.number || 1);
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.data,'--')
|
||||
@ -76,68 +78,43 @@
|
||||
|
||||
&.good-info {
|
||||
padding-top: 20rpx;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
|
||||
.good-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 8rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 16rpx;
|
||||
background: #f5f5f5;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.good-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
height: 160rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.goods-row-first {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8rpx;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
|
||||
.goods-name {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
line-height: 40rpx;
|
||||
margin-right: 16rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-row-second {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.goods-spec {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-right: 20rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.goods-count {
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,17 +5,26 @@
|
||||
订单编号:{{ data.order_no || "-" }}
|
||||
</text>
|
||||
<!-- 待支付状态:显示倒计时横幅 -->
|
||||
<view v-if="data.status === SHOP_ORDER_UNPAY && !data.tui_status && countDownTime > 0"
|
||||
class="order-status-banner">
|
||||
<view
|
||||
v-if="
|
||||
data.status === SHOP_ORDER_UNPAY &&
|
||||
!data.tui_status &&
|
||||
countDownTime > 0
|
||||
"
|
||||
class="order-status-banner"
|
||||
>
|
||||
<view class="status-banner-left">
|
||||
<text class="status-text">等待付款</text>
|
||||
</view>
|
||||
<view class="status-banner-right">
|
||||
<text class="countdown-text">{{ formatCountdown(countDownTime) }}</text>
|
||||
<text class="countdown-text">{{
|
||||
formatCountdown(countDownTime)
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 其他状态:显示原有样式 -->
|
||||
<view v-else-if="
|
||||
<view
|
||||
v-else-if="
|
||||
([
|
||||
SHOP_ORDER_CANCEL,
|
||||
SHOP_ORDER_UNPAY,
|
||||
@ -26,40 +35,59 @@
|
||||
].includes(data.status) &&
|
||||
!data.tui_status) ||
|
||||
[SHOP_ORDER_AFTERSALE_REJECT].includes(data.tui_status)
|
||||
" class="flex-center fs-24 order-btn" :class="[
|
||||
"
|
||||
class="flex-center fs-24 order-btn"
|
||||
:class="[
|
||||
![SHOP_ORDER_DONE, SHOP_ORDER_CANCEL, SHOP_ORDER_UNREMARK].includes(
|
||||
data.status
|
||||
)
|
||||
? 'app-fc-mark confirm'
|
||||
: 'cancel',
|
||||
]">
|
||||
]"
|
||||
>
|
||||
{{ orderStatus }}
|
||||
</view>
|
||||
<view v-if="
|
||||
<view
|
||||
v-if="
|
||||
[SHOP_ORDER_AFTERSALE, SHOP_ORDER_AFTERSALE_DONE].includes(
|
||||
data.tui_status
|
||||
)
|
||||
" class="flex-center fs-24 order-btn cancel">
|
||||
"
|
||||
class="flex-center fs-24 order-btn cancel"
|
||||
>
|
||||
{{ refundOrderStatus }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-content" :class="{ 'split-border': showStatusBtn }" @click="jumpToDetails">
|
||||
<good-info :data="data" :actual_price="data.actual_price" />
|
||||
<view v-if="data.type && data.type !== 1" class="fs-24 app-fc-mark order-type">
|
||||
<view
|
||||
class="order-content"
|
||||
:class="{ 'split-border': showStatusBtn }"
|
||||
@click="jumpToDetails"
|
||||
>
|
||||
<good-info :data="data.items" :actual_price="data.actual_price" />
|
||||
<view
|
||||
v-if="data.type && data.type !== 1"
|
||||
class="fs-24 app-fc-mark order-type"
|
||||
>
|
||||
随车订单
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showStatusBtn" class="order-btns">
|
||||
<!-- 待支付 -->
|
||||
<template v-if="[SHOP_ORDER_UNPAY].includes(data.status)">
|
||||
<view class="flex-center fs-24 app-fc-main cancel-order-btn" @click.stop="$emit('cancelOrder', data)">
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-main cancel-order-btn"
|
||||
@click.stop="$emit('cancelOrder', data)"
|
||||
>
|
||||
取消订单
|
||||
</view>
|
||||
<view class="order-btns-right">
|
||||
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
|
||||
联系客服
|
||||
</view> -->
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm" @click.stop="$emit('pay', data)">
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('pay', data)"
|
||||
>
|
||||
立即支付
|
||||
</view>
|
||||
</view>
|
||||
@ -68,11 +96,16 @@
|
||||
<!-- 待预约 -->
|
||||
<template v-if="[SHOP_ORDER_UNSLIVER].includes(data.status)">
|
||||
<view class="order-btns-right">
|
||||
<view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('refund', data)">
|
||||
<!-- <view
|
||||
class="flex-center fs-24 app-fc-main status-btn"
|
||||
@click.stop="remindRefund(data.order_id)"
|
||||
>
|
||||
申请退款
|
||||
</view>
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="jumpToReservation">
|
||||
</view> -->
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="jumpToReservation(data.order_id)"
|
||||
>
|
||||
立即预约
|
||||
</view>
|
||||
</view>
|
||||
@ -84,18 +117,23 @@
|
||||
联系客服
|
||||
</view> -->
|
||||
|
||||
<view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('afterSale', data)">
|
||||
<!-- <view
|
||||
class="flex-center fs-24 app-fc-main status-btn"
|
||||
@click.stop="$emit('afterSale', data)"
|
||||
>
|
||||
申请售后
|
||||
</view>
|
||||
</view> -->
|
||||
<!-- 随车订单不显示物流 -->
|
||||
<!-- <view v-if="data.pay_type !== pay_type_BYCAR" class="flex-center fs-24 app-fc-main status-btn"
|
||||
@click.stop="$emit('checkSliver', data)">
|
||||
查看物流
|
||||
</view> -->
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('confirmSliver', data)">
|
||||
<!-- <view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('confirmSliver', data)"
|
||||
>
|
||||
确认收货
|
||||
</view>
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<!-- 已签收未评价 -->
|
||||
@ -103,7 +141,10 @@
|
||||
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
|
||||
联系客服
|
||||
</view> -->
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm" @click.stop="$emit('remark', data)">
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('remark', data)"
|
||||
>
|
||||
立即评价
|
||||
</view>
|
||||
</template>
|
||||
@ -113,18 +154,20 @@
|
||||
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
|
||||
联系客服
|
||||
</view> -->
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm "
|
||||
style="visibility: hidden;"
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
style="visibility: hidden"
|
||||
>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="[SHOP_ORDER_DONE].includes(data.status)">
|
||||
<!-- <view class="flex-center fs-24 app-fc-main status-btn" @click.stop="$emit('concactService', data)">
|
||||
联系客服
|
||||
</view> -->
|
||||
<view class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('remarkDetails', data)">
|
||||
<view
|
||||
class="flex-center fs-24 app-fc-white status-btn confirm"
|
||||
@click.stop="$emit('remarkDetails', data)"
|
||||
>
|
||||
查看评价
|
||||
</view>
|
||||
</template>
|
||||
@ -135,6 +178,8 @@
|
||||
<script>
|
||||
import PopUpModal from "@/components/PopUpModal.vue";
|
||||
import GoodInfo from "./GoodInfo.vue";
|
||||
import { walletTransaction, cancelPetOrderMall } from "../../../../api/login";
|
||||
|
||||
import {
|
||||
SHOP_ORDER_STATUS,
|
||||
SHOP_ORDER_UNPAY,
|
||||
@ -149,7 +194,7 @@
|
||||
SHOP_ORDER_UNREMARK,
|
||||
pay_type_ADDRESS,
|
||||
pay_type_BYCAR,
|
||||
pay_type_BYPET
|
||||
pay_type_BYPET,
|
||||
} from "@/constants/app.business";
|
||||
|
||||
export default {
|
||||
@ -181,7 +226,7 @@
|
||||
},
|
||||
components: {
|
||||
GoodInfo,
|
||||
PopUpModal
|
||||
PopUpModal,
|
||||
},
|
||||
options: {
|
||||
styleIsolation: "shared",
|
||||
@ -214,11 +259,11 @@
|
||||
refundParams() {
|
||||
return {
|
||||
reasonCode: [410],
|
||||
note: '用户申请退款',
|
||||
note: "用户申请退款",
|
||||
applySource: 101,
|
||||
afterSaleType: 3,
|
||||
needRefundPackFee: true
|
||||
}
|
||||
needRefundPackFee: true,
|
||||
};
|
||||
},
|
||||
orderStatus() {
|
||||
return SHOP_ORDER_STATUS[this.data.status] || "";
|
||||
@ -235,7 +280,8 @@
|
||||
SHOP_ORDER_DONE,
|
||||
SHOP_ORDER_UNREMARK,
|
||||
].includes(this.data.status) &&
|
||||
!this.data.tui_status) || [SHOP_ORDER_AFTERSALE_REJECT].includes(this.data.tui_status)
|
||||
!this.data.tui_status) ||
|
||||
[SHOP_ORDER_AFTERSALE_REJECT].includes(this.data.tui_status)
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -243,13 +289,13 @@
|
||||
showCancelModal(val) {
|
||||
this.$emit("disableScroll", val);
|
||||
},
|
||||
'data.daojishi'(newVal) {
|
||||
"data.daojishi"(newVal) {
|
||||
if (this.data.status === this.SHOP_ORDER_UNPAY && newVal) {
|
||||
this.countDownTime = newVal;
|
||||
this.startCountDown();
|
||||
}
|
||||
},
|
||||
'data.status'(newVal) {
|
||||
"data.status"(newVal) {
|
||||
if (newVal === this.SHOP_ORDER_UNPAY && this.data.daojishi) {
|
||||
this.countDownTime = this.data.daojishi;
|
||||
this.startCountDown();
|
||||
@ -269,32 +315,119 @@
|
||||
this.stopCountDown();
|
||||
},
|
||||
methods: {
|
||||
// 退款回调(组件触发)
|
||||
handleRefund(event) {
|
||||
const { status, result, outOrderNo } = event.detail
|
||||
console.log('退款回调:', { status, result, outOrderNo })
|
||||
|
||||
if (status === 'success') {
|
||||
remindRefund(id) {
|
||||
const data = {
|
||||
id: Number(id),
|
||||
};
|
||||
uni.showLoading({
|
||||
icon: "none",
|
||||
title: "处理中",
|
||||
mask: true,
|
||||
});
|
||||
cancelPetOrderMall(data)
|
||||
.then((res) => {
|
||||
uni.hideLoading();
|
||||
const plugin = tt.requirePlugin("lifeServicePlugin");
|
||||
let res1 = {
|
||||
code: 0,
|
||||
result: "success",
|
||||
msg: "success",
|
||||
data: {
|
||||
outOrderNo: "DYG177556196373493862814838179",
|
||||
refundInfo: {
|
||||
reason: ["计划有变,暂时不需要了"]
|
||||
},
|
||||
// refundInfo: {
|
||||
// reason:["计划有变,暂时不需要了"],
|
||||
// reasonCode:[401],
|
||||
// },
|
||||
itemOrderList:[
|
||||
{
|
||||
"itemOrderId": "1093391915337944382",
|
||||
"refundAmount": 9000
|
||||
}],
|
||||
// goodsList: [
|
||||
// { goodsId: "7625832097692813354", goodsType: 1, quantity: 1 },
|
||||
// ],
|
||||
},
|
||||
};
|
||||
// console.log('applyRefund options', JSON.stringify(options))
|
||||
console.log(res1.data,'??')
|
||||
plugin.applyRefund({
|
||||
itemOrderList:res1.data.itemOrderList,
|
||||
// goodsList: res1.data.goodsList,
|
||||
outOrderNo: res1.data.outOrderNo,
|
||||
refundInfo: res1.data.refundInfo,
|
||||
success: (res) => {
|
||||
uni.showToast({
|
||||
title: '退款申请已提交',
|
||||
icon: 'success'
|
||||
})
|
||||
this.$emit('refund', this.data)
|
||||
title: "退款申请已提交",
|
||||
icon: "success",
|
||||
});
|
||||
this.$emit("refund", this.data);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log("退款失败:", err);
|
||||
// 处理session过期错误
|
||||
if (err && err.errMsg && err.errMsg.includes("session已过期")) {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "会话已过期,请重新登录后再试",
|
||||
showCancel: false,
|
||||
confirmText: "确定",
|
||||
success: () => {
|
||||
// 清除当前用户信息并跳转到登录页
|
||||
this.$store.dispatch("user/deleteToken");
|
||||
this.$store.dispatch("user/clearUserInfo");
|
||||
uni.clearStorageSync();
|
||||
uni.reLaunch({
|
||||
url: "/pages/client/auth/index",
|
||||
});
|
||||
},
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result?.errMsg || '退款失败,请稍后重试',
|
||||
icon: 'none'
|
||||
title: err?.errMsg || err?.msg || "退款失败,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading();
|
||||
console.error("获取退款信息失败:", err);
|
||||
uni.showToast({
|
||||
title: err?.msg || "获取退款信息失败",
|
||||
icon: "none",
|
||||
});
|
||||
});
|
||||
},
|
||||
// 退款回调(组件触发)
|
||||
handleRefund(event) {
|
||||
const { status, result, outOrderNo } = event.detail;
|
||||
console.log("退款回调:", { status, result, outOrderNo });
|
||||
|
||||
if (status === "success") {
|
||||
uni.showToast({
|
||||
title: "退款申请已提交",
|
||||
icon: "success",
|
||||
});
|
||||
this.$emit("refund", this.data);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result?.errMsg || "退款失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 错误处理
|
||||
handleError(event) {
|
||||
console.error('退款组件报错:', event.detail)
|
||||
console.error("退款组件报错:", event.detail);
|
||||
uni.showToast({
|
||||
title: '组件加载失败,请稍后重试',
|
||||
icon: 'none'
|
||||
})
|
||||
title: "组件加载失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
|
||||
startCountDown() {
|
||||
@ -306,7 +439,7 @@
|
||||
} else {
|
||||
this.stopCountDown();
|
||||
// 倒计时结束,可以触发刷新
|
||||
this.$emit('countdownEnd', this.data);
|
||||
this.$emit("countdownEnd", this.data);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
@ -329,11 +462,11 @@
|
||||
this.showCancelModal = false;
|
||||
},
|
||||
jumpToDetails() {
|
||||
this.$emit('jumpToDetails', this.data)
|
||||
this.$emit("jumpToDetails", this.data);
|
||||
},
|
||||
jumpToReservation() {
|
||||
jumpToReservation(orderId) {
|
||||
uni.reLaunch({
|
||||
url: '/pages/client/index/index?activePageId=reservationPage'
|
||||
url: `/pages/client/index/index?activePageId=reservationPage&orderId=${orderId}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -380,14 +513,14 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
background: #FF19A0;
|
||||
background: #ff19a0;
|
||||
padding: 8rpx;
|
||||
flex-shrink: 0;
|
||||
border-radius: 10px 0px 10px 10px;
|
||||
|
||||
.status-text {
|
||||
font-size: 20rpx;
|
||||
color: #FFFFFF;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,21 +529,18 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
background: #FFF0F8;
|
||||
background: #fff0f8;
|
||||
padding: 8rpx;
|
||||
flex-shrink: 0;
|
||||
|
||||
|
||||
|
||||
.countdown-text {
|
||||
font-size: 20rpx;
|
||||
color: #FF19A0;
|
||||
color: #ff19a0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.order-btns {
|
||||
padding-top: 20rpx;
|
||||
display: flex;
|
||||
@ -419,7 +549,7 @@
|
||||
|
||||
.cancel-order-btn {
|
||||
font-size: 24rpx;
|
||||
color: #9B939A;
|
||||
color: #9b939a;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
|
||||
@ -433,7 +563,7 @@
|
||||
height: 34px;
|
||||
// padding: 16rpx 20rpx;
|
||||
border-radius: 64rpx;
|
||||
border: 1px solid #FF19A0;;
|
||||
border: 1px solid #ff19a0;
|
||||
margin-left: 20rpx;
|
||||
|
||||
&.confirm {
|
||||
@ -447,7 +577,6 @@
|
||||
.good-info-multi {
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<view class="order-create-container">
|
||||
<!-- 商品信息 -->
|
||||
<view class="info-cell goods-info-cell">
|
||||
@ -10,81 +11,70 @@
|
||||
>
|
||||
<image
|
||||
class="goods-img"
|
||||
:src="item.item_pic || item.product_pic"
|
||||
:src="item.image"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="goods-content">
|
||||
<view class="goods-row-first">
|
||||
<view class="goods-name">{{
|
||||
item.item_name || item.product_name
|
||||
}}</view>
|
||||
<text class="goods-price"
|
||||
>¥{{ item.product_price || item.goods_price }}</text
|
||||
>
|
||||
<!-- <view class="goods-name">{{
|
||||
item.name
|
||||
}}</view> -->
|
||||
<view class="price-wrapper">
|
||||
<text class="final-price-label">到手价</text>
|
||||
<text class="final-price">¥{{ item.price }}</text>
|
||||
</view>
|
||||
<view class="goods-row-second">
|
||||
<text class="goods-count">共{{ item.number || 1 }}件</text>
|
||||
<view class="sales-info">
|
||||
<text class="sales-count">{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="info-cell pay-cell">
|
||||
<view class="flex-row-between pay-info">
|
||||
<text class="pay-label">商品金额</text>
|
||||
<text class="pay-value">¥{{ payPrice }}</text>
|
||||
</view>
|
||||
<view
|
||||
v-if="couponList.length"
|
||||
class="flex-row-between pay-info coupon-row"
|
||||
@click="showCouponModal = true"
|
||||
>
|
||||
<text class="pay-label">优惠券</text>
|
||||
<view class="flex-row-end">
|
||||
<text class="coupon-price">
|
||||
{{ couponFee ? `- ¥${couponFee}` : "请选择" }}
|
||||
</text>
|
||||
|
||||
<!-- 图片撑满屏幕宽度 -->
|
||||
<!-- <image
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/1.png"
|
||||
mode="widthFix"
|
||||
/> -->
|
||||
<image
|
||||
class="arrow-icon"
|
||||
src="@/static/images/arrow_right_black.png"
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/2.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="flex-row-between pay-info">
|
||||
<text class="pay-label">运费</text>
|
||||
<text class="pay-value">{{ sliverFee ? `¥${sliverFee}` : "包邮" }}</text>
|
||||
</view> -->
|
||||
<view class="flex-row-between pay-price">
|
||||
<text class="pay-label">需付款</text>
|
||||
<text class="pay-total">¥{{ payPrice }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="info-cell payment-method-cell">
|
||||
<view class="payment-item" @click.stop="selectOption1('1')">
|
||||
<view class="payment-left">
|
||||
<image class="payment-icon" src="@/static/images/douy.png" mode="widthFix" />
|
||||
<text class="payment-text">抖音支付</text>
|
||||
</view>
|
||||
<image class="payment-check"
|
||||
:src="selected2 ? require('@/static/images/cart_checked.png') : require('@/static/images/unchecked.png')"
|
||||
mode="widthFix" />
|
||||
</view>
|
||||
</view> -->
|
||||
<image
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/3.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<!-- <image
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/4.png"
|
||||
mode="widthFix"
|
||||
/> -->
|
||||
<!-- <image
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/5.png"
|
||||
mode="widthFix"
|
||||
/> -->
|
||||
<!-- <image
|
||||
class="full-width-img"
|
||||
src="https://static.wagoo.pet/statics/6.png"
|
||||
mode="widthFix"
|
||||
/> -->
|
||||
|
||||
<view class="order-create-container">
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
|
||||
|
||||
<view class="place-view"></view>
|
||||
|
||||
<view class="order-create-bottom">
|
||||
<!-- <view class="cancel-btn" @click="cancelOrder">
|
||||
<text class="cancel-btn-text">取消订单</text>
|
||||
</view> -->
|
||||
<view class="price-info">
|
||||
<text class="current-price">¥{{ orderPrice.toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="pay-btn" @click="createOrder">
|
||||
<text class="pay-btn-text">立即支付</text>
|
||||
<text class="pay-btn-text">立即购买</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -94,6 +84,7 @@
|
||||
@close="showGoodInfoModal = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -112,6 +103,10 @@ import { getAddressInfo } from "../../../api/address";
|
||||
import { COUPON_TYPE_GOODS } from "../../../constants/app.business";
|
||||
import { walletTransaction } from "../../../api/login";
|
||||
import { imgPrefix, jumpToWeChat } from "@/utils/common";
|
||||
import {
|
||||
addCart,
|
||||
getGoodsDetail,
|
||||
} from "@/api/shop";
|
||||
|
||||
const sliverList = [
|
||||
{
|
||||
@ -133,7 +128,9 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orderData:[],
|
||||
payPrice: 0,
|
||||
orPrice:0,
|
||||
type: "",
|
||||
orderData: [],
|
||||
addressInfo: {},
|
||||
@ -156,7 +153,6 @@ export default {
|
||||
selected4: true,
|
||||
recharge: true,
|
||||
record: false,
|
||||
walletBalance: "1000.00",
|
||||
imgPrefix,
|
||||
WeChat: undefined,
|
||||
wallet: "2",
|
||||
@ -179,153 +175,40 @@ export default {
|
||||
},
|
||||
},
|
||||
onLoad(option) {
|
||||
const { type, petOrderId = "", petOrderAddressId = "" } = option;
|
||||
this.type = type;
|
||||
this.petOrderId = petOrderId;
|
||||
this.petOrderAddressId = petOrderAddressId;
|
||||
|
||||
if (petOrderAddressId) {
|
||||
getAddressInfo(petOrderAddressId).then((res) => {
|
||||
this.addressInfo = {
|
||||
...res?.info,
|
||||
};
|
||||
});
|
||||
}
|
||||
uni.$on("selectAddress", this.addressChange);
|
||||
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
eventChannel.on("createOrder", (data) => {
|
||||
// Helper function to extract first image from image_list
|
||||
const extractFirstImage = (imageList) => {
|
||||
if (!imageList) return "";
|
||||
try {
|
||||
const parsedList =
|
||||
typeof imageList === "string" ? JSON.parse(imageList) : imageList;
|
||||
if (Array.isArray(parsedList) && parsedList.length > 0) {
|
||||
return parsedList[0].url || parsedList[0] || "";
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error parsing image_list:", e);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
this.orderData = (data?.goodList || []).map((item) => {
|
||||
// Check if product_pic is actually an image_list that needs parsing
|
||||
let processedItem = { ...item };
|
||||
if (processedItem.product_pic) {
|
||||
// If product_pic looks like an array or JSON string, try to parse it
|
||||
if (
|
||||
typeof processedItem.product_pic === "string" &&
|
||||
(processedItem.product_pic.startsWith("[") ||
|
||||
processedItem.product_pic.startsWith("{"))
|
||||
) {
|
||||
const extractedUrl = extractFirstImage(processedItem.product_pic);
|
||||
if (extractedUrl) {
|
||||
processedItem.product_pic = extractedUrl;
|
||||
}
|
||||
} else if (Array.isArray(processedItem.product_pic)) {
|
||||
const extractedUrl = extractFirstImage(processedItem.product_pic);
|
||||
if (extractedUrl) {
|
||||
processedItem.product_pic = extractedUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return processedItem;
|
||||
});
|
||||
|
||||
this.payPrice = this.orderData.reduce(
|
||||
(sum, item) =>
|
||||
sum +
|
||||
Number((item.product_price || item.goods_price) * item.number || 0),
|
||||
0
|
||||
);
|
||||
console.log(data, "--=?");
|
||||
const price = this.orderData.reduce(
|
||||
(total, prev) => total + +prev.item_price,
|
||||
0
|
||||
);
|
||||
this.orderPrice = +price.toFixed(2);
|
||||
this.confirmPrice = +(this.orderPrice - this.couponFee).toFixed(2);
|
||||
});
|
||||
// console.log(option,'?')
|
||||
this.getGoodsList(option.product_id)
|
||||
},
|
||||
methods: {
|
||||
getGoodsList(id) {
|
||||
getGoodsDetail({
|
||||
product_id:id,
|
||||
})
|
||||
.then((res) => {
|
||||
this.orderData = res.data
|
||||
this.orPrice = res.data.price
|
||||
this.orderPrice = res.data[0].price
|
||||
console.log( this.orderData,'--=??')
|
||||
})
|
||||
},
|
||||
createOrder(isPrePay) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isPrePay) {
|
||||
uni.showLoading({
|
||||
title: "处理中",
|
||||
title: "支付中",
|
||||
mask: true,
|
||||
});
|
||||
}
|
||||
console.log(this.orderData[0].goods_id,'-=-')
|
||||
const params = {
|
||||
id: Number(this.orderData[0].goods_id),
|
||||
};
|
||||
|
||||
createCartOrder(params)
|
||||
.then((res) => {
|
||||
uni.hideLoading();
|
||||
|
||||
// Check if tt and requirePlugin are available
|
||||
if (typeof tt !== "undefined" && tt.requirePlugin) {
|
||||
try {
|
||||
const plugin = tt.requirePlugin("lifeServicePlugin");
|
||||
if (plugin && plugin.createOrder) {
|
||||
// let res1 = {
|
||||
// data: {
|
||||
// businessLine: 1,
|
||||
// skuList: [
|
||||
// {
|
||||
// quantity: 1,
|
||||
// skuId: "1861281775887367",
|
||||
// skuType: 1,
|
||||
// price: 12000,
|
||||
// goodsInfo: {
|
||||
// goodsName:
|
||||
// "狗狗移动上门赛级洗护| 狗狗洗澡| 体重【5-10kg】",
|
||||
// goodsPhoto:
|
||||
// "https://static.wagoo.pet/statics/dog5to10base.png",
|
||||
// goodsId: "7625864573682075667",
|
||||
// goodsType: 1,
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// bookInfo: {
|
||||
// itemBookInfoList: [
|
||||
// {
|
||||
// poiId: "7620725019240319028",
|
||||
// shopName: "WAGOO·上海市",
|
||||
// outShopId: "life_7620725019240319028",
|
||||
// goodsId: "7625864573682075667",
|
||||
// bookStartTime: 1775613600000,
|
||||
// bookEndTime: 1775622600000,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// payment: {
|
||||
// totalAmount: 12000,
|
||||
// },
|
||||
// contactInfo: {
|
||||
// phoneNumber: "13773726377",
|
||||
// contactName: "老王",
|
||||
// },
|
||||
// storeInfo: {
|
||||
// storeName: "WAGOO·上海市",
|
||||
// },
|
||||
// callbackData: {
|
||||
// douyin_product_id: "7625864573682075667",
|
||||
// douyin_sku_id: "1861281775887367",
|
||||
// goods_id: 183,
|
||||
// order_date: "2026-04-08",
|
||||
// period_id: 1,
|
||||
// test: 999999,
|
||||
// },
|
||||
// tradeOption: {
|
||||
// life_trade_flag: 1,
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// console.log(res.data,'???')
|
||||
uni.hideLoading();
|
||||
plugin.createOrder({
|
||||
skuList: res.data.skuList,
|
||||
bookInfo: res.data.bookInfo,
|
||||
@ -334,14 +217,10 @@ export default {
|
||||
storeInfo: res.data.storeInfo,
|
||||
tradeOption: res.data.tradeOption,
|
||||
payment: res.data.payment,
|
||||
// callbackData:res.data.callbackData,
|
||||
// tradeOption:res.data.tradeOption,
|
||||
// goodsList:res.data.goodsList,
|
||||
success: (res) => {
|
||||
const { orderId, outOrderNo } = res;
|
||||
console.log("success res", res);
|
||||
console.log("orderId", orderId, "outOrderNo", outOrderNo);
|
||||
// Update data the Vue way
|
||||
this.orderId = orderId;
|
||||
this.outOrderNo = outOrderNo;
|
||||
uni.navigateTo({
|
||||
@ -350,23 +229,8 @@ export default {
|
||||
},
|
||||
fail: (res) => {
|
||||
console.log("fail res", res);
|
||||
const { orderId, outOrderNo, errNo, errMsg, errLogId } =
|
||||
res;
|
||||
if (errLogId) {
|
||||
console.log("预下单失败", errNo, errMsg, errLogId);
|
||||
}
|
||||
if (orderId || outOrderNo) {
|
||||
console.log(
|
||||
"支付失败",
|
||||
errNo,
|
||||
errMsg,
|
||||
orderId,
|
||||
outOrderNo
|
||||
);
|
||||
}
|
||||
console.log(errNo, errMsg);
|
||||
uni.showToast({
|
||||
title: errMsg || "支付失败",
|
||||
title: "支付失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
@ -392,7 +256,6 @@ export default {
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
|
||||
resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -411,8 +274,12 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100%;
|
||||
background: #f7f8fa;
|
||||
}
|
||||
|
||||
.order-create-container {
|
||||
height: 100%;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background: #f7f8fa;
|
||||
@ -424,99 +291,13 @@ export default {
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.arrow-icon {
|
||||
width: 11rpx;
|
||||
height: 18rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.address-info-cell {
|
||||
.address-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.address-row-first {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.address-row-second {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.address-icon {
|
||||
width: 24rpx;
|
||||
height: 32rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.address-placeholder {
|
||||
font-size: 24rpx;
|
||||
color: #3d3d3d;
|
||||
padding: 20rpx 0rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.address-name {
|
||||
font-size: 28rpx;
|
||||
color: #3d3d3d;
|
||||
|
||||
.address-phone {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-details {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 36rpx;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 11rpx;
|
||||
height: 18rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.sliver-info-cell {
|
||||
.sliver-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sliver-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sliver-text {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
&.goods-info-cell {
|
||||
padding: 0;
|
||||
|
||||
.goods-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 24rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
@ -527,210 +308,68 @@ export default {
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
height: 355px;
|
||||
border-radius: 16rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.goods-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: 100rpx;
|
||||
justify-content: flex-start;
|
||||
min-height: 200rpx;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.goods-row-first {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12rpx;
|
||||
padding-top: 8rpx;
|
||||
|
||||
.goods-name {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #3d3d3d;
|
||||
line-height: 40rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 20rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #3d3d3d;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-row-second {
|
||||
.price-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.goods-spec {
|
||||
flex: 1;
|
||||
.final-price-label {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.goods-count {
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-multi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
.goods-imgs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
.goods-img-small {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
color: #ff19a0;
|
||||
background: linear-gradient(to right, #ffeef7, #fff);
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 4rpx 0 0 4rpx;
|
||||
margin-right: 8rpx;
|
||||
border-radius: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-count-wrapper {
|
||||
flex-shrink: 0;
|
||||
|
||||
.goods-count-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pay-cell {
|
||||
.pay-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 0;
|
||||
|
||||
.pay-label {
|
||||
font-size: 24rpx;
|
||||
color: #9b939a;
|
||||
}
|
||||
|
||||
.pay-value {
|
||||
font-size: 24rpx;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-row {
|
||||
.coupon-price {
|
||||
font-size: 28rpx;
|
||||
.final-price {
|
||||
font-size: 48rpx;
|
||||
color: #ff19a0;
|
||||
font-weight: 700;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-price {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 16rpx;
|
||||
margin-top: 16rpx;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
|
||||
.pay-label {
|
||||
font-size: 28rpx;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
|
||||
.pay-total {
|
||||
font-size: 28rpx;
|
||||
color: #ff19a0;
|
||||
.sales-info {
|
||||
.sales-count {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
text-align: justify;
|
||||
color: #3D3D3D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.payment-method-cell {
|
||||
.payment-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.payment-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.payment-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.payment-text {
|
||||
font-size: 24rpx;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
.payment-check {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.pay-type {
|
||||
.pay-icon {
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
|
||||
.pay-select-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.pay-type-text {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.good-list {
|
||||
padding: 20rpx;
|
||||
|
||||
.good-img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.good-num {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -752,71 +391,49 @@ export default {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0px -2px 10px 0px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.cancel-btn {
|
||||
flex: 1;
|
||||
height: 92rpx;
|
||||
border-radius: 92rpx;
|
||||
border: 2rpx solid #ff19a0;
|
||||
background: #fff;
|
||||
.price-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
|
||||
.cancel-btn-text {
|
||||
font-size: 30rpx;
|
||||
.current-price {
|
||||
font-size: 40rpx;
|
||||
color: #ff19a0;
|
||||
font-weight: 500;
|
||||
font-weight: 700;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.pay-btn {
|
||||
flex: 1;
|
||||
height: 92rpx;
|
||||
border-radius: 92rpx;
|
||||
flex: 0 0 auto;
|
||||
height: 72rpx;
|
||||
padding: 0 40rpx;
|
||||
border-radius: 72rpx;
|
||||
background: #ff19a0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.pay-btn-text {
|
||||
font-size: 30rpx;
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sliver-content {
|
||||
padding: 16rpx 0;
|
||||
|
||||
.sliver-item {
|
||||
padding: 52rpx 0;
|
||||
margin: 0 52rpx;
|
||||
width: calc(100% - 52rpx * 2);
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1rpx solid #f7f3f7;
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.sliver-btn {
|
||||
width: 630rpx;
|
||||
height: 92rpx;
|
||||
background: #fe019b;
|
||||
border-radius: 92rpx;
|
||||
margin: 18rpx auto 10rpx;
|
||||
}
|
||||
}
|
||||
.full-width-img {
|
||||
width: calc(100% - 40rpx);
|
||||
margin: 0 20rpx;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@ -2,9 +2,15 @@
|
||||
<view class="order-create-container">
|
||||
<view class="flex-center order-status">
|
||||
<!-- 待支付 -->
|
||||
<template v-if="orderData.status === SHOP_ORDER_UNPAY && !orderData.tui_status">
|
||||
<template
|
||||
v-if="orderData.status === SHOP_ORDER_UNPAY && !orderData.tui_status"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_unpay.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_unpay.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">待支付</text>
|
||||
</view>
|
||||
<view v-if="countDownTime > 0" class="fs-24 app-fc-main status-tips">
|
||||
@ -16,31 +22,47 @@
|
||||
</template>
|
||||
|
||||
<!-- 待发货 -->
|
||||
<template v-if="orderData.status === SHOP_ORDER_UNSLIVER && !orderData.tui_status">
|
||||
<template
|
||||
v-if="orderData.status === SHOP_ORDER_UNSLIVER && !orderData.tui_status"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_ungo.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_ungo.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">待预约</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips">
|
||||
已付款,待预约
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips"> 已付款,待预约 </view>
|
||||
</template>
|
||||
|
||||
<!-- 待收货 -->
|
||||
<template v-if="
|
||||
<template
|
||||
v-if="
|
||||
orderData.status === SHOP_ORDER_UNRECEIVE && !orderData.tui_status
|
||||
">
|
||||
"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_go.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_go.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">待收货</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips"> 已发货,等待收货 </view>
|
||||
</template>
|
||||
|
||||
<!-- 已签收 -->
|
||||
<template v-if="orderData.status === SHOP_ORDER_UNREMARK && !orderData.tui_status">
|
||||
<template
|
||||
v-if="orderData.status === SHOP_ORDER_UNREMARK && !orderData.tui_status"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_done.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_done.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">已签收</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips">
|
||||
@ -49,17 +71,29 @@
|
||||
</template>
|
||||
|
||||
<!-- 已完成 -->
|
||||
<template v-if="orderData.status === SHOP_ORDER_DONE && !orderData.tui_status">
|
||||
<template
|
||||
v-if="orderData.status === SHOP_ORDER_DONE && !orderData.tui_status"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_done.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_done.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">已完成</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 已取消 -->
|
||||
<template v-if="orderData.status === SHOP_ORDER_CANCEL && !orderData.tui_status">
|
||||
<template
|
||||
v-if="orderData.status === SHOP_ORDER_CANCEL && !orderData.tui_status"
|
||||
>
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_cancel.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_cancel.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">已取消</text>
|
||||
</view>
|
||||
</template>
|
||||
@ -67,7 +101,11 @@
|
||||
<!-- 申请售后-等待平台确认 -->
|
||||
<template v-if="orderData.tui_status === SHOP_ORDER_AFTERSALE">
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/refund_undo.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/refund_undo.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">等待平台确认</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips">
|
||||
@ -78,7 +116,11 @@
|
||||
<!-- 申请售后-退款成功 -->
|
||||
<template v-if="orderData.tui_status === SHOP_ORDER_AFTERSALE_DONE">
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_done.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_done.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">退款成功</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main status-tips">
|
||||
@ -89,16 +131,23 @@
|
||||
<!-- 申请售后-退款驳回 -->
|
||||
<template v-if="orderData.tui_status === SHOP_ORDER_AFTERSALE_REJECT">
|
||||
<view class="flex-row-center">
|
||||
<image class="status-icon" src="./static/order_cancel.png" mode="widthFix" />
|
||||
<image
|
||||
class="status-icon"
|
||||
src="./static/order_cancel.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<text class="fs-36 app-fc-main app-font-bold">退款驳回</text>
|
||||
</view>
|
||||
<view class="fs-24 app-fc-main flex-center refund-btn" @click="showRefundModal = true">
|
||||
<view
|
||||
class="fs-24 app-fc-main flex-center refund-btn"
|
||||
@click="showRefundModal = true"
|
||||
>
|
||||
查看驳回原因
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<view class="info-cell address-info-cell">
|
||||
<view v-if="orderData.address" class="info-cell address-info-cell">
|
||||
<view class="address-content">
|
||||
<view class="address-row-first">
|
||||
<image class="address-icon" src="@/static/images/address.png" />
|
||||
@ -145,16 +194,28 @@
|
||||
<!-- 商品信息 -->
|
||||
<view class="info-cell goods-info-cell">
|
||||
<template>
|
||||
<view class="goods-item" v-for="(item, index) in orderData.products" :key="index">
|
||||
<image class="goods-img" :src="item.product_pic" mode="aspectFill" @click="jumpToGoodDetails(item)" />
|
||||
<view class="goods-content" @click="jumpToGoodDetails(item)">
|
||||
<view
|
||||
class="goods-item"
|
||||
v-for="(item, index) in orderData.products"
|
||||
:key="index"
|
||||
>
|
||||
<image
|
||||
class="goods-img"
|
||||
:src="item.product_pic"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="goods-content" >
|
||||
<view class="goods-row-first">
|
||||
<view class="goods-name">{{ item.product_name || "" }}</view>
|
||||
<text class="goods-price">¥{{ item.product_actual_price || 0 }}</text>
|
||||
<text class="goods-price"
|
||||
>¥{{ item.product_actual_price || 0 }}</text
|
||||
>
|
||||
</view>
|
||||
<view class="goods-row-second">
|
||||
<view class="goods-spec">
|
||||
{{ item.shuxing_name || "" }}{{ item.shuxing_name && item.price_name ? ";" : "" }}{{ item.price_name || "" }}
|
||||
{{ item.shuxing_name || ""
|
||||
}}{{ item.shuxing_name && item.price_name ? ";" : ""
|
||||
}}{{ item.price_name || "" }}
|
||||
</view>
|
||||
<text class="goods-count">共{{ item.number || 1 }}件</text>
|
||||
</view>
|
||||
@ -165,11 +226,13 @@
|
||||
|
||||
<view class="info-cell pay-cell">
|
||||
<view class="flex-row-between pay-price">
|
||||
<text class="pay-label">
|
||||
商品总价
|
||||
</text>
|
||||
<text class="pay-label"> 商品总价 </text>
|
||||
<text class="pay-total">
|
||||
¥{{ [SHOP_ORDER_AFTERSALE_DONE].includes(orderData.tui_status) ? refundPrice : orderData.actual_price }}
|
||||
¥{{
|
||||
[SHOP_ORDER_AFTERSALE_DONE].includes(orderData.tui_status)
|
||||
? refundPrice
|
||||
: orderData.actual_price
|
||||
}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
@ -196,15 +259,26 @@
|
||||
<text class="order-value">{{ formatTime(orderData.shou_time) }}</text>
|
||||
</view>
|
||||
<view
|
||||
v-if="[SHOP_ORDER_CANCEL].includes(orderData.status) && !orderData.tui_status && orderData.quxiao_time"
|
||||
class="flex-row-between order-row">
|
||||
v-if="
|
||||
[SHOP_ORDER_CANCEL].includes(orderData.status) &&
|
||||
!orderData.tui_status &&
|
||||
orderData.quxiao_time
|
||||
"
|
||||
class="flex-row-between order-row"
|
||||
>
|
||||
<text class="order-label">取消时间</text>
|
||||
<text class="order-value">{{ formatTime(orderData.quxiao_time) }}</text>
|
||||
</view>
|
||||
<view v-if="
|
||||
[SHOP_ORDER_AFTERSALE, SHOP_ORDER_AFTERSALE_DONE, SHOP_ORDER_AFTERSALE_REJECT].includes(orderData.tui_status) &&
|
||||
orderData.tui_yuanyin
|
||||
" class="flex-row-between order-row">
|
||||
<view
|
||||
v-if="
|
||||
[
|
||||
SHOP_ORDER_AFTERSALE,
|
||||
SHOP_ORDER_AFTERSALE_DONE,
|
||||
SHOP_ORDER_AFTERSALE_REJECT,
|
||||
].includes(orderData.tui_status) && orderData.tui_yuanyin
|
||||
"
|
||||
class="flex-row-between order-row"
|
||||
>
|
||||
<text class="order-label">售后事项</text>
|
||||
<text class="order-value">{{ orderData.tui_yuanyin }}</text>
|
||||
</view>
|
||||
@ -241,33 +315,47 @@
|
||||
|
||||
<view class="place-view"></view>
|
||||
|
||||
<view v-if="
|
||||
<view
|
||||
v-if="
|
||||
[
|
||||
SHOP_ORDER_UNPAY,
|
||||
SHOP_ORDER_UNSLIVER,
|
||||
SHOP_ORDER_UNRECEIVE,
|
||||
SHOP_ORDER_DONE,
|
||||
SHOP_ORDER_UNREMARK
|
||||
SHOP_ORDER_UNREMARK,
|
||||
].includes(orderData.status)
|
||||
&& showBeforeSaleOrderStatus
|
||||
" class="bottom-view">
|
||||
"
|
||||
class="bottom-view"
|
||||
:class="{ 'two-buttons': showTwoButtons }"
|
||||
>
|
||||
<!-- 待支付 -->
|
||||
<template v-if="[SHOP_ORDER_UNPAY].includes(orderData.status)">
|
||||
<template
|
||||
v-if="
|
||||
[SHOP_ORDER_UNPAY].includes(orderData.status) &&
|
||||
showBeforeSaleOrderStatus
|
||||
"
|
||||
>
|
||||
<view class="handle-btn" @click.stop="showCancelModal = true">
|
||||
<text class="fs-32 btnColor" style="color: #FF19A0;">取消订单</text>
|
||||
<text class="fs-32 btnColor" style="color: #ff19a0">取消订单</text>
|
||||
</view>
|
||||
<view class="handle-btn" @click.stop="pay">
|
||||
<view class="handle-btn" @click.stop="pay(orderData)">
|
||||
<text class="fs-32 btnColor">立即支付</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 待发货 -->
|
||||
<template v-if="[SHOP_ORDER_UNSLIVER].includes(orderData.status)">
|
||||
<!-- 抖音退款组件 -->
|
||||
<view class="refund-btn-wrapper">
|
||||
<!-- 待发货(待预约) -->
|
||||
<template
|
||||
v-if="
|
||||
[SHOP_ORDER_UNSLIVER].includes(orderData.status) &&
|
||||
showBeforeSaleOrderStatus
|
||||
"
|
||||
>
|
||||
<!-- 抖音退款组件 - 只有在没有售后状态或售后被驳回时显示 -->
|
||||
<view class="handle-btn refund-btn">
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<pay-button-sdk
|
||||
mode=1
|
||||
:order-id="orderData.order_no || orderData.order_id"
|
||||
:mode="1"
|
||||
:order-id="orderData.order_no"
|
||||
:order-status="1"
|
||||
:refund-total-amount="Math.round((orderData.actual_price || 0) * 100)"
|
||||
:apply-refund-params="{
|
||||
@ -277,11 +365,16 @@
|
||||
afterSaleType: 3,
|
||||
needRefundPackFee: true
|
||||
}"
|
||||
style="width:280rpx;height:100rpx;text-align:center;line-height: 100rpx;"
|
||||
style="width:100%;height:100%;display:block;position:relative;z-index:999;"
|
||||
@refund="handleRefundSuccess"
|
||||
@error="handleRefundError"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<text class="fs-32 btnColor" style="color: #ff19a0" @click.stop="remindRefund(orderData.order_id)">申请退款</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<!-- 立即预约按钮 -->
|
||||
<view class="handle-btn" @click.stop="remindSliver">
|
||||
<text class="fs-32 btnColor">立即预约</text>
|
||||
</view>
|
||||
@ -296,9 +389,9 @@
|
||||
<!-- <view v-if="orderData.order_type !== ORDER_TYPE_BYCAR" class="handle-btn" @click.stop="getSliverInfo">
|
||||
<text class="fs-32 btnColor" style="color: #FF19A0;">查看物流</text>
|
||||
</view> -->
|
||||
<view class="handle-btn" @click.stop="confirmSliver">
|
||||
<!-- <view class="handle-btn" @click.stop="confirmSliver">
|
||||
<text class="fs-32 btnColor">确认收货</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<!-- 已签收待评价 -->
|
||||
@ -316,28 +409,66 @@
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<good-info-modal v-if="showGoodInfoModal" :goods="orderData.goods_list" @close="showGoodInfoModal = false"
|
||||
@clickGoodImg="jumpToGoodDetails" @clickGoodInfo="jumpToGoodDetails" />
|
||||
<good-info-modal
|
||||
v-if="showGoodInfoModal"
|
||||
:goods="orderData.goods_list"
|
||||
@close="showGoodInfoModal = false"
|
||||
@clickGoodImg="jumpToGoodDetails"
|
||||
@clickGoodInfo="jumpToGoodDetails"
|
||||
/>
|
||||
|
||||
<recharge-coupon-modal v-if="showCouponModal" :couponList="couponList" :price="payPrice" :showOptBtn="true"
|
||||
@useCoupon="useCoupon" @close="showCouponModal = false" />
|
||||
<recharge-coupon-modal
|
||||
v-if="showCouponModal"
|
||||
:couponList="couponList"
|
||||
:price="payPrice"
|
||||
:showOptBtn="true"
|
||||
@useCoupon="useCoupon"
|
||||
@close="showCouponModal = false"
|
||||
/>
|
||||
|
||||
<contact-modal v-if="showContact" :data="configInfo" @close="showContact = false" />
|
||||
<contact-modal
|
||||
v-if="showContact"
|
||||
:data="configInfo"
|
||||
@close="showContact = false"
|
||||
/>
|
||||
|
||||
<pop-up-modal v-if="showCancelModal" content="确定要退款吗?" @confirm="orderCancel"
|
||||
@cancel="showCancelModal = false" />
|
||||
<pop-up-modal
|
||||
v-if="showCancelModal"
|
||||
content="确定要退款吗?"
|
||||
@confirm="orderCancel"
|
||||
@cancel="showCancelModal = false"
|
||||
/>
|
||||
|
||||
<success-modal v-if="showRemindSliver" title="提醒成功" message="已通知商家,请耐心等待商家发货" @close="showRemindSliver = false"
|
||||
@ok="showRemindSliver = false" />
|
||||
<success-modal
|
||||
v-if="showRemindSliver"
|
||||
title="提醒成功"
|
||||
message="已通知商家,请耐心等待商家发货"
|
||||
@close="showRemindSliver = false"
|
||||
@ok="showRemindSliver = false"
|
||||
/>
|
||||
|
||||
<success-modal v-if="showRefundModal" class="reject-modal" :showImg="false" title="驳回原因"
|
||||
:message="orderData.tui_msg" @close="showRefundModal = false" @ok="showRefundModal = false" />
|
||||
<success-modal
|
||||
v-if="showRefundModal"
|
||||
class="reject-modal"
|
||||
:showImg="false"
|
||||
title="驳回原因"
|
||||
:message="orderData.tui_msg"
|
||||
@close="showRefundModal = false"
|
||||
@ok="showRefundModal = false"
|
||||
/>
|
||||
|
||||
<sliver-info v-if="showSliverRouteModal" :orderId="orderId" :orderInfo="orderData"
|
||||
@close="showSliverRouteModal = false" />
|
||||
<sliver-info
|
||||
v-if="showSliverRouteModal"
|
||||
:orderId="orderId"
|
||||
:orderInfo="orderData"
|
||||
@close="showSliverRouteModal = false"
|
||||
/>
|
||||
|
||||
<call-modal :phone-number="managerPhoneNum" v-if="isShowCallManagerModal"
|
||||
@close="isShowCallManagerModal = false" />
|
||||
<call-modal
|
||||
:phone-number="managerPhoneNum"
|
||||
v-if="isShowCallManagerModal"
|
||||
@close="isShowCallManagerModal = false"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -355,18 +486,17 @@ import DraggableContact from "@/components/DraggableContact.vue";
|
||||
import {
|
||||
walletTransaction,
|
||||
cancelPetOrderRefund,
|
||||
cancelPetOrderMall
|
||||
cancelPetOrderMall,
|
||||
cancelUnpaid
|
||||
} from "../../../api/login";
|
||||
|
||||
|
||||
import {
|
||||
getConfig
|
||||
} from "../../../api/config";
|
||||
import { getConfig } from "../../../api/config";
|
||||
import {
|
||||
cancelOrder,
|
||||
confirmOrder,
|
||||
getShopOrderDetails,
|
||||
payOrder,
|
||||
deleteCart,
|
||||
remindOrder,
|
||||
} from "../../../api/shop";
|
||||
import {
|
||||
@ -381,12 +511,9 @@ import {
|
||||
SHOP_ORDER_UNREMARK,
|
||||
ORDER_TYPE_ADDRESS,
|
||||
ORDER_TYPE_BYCAR,
|
||||
ORDER_TYPE_BYPET
|
||||
ORDER_TYPE_BYPET,
|
||||
} from "@/constants/app.business";
|
||||
import {
|
||||
jumpToWeChat,
|
||||
imgPrefix
|
||||
} from "@/utils/common";
|
||||
import { jumpToWeChat, imgPrefix } from "@/utils/common";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -398,7 +525,7 @@ import {
|
||||
SuccessModal,
|
||||
SliverInfo,
|
||||
CallModal,
|
||||
DraggableContact
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -418,9 +545,12 @@ import {
|
||||
orderData: {},
|
||||
showGoodInfoModal: false,
|
||||
showCouponModal: false,
|
||||
couponList: Array.from({
|
||||
length: 5
|
||||
}, (v, k) => k),
|
||||
couponList: Array.from(
|
||||
{
|
||||
length: 5,
|
||||
},
|
||||
(v, k) => k
|
||||
),
|
||||
couponInfo: null,
|
||||
showContact: false,
|
||||
configInfo: {
|
||||
@ -451,6 +581,24 @@ import {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 判断是否显示两个按钮
|
||||
showTwoButtons() {
|
||||
// 待支付状态显示两个按钮
|
||||
if (
|
||||
this.orderData.status === SHOP_ORDER_UNPAY &&
|
||||
this.showBeforeSaleOrderStatus
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
// 待发货状态且没有售后时显示两个按钮
|
||||
if (
|
||||
this.orderData.status === SHOP_ORDER_UNSLIVER &&
|
||||
this.showBeforeSaleOrderStatus
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
goodsImgs() {
|
||||
return (this.orderData?.goods_list || [])
|
||||
.map((item) => item.goods_pic)
|
||||
@ -469,32 +617,34 @@ import {
|
||||
return +this.orderData?.refund_fee || 0;
|
||||
},
|
||||
showBeforeSaleOrderStatus() {
|
||||
return !this.orderData.tui_status || this.orderData.tui_status === SHOP_ORDER_AFTERSALE_REJECT
|
||||
return (
|
||||
!this.orderData.tui_status ||
|
||||
this.orderData.tui_status === SHOP_ORDER_AFTERSALE_REJECT
|
||||
);
|
||||
},
|
||||
carNumber() {
|
||||
return this.orderData?.car_info?.car_no || ''
|
||||
return this.orderData?.car_info?.car_no || "";
|
||||
},
|
||||
managerPhoneNum() {
|
||||
return this.orderData?.guanjia_info?.mobile || ''
|
||||
return this.orderData?.guanjia_info?.mobile || "";
|
||||
},
|
||||
managerName() {
|
||||
return this.orderData?.guanjia_info?.name || ''
|
||||
return this.orderData?.guanjia_info?.name || "";
|
||||
},
|
||||
guanjiaPic() {
|
||||
return this.orderData?.guanjia_info?.guanjia_pic || ''
|
||||
return this.orderData?.guanjia_info?.guanjia_pic || "";
|
||||
},
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
this.orderId = options.id;
|
||||
this.getOrderDetail();
|
||||
|
||||
// 初始化联系客服按钮位置
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const windowHeight = systemInfo.windowHeight;
|
||||
// 计算底部距离:calc(35vh - 130rpx - 48rpx) 转换为rpx
|
||||
// 35vh = windowHeight * 0.35,转换为rpx (750rpx = windowHeight px)
|
||||
const vh35InRpx = (windowHeight * 0.35 / windowHeight) * 750;
|
||||
const vh35InRpx = ((windowHeight * 0.35) / windowHeight) * 750;
|
||||
this.contactBtnBottom = vh35InRpx - 130 - 48;
|
||||
},
|
||||
beforeDestroy() {
|
||||
@ -517,24 +667,6 @@ import {
|
||||
}
|
||||
});
|
||||
},
|
||||
selectOption1(v) {
|
||||
this.WeChat = v
|
||||
this.wallet = ''
|
||||
console.log(this.WeChat)
|
||||
this.selected1 = false;
|
||||
this.selected2 = true;
|
||||
this.selected3 = true;
|
||||
this.selected4 = false;
|
||||
},
|
||||
selectOption2(v) {
|
||||
this.WeChat = ''
|
||||
this.wallet = v
|
||||
console.log(this.wallet)
|
||||
this.selected1 = true;
|
||||
this.selected2 = false;
|
||||
this.selected3 = false;
|
||||
this.selected4 = true;
|
||||
},
|
||||
coutDown() {
|
||||
setTimeout(() => {
|
||||
if (this.countDownTime > 0) {
|
||||
@ -548,9 +680,68 @@ import {
|
||||
useCoupon(data) {
|
||||
this.showCouponModal = false;
|
||||
this.couponInfo = {
|
||||
...data
|
||||
...data,
|
||||
};
|
||||
},
|
||||
remindRefund(id) {
|
||||
const data = {
|
||||
id: Number(id),
|
||||
};
|
||||
uni.showLoading({
|
||||
icon: "none",
|
||||
title: "处理中",
|
||||
mask: true,
|
||||
});
|
||||
cancelPetOrderMall(data).then((res) => {
|
||||
uni.hideLoading();
|
||||
const plugin = tt.requirePlugin("lifeServicePlugin");
|
||||
plugin.applyRefund({
|
||||
goodsList: res.data.goodsList,
|
||||
outOrderNo: res.data.outOrderNo,
|
||||
refundInfo: res.data.refundInfo,
|
||||
success: (res) => {
|
||||
uni.showToast({
|
||||
title: '退款申请已提交',
|
||||
icon: 'success'
|
||||
});
|
||||
this.getOrderDetail();
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log("退款失败:", err);
|
||||
// 处理session过期错误
|
||||
if (err && err.errMsg && err.errMsg.includes('session已过期')) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '会话已过期,请重新登录后再试',
|
||||
showCancel: false,
|
||||
confirmText: '确定',
|
||||
success: () => {
|
||||
// 清除当前用户信息并跳转到登录页
|
||||
this.$store.dispatch("user/deleteToken");
|
||||
this.$store.dispatch("user/clearUserInfo");
|
||||
uni.clearStorageSync();
|
||||
uni.reLaunch({
|
||||
url: "/pages/client/auth/index"
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: err?.errMsg || err?.msg || '退款失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
console.error("获取退款信息失败:", err);
|
||||
uni.showToast({
|
||||
title: err?.msg || '获取退款信息失败',
|
||||
icon: 'none'
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// 取消订单
|
||||
orderCancel() {
|
||||
@ -560,9 +751,9 @@ import {
|
||||
mask: true,
|
||||
});
|
||||
const data = {
|
||||
order_id: Number(this.orderId),
|
||||
}
|
||||
cancelPetOrderMall(data).then((res) => {
|
||||
id: Number(this.orderId),
|
||||
};
|
||||
cancelUnpaid(data).then((res) => {
|
||||
uni.hideLoading();
|
||||
this.showCancelModal = false;
|
||||
this.getOrderDetail();
|
||||
@ -581,49 +772,40 @@ import {
|
||||
});
|
||||
},
|
||||
// 立即支付
|
||||
pay() {
|
||||
// if (this.WeChat === undefined && this.wallet === undefined) {
|
||||
// uni.showToast({
|
||||
// title: '请选择支付方式',
|
||||
// icon: "none",
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
pay(data) {
|
||||
uni.showLoading({
|
||||
icon: "none",
|
||||
title: "支付中",
|
||||
mask: true,
|
||||
});
|
||||
payOrder({
|
||||
type:4,
|
||||
total_fee: Number(this.orderData.actual_price),
|
||||
order_id:this.orderData.order_id,
|
||||
order_no:this.orderData.order_no
|
||||
}).then((res) => {
|
||||
tt.pay({
|
||||
orderInfo: {
|
||||
order_id:res.data.orderInfo.order_id,
|
||||
order_token:res.data.orderInfo.order_token,
|
||||
},
|
||||
service:5,
|
||||
success: (res) => {
|
||||
// console.log(data,'-?')
|
||||
|
||||
const plugin = tt.requirePlugin('lifeServicePlugin');
|
||||
// 先隐藏loading,让插件显示自己的弹窗
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: "支付成功",
|
||||
icon: "none",
|
||||
});
|
||||
plugin.continueToPay({
|
||||
orderId:data.douyin_order_id, // 内部订单号
|
||||
// outOrderNo: "outOrderNo", // 外部订单号 2个订单号必填一个
|
||||
success: (res) => {
|
||||
const { orderId, outOrderNo } = res;
|
||||
console.log("success res", res);
|
||||
console.log("orderId", orderId, "outOrderNo", outOrderNo);
|
||||
this.getOrderDetail();
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading();
|
||||
fail: (res) => {
|
||||
const { orderId, outOrderNo, errNo, errMsg, errLogId } = res;
|
||||
if (errLogId) {
|
||||
console.log("查询订单信息失败", errNo, errMsg, errLogId);
|
||||
}
|
||||
if (orderId || outOrderNo) {
|
||||
console.log("支付失败", errNo, errMsg, orderId, outOrderNo);
|
||||
}
|
||||
uni.showToast({
|
||||
title: err?.msg || "支付失败",
|
||||
title: errMsg || "支付失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
// 提醒发货
|
||||
@ -651,7 +833,7 @@ import {
|
||||
title: "暂无评价",
|
||||
icon: "none",
|
||||
});
|
||||
return
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/remark/details?remarkId=${this.orderData.pinglun_id}`,
|
||||
@ -704,7 +886,10 @@ import {
|
||||
// 按钮高度约120rpx
|
||||
const btnHeight = 120;
|
||||
|
||||
newBottom = Math.max(0, Math.min(newBottom, windowHeight * 2 - btnHeight));
|
||||
newBottom = Math.max(
|
||||
0,
|
||||
Math.min(newBottom, windowHeight * 2 - btnHeight)
|
||||
);
|
||||
|
||||
// right始终保持为0
|
||||
this.contactBtnRight = 0;
|
||||
@ -727,15 +912,15 @@ import {
|
||||
},
|
||||
// 退款成功回调
|
||||
handleRefundSuccess(e) {
|
||||
console.log('退款成功:', e.detail)
|
||||
uni.showToast({ title: '退款申请已提交', icon: 'success' })
|
||||
this.getOrderDetail()
|
||||
console.log("退款成功:", e.detail);
|
||||
uni.showToast({ title: "退款申请已提交", icon: "success" });
|
||||
this.getOrderDetail();
|
||||
},
|
||||
|
||||
// 退款错误回调
|
||||
handleRefundError(e) {
|
||||
console.error('退款错误:', e.detail)
|
||||
uni.showToast({ title: e.detail.message || '退款失败', icon: 'none' })
|
||||
console.error("退款错误:", e.detail);
|
||||
uni.showToast({ title: e.detail.message || "退款失败", icon: "none" });
|
||||
},
|
||||
|
||||
formatSecond(seconds) {
|
||||
@ -755,7 +940,7 @@ import {
|
||||
height: 100%;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background: #F7F8FA;
|
||||
background: #f7f8fa;
|
||||
padding-top: 0;
|
||||
|
||||
.order-status {
|
||||
@ -822,7 +1007,7 @@ import {
|
||||
|
||||
.address-name {
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
|
||||
.address-phone {
|
||||
margin-left: 8rpx;
|
||||
@ -847,14 +1032,13 @@ import {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
|
||||
.sliver-text {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
@ -898,18 +1082,18 @@ import {
|
||||
.goods-name {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
line-height: 40rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// white-space: nowrap;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
@ -958,7 +1142,7 @@ import {
|
||||
|
||||
.payment-text {
|
||||
font-size: 24rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
@ -981,19 +1165,19 @@ import {
|
||||
|
||||
.pay-label {
|
||||
font-size: 24rpx;
|
||||
color: #9B939A;
|
||||
color: #9b939a;
|
||||
}
|
||||
|
||||
.pay-value {
|
||||
font-size: 24rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-row {
|
||||
.coupon-price {
|
||||
font-size: 28rpx;
|
||||
color: #FF19A0;
|
||||
color: #ff19a0;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
@ -1007,12 +1191,12 @@ import {
|
||||
|
||||
.pay-label {
|
||||
font-size: 28rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
|
||||
.pay-total {
|
||||
font-size: 28rpx;
|
||||
color: #FF19A0;
|
||||
color: #ff19a0;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
@ -1063,12 +1247,12 @@ import {
|
||||
|
||||
.order-label {
|
||||
font-size: 24rpx;
|
||||
color: #9B939A;
|
||||
color: #9b939a;
|
||||
}
|
||||
|
||||
.order-value {
|
||||
font-size: 24rpx;
|
||||
color: #3D3D3D;
|
||||
color: #3d3d3d;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1136,11 +1320,16 @@ import {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
justify-content: center;
|
||||
background-color: #ffffff;
|
||||
padding-top: 12rpx;
|
||||
align-items: center;
|
||||
|
||||
// 两个按钮时左右分布
|
||||
&.two-buttons {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.refund-btn-wrapper {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
@ -1167,10 +1356,62 @@ import {
|
||||
}
|
||||
}
|
||||
|
||||
// 最后一个按钮的特殊样式(优先级最高)
|
||||
// 退款按钮保持粉色边框白色背景样式
|
||||
.handle-btn.refund-btn {
|
||||
border: 2rpx solid #ff19a0 !important;
|
||||
background: transparent !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
|
||||
.btnColor {
|
||||
color: #ff19a0 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// 确保 pay-button 组件居中显示
|
||||
::v-deep pay-button {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
// 确保 pay-button-sdk 组件居中显示
|
||||
::v-deep pay-button-sdk {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
// 确保组件内部的所有元素都居中
|
||||
::v-deep * {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 最后一个按钮(立即预约)保持粉色背景白色文字样式
|
||||
.handle-btn:last-child {
|
||||
border: 2rpx solid #FF19A0 !important;
|
||||
background: #FF19A0 !important;
|
||||
border: 2rpx solid #ff19a0 !important;
|
||||
background: #ff19a0 !important;
|
||||
|
||||
text {
|
||||
color: #fff !important;
|
||||
@ -1185,6 +1426,22 @@ import {
|
||||
flex: 1 !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
// 确保 pay-button 组件正确显示
|
||||
::v-deep pay-button {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
// 确保组件内部所有元素都可见
|
||||
::v-deep pay-button * {
|
||||
display: block !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-float-btn {
|
||||
@ -1199,8 +1456,8 @@ import {
|
||||
}
|
||||
|
||||
.contact-btn {
|
||||
color: #FFFFFF;
|
||||
background-color: #FF19A0;
|
||||
color: #ffffff;
|
||||
background-color: #ff19a0;
|
||||
border-radius: 257px;
|
||||
padding: 6rpx 8rpx;
|
||||
transform: translateY(-8px);
|
||||
@ -1244,6 +1501,5 @@ import {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
class="flex-column-start news-item">
|
||||
<order-item :data="data" @disableScroll="disableScrollAction" @cancelOrder="cancelOrderAction"
|
||||
@refund="handleRefundFromItem" @concactService="jumpToWeChat" @confirmSliver="confirmSliver" @remindSilver="remindSliver" @pay="pay"
|
||||
@afterSale="afterSale" @checkSliver="checkSliver" @remark="remark" @remarkDetails="remarkDetails"
|
||||
@checkSliver="checkSliver" @remark="remark" @remarkDetails="remarkDetails"
|
||||
@jumpToDetails="jumpToDetails" />
|
||||
</view>
|
||||
<uni-load-more v-if="isLoading || (!isLoading && total && total === list.length)"
|
||||
@ -101,7 +101,7 @@ import ContactModal from "@/components/ContactModal.vue";
|
||||
import SliverInfo from "./components/SliverInfo.vue";
|
||||
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
import { walletTransaction, cancelPetOrderRefund, cancelPetOrderMall } from "../../../api/login";
|
||||
import { walletTransaction, cancelPetOrderRefund, cancelPetOrderMall,cancelUnpaid } from "../../../api/login";
|
||||
|
||||
|
||||
import {
|
||||
@ -250,14 +250,14 @@ export default {
|
||||
mask: true,
|
||||
});
|
||||
const data = {
|
||||
id: this.orderInfo.order_id,
|
||||
id: Number(this.orderInfo.order_id),
|
||||
// business_type:1
|
||||
}
|
||||
|
||||
// 判断是取消订单还是退款
|
||||
const apiPromise = this.cancelModalContent.includes('退款')
|
||||
? cancelPetOrderRefund(data)
|
||||
: cancelPetOrderMall(data);
|
||||
? cancelUnpaid(data)
|
||||
: cancelUnpaid(data);
|
||||
|
||||
apiPromise.then((res) => {
|
||||
uni.hideLoading();
|
||||
@ -308,18 +308,21 @@ export default {
|
||||
title: "支付中",
|
||||
mask: true,
|
||||
});
|
||||
console.log(data,'-?')
|
||||
|
||||
const plugin = tt.requirePlugin('tta5a3d31e3aecfb9b11');
|
||||
const plugin = tt.requirePlugin('lifeServicePlugin');
|
||||
// 先隐藏loading,让插件显示自己的弹窗
|
||||
uni.hideLoading();
|
||||
plugin.continueToPay({
|
||||
orderId: "orderId", // 内部订单号
|
||||
outOrderNo: "outOrderNo", // 外部订单号 2个订单号必填一个
|
||||
orderId:data.douyin_order_id, // 内部订单号
|
||||
// outOrderNo: "outOrderNo", // 外部订单号 2个订单号必填一个
|
||||
success: (res) => {
|
||||
const { orderId, outOrderNo } = res;
|
||||
console.log("success res", res);
|
||||
console.log("orderId", orderId, "outOrderNo", outOrderNo);
|
||||
this.reloadData();
|
||||
},
|
||||
fail: (res) => {
|
||||
uni.hideLoading();
|
||||
const { orderId, outOrderNo, errNo, errMsg, errLogId } = res;
|
||||
if (errLogId) {
|
||||
console.log("查询订单信息失败", errNo, errMsg, errLogId);
|
||||
@ -327,6 +330,11 @@ plugin.continueToPay({
|
||||
if (orderId || outOrderNo) {
|
||||
console.log("支付失败", errNo, errMsg, orderId, outOrderNo);
|
||||
}
|
||||
// 隐藏抖音的报错信息,显示自定义中文提示
|
||||
uni.showToast({
|
||||
title: "支付失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
// payOrder({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="goods-item" >
|
||||
<image class="goods-img" :src="getProductImage(data)" mode="aspectFill" />
|
||||
<view class="goods-item" :class="{ 'goods-item-home': isHome }">
|
||||
<image @click.stop="handleBuyNow" class="goods-img" :src="getProductImage(data)" mode="aspectFill" />
|
||||
<view class=" fs-24 app-fc-main goods-name">
|
||||
{{ data.product.product_name || "" }}
|
||||
</view>
|
||||
@ -43,6 +43,10 @@
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
isHome: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -70,7 +74,6 @@
|
||||
if (data.product_pic) {
|
||||
return data.product_pic;
|
||||
}
|
||||
|
||||
// Try to parse image_list from attr_key_value_map
|
||||
if (data.product?.attr_key_value_map?.image_list) {
|
||||
try {
|
||||
@ -94,7 +97,7 @@
|
||||
.goods-item {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx;
|
||||
padding: 2rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 22rpx;
|
||||
position: relative;
|
||||
@ -102,15 +105,24 @@
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
||||
&.goods-item-home {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
display: block;
|
||||
// width: 260rpx;
|
||||
height: 260rpx;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 320rpx;
|
||||
// max-width: 100%;
|
||||
border-radius: 16rpx;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
&.goods-item-home .goods-img {
|
||||
height: 145px;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
margin: 20rpx 0;
|
||||
// overflow: hidden;
|
||||
|
||||
@ -170,6 +170,8 @@ export default {
|
||||
total: 0,
|
||||
page: 1,
|
||||
size: 10,
|
||||
nextCursor: '',
|
||||
hasMore: true,
|
||||
showModal: false,
|
||||
addGoodInfo: null,
|
||||
showContactModal: false,
|
||||
@ -263,6 +265,9 @@ export default {
|
||||
initData() {
|
||||
this.getCategoryList();
|
||||
this.page = 1;
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.goodsList = [];
|
||||
this.getGoodsList();
|
||||
this.getCartListData();
|
||||
},
|
||||
@ -281,13 +286,25 @@ export default {
|
||||
// 商品列表
|
||||
getGoodsList() {
|
||||
if (this.isLoading) return;
|
||||
if (!this.hasMore && this.page > 1) return;
|
||||
this.isLoading = true;
|
||||
getGoodsListData({
|
||||
type: this.selectCategoryId ? this.selectCategoryId : 0,
|
||||
cursor: this.nextCursor,
|
||||
})
|
||||
.then((res) => {
|
||||
const list = res?.data.data.products || [];
|
||||
const hasMore = res?.data.data.has_more;
|
||||
const nextCursor = res?.data.data.next_cursor || '';
|
||||
|
||||
if (this.page === 1) {
|
||||
this.goodsList = list;
|
||||
} else {
|
||||
this.goodsList = [...this.goodsList, ...list];
|
||||
}
|
||||
|
||||
this.hasMore = hasMore;
|
||||
this.nextCursor = nextCursor;
|
||||
this.total = res?.count || 0;
|
||||
})
|
||||
.finally(() => {
|
||||
@ -300,10 +317,12 @@ export default {
|
||||
this.page = 1;
|
||||
this.size = 10;
|
||||
this.total = 0;
|
||||
this.nextCursor = '';
|
||||
this.hasMore = true;
|
||||
this.getGoodsList();
|
||||
},
|
||||
onLoadMore() {
|
||||
if (!this.isLoading && this.total > this.goodsList.length) {
|
||||
if (!this.isLoading && this.hasMore) {
|
||||
this.page++;
|
||||
this.getGoodsList();
|
||||
}
|
||||
@ -378,20 +397,20 @@ export default {
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/order/create`,
|
||||
success: (res) => {
|
||||
// 通过eventChannel向被打开页面传送数据
|
||||
res.eventChannel.emit("createOrder", {
|
||||
goodList: [{
|
||||
goods_id:goodsData.product.out_id,
|
||||
product_pic: firstImageUrl,
|
||||
number:1,
|
||||
goods_name: goodsData.product.product_name,
|
||||
price_name: goodsData?.product.product_name,
|
||||
goods_price: goodsData.sku.actual_amount / 100
|
||||
}, ],
|
||||
});
|
||||
},
|
||||
url: `/pages/client/order/create?product_id=${goodsData.product.product_id}`,
|
||||
// success: (res) => {
|
||||
// // 通过eventChannel向被打开页面传送数据
|
||||
// res.eventChannel.emit("createOrder", {
|
||||
// goodList: [{
|
||||
// goods_id:goodsData.product.out_id,
|
||||
// product_pic: firstImageUrl,
|
||||
// number:1,
|
||||
// goods_name: goodsData.product.product_name,
|
||||
// price_name: goodsData?.product.product_name,
|
||||
// goods_price: goodsData.sku.actual_amount / 100
|
||||
// }, ],
|
||||
// });
|
||||
// },
|
||||
});
|
||||
},
|
||||
// 购物车列表
|
||||
@ -419,31 +438,31 @@ export default {
|
||||
// 立即购买
|
||||
handleBuyNow(good) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/order/create`,
|
||||
success: (res) => {
|
||||
// 通过 eventChannel 向被打开页面传送数据
|
||||
res.eventChannel.emit("createOrder", {
|
||||
goodList: [
|
||||
{
|
||||
goods_id: good.product_id,
|
||||
item_type: good.type,
|
||||
price_id: good.prices?.[0]?.price_id,
|
||||
price_desc: good.prices?.[0]?.price_desc,
|
||||
item_name: good.product_name,
|
||||
item_price: good.prices?.[0]?.actual_price,
|
||||
item_pic: good.product_pic,
|
||||
number: 1,
|
||||
product_id: good.product_id,
|
||||
product_name: good.product_name,
|
||||
product_pic: good.product_pic,
|
||||
goods_price: good.prices?.[0]?.actual_price / 100,
|
||||
product_price: good.prices?.[0]?.actual_price / 100,
|
||||
original_price: good.prices?.[0]?.original_price,
|
||||
yunfei: good.yunfei || 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
url: `/pages/client/order/create?product_id=${good.product.product_id}`,
|
||||
// success: (res) => {
|
||||
// // 通过 eventChannel 向被打开页面传送数据
|
||||
// res.eventChannel.emit("createOrder", {
|
||||
// goodList: [
|
||||
// {
|
||||
// goods_id: good.product_id,
|
||||
// item_type: good.type,
|
||||
// price_id: good.prices?.[0]?.price_id,
|
||||
// price_desc: good.prices?.[0]?.price_desc,
|
||||
// item_name: good.product_name,
|
||||
// item_price: good.prices?.[0]?.actual_price,
|
||||
// item_pic: good.product_pic,
|
||||
// number: 1,
|
||||
// product_id: good.product_id,
|
||||
// product_name: good.product_name,
|
||||
// product_pic: good.product_pic,
|
||||
// goods_price: good.prices?.[0]?.actual_price / 100,
|
||||
// product_price: good.prices?.[0]?.actual_price / 100,
|
||||
// original_price: good.prices?.[0]?.original_price,
|
||||
// yunfei: good.yunfei || 0,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// },
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -476,7 +495,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 32rpx;
|
||||
height: 88rpx;
|
||||
height: 80rpx;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
|
||||
@ -643,7 +662,6 @@ export default {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
margin-top: 40rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.goods-list-item {
|
||||
|
||||
335
src/utils/goodsCache.js
Normal file
335
src/utils/goodsCache.js
Normal file
@ -0,0 +1,335 @@
|
||||
/**
|
||||
* 商品数据缓存工具
|
||||
* 用于首页和分类页的商品列表缓存,避免重复请求相同数据
|
||||
*/
|
||||
|
||||
import { getGoodsListData } from '@/api/shop'
|
||||
|
||||
// 缓存存储对象
|
||||
const goodsCache = {
|
||||
// 首页商品缓存
|
||||
home: null,
|
||||
// 分类页商品缓存,key为分类ID
|
||||
category: {}
|
||||
}
|
||||
|
||||
// 缓存过期时间(5分钟,单位:毫秒)
|
||||
const CACHE_EXPIRE_TIME = 5 * 60 * 1000
|
||||
|
||||
/**
|
||||
* 计算数据的哈希值,用于判断数据是否有变化
|
||||
* @param {Array} data - 商品数据列表
|
||||
* @returns {string} 数据哈希值
|
||||
*/
|
||||
function calculateDataHash(data) {
|
||||
if (!data || !Array.isArray(data) || data.length === 0) {
|
||||
return 'empty'
|
||||
}
|
||||
|
||||
// 使用商品ID、价格、更新时间等关键信息计算哈希
|
||||
const keyData = data.map(item => {
|
||||
const product = item.product || item
|
||||
return `${product.product_id || product.id}-${product.updated_at || Date.now()}-${item.sku?.actual_amount || product.price || 0}`
|
||||
}).join('|')
|
||||
|
||||
// 简单的字符串哈希函数
|
||||
let hash = 0
|
||||
for (let i = 0; i < keyData.length; i++) {
|
||||
const char = keyData.charCodeAt(i)
|
||||
hash = ((hash << 5) - hash) + char
|
||||
hash = hash & hash // 转换为32位整数
|
||||
}
|
||||
return hash.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存的首页商品数据
|
||||
* @returns {Object|null} 缓存的商品数据,包含数据、哈希值和时间戳
|
||||
*/
|
||||
export function getHomeGoodsCache() {
|
||||
return goodsCache.home
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置首页商品缓存
|
||||
* @param {Array} data - 商品数据列表
|
||||
*/
|
||||
export function setHomeGoodsCache(data) {
|
||||
goodsCache.home = {
|
||||
data,
|
||||
hash: calculateDataHash(data),
|
||||
timestamp: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定分类的商品缓存
|
||||
* @param {Number|String} categoryId - 分类ID
|
||||
* @returns {Object|null} 缓存的商品数据
|
||||
*/
|
||||
export function getCategoryGoodsCache(categoryId) {
|
||||
return goodsCache.category[categoryId] || null
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置指定分类的商品缓存
|
||||
* @param {Number|String} categoryId - 分类ID
|
||||
* @param {Array} data - 商品数据列表
|
||||
*/
|
||||
export function setCategoryGoodsCache(categoryId, data) {
|
||||
goodsCache.category[categoryId] = {
|
||||
data,
|
||||
hash: calculateDataHash(data),
|
||||
timestamp: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查缓存是否有效
|
||||
* @param {Object} cache - 缓存对象
|
||||
* @returns {Boolean} 缓存是否有效
|
||||
*/
|
||||
function isCacheValid(cache) {
|
||||
if (!cache) return false
|
||||
|
||||
const now = Date.now()
|
||||
// 检查缓存是否过期
|
||||
if (now - cache.timestamp > CACHE_EXPIRE_TIME) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页商品数据(带缓存)
|
||||
* @param {Object} params - 请求参数
|
||||
* @param {Boolean} forceRefresh - 是否强制刷新
|
||||
* @returns {Promise} 商品数据
|
||||
*/
|
||||
export function getHomeGoodsWithCache(params, forceRefresh = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cache = getHomeGoodsCache()
|
||||
|
||||
// 如果有有效缓存且不强制刷新,先返回缓存数据
|
||||
if (!forceRefresh && isCacheValid(cache)) {
|
||||
// 先从缓存返回数据
|
||||
resolve({
|
||||
data: { data: { products: cache.data } },
|
||||
fromCache: true
|
||||
})
|
||||
}
|
||||
|
||||
// 无论是否有缓存,都请求最新数据进行对比
|
||||
getGoodsListData(params).then(res => {
|
||||
const newData = res?.data.data?.products || res?.data.data || []
|
||||
const hasMore = res?.data.data?.has_more
|
||||
const nextCursor = res?.data.data?.next_cursor || ''
|
||||
const newHash = calculateDataHash(newData)
|
||||
|
||||
// 检查数据是否有变化
|
||||
const hasChanged = !cache || cache.hash !== newHash
|
||||
|
||||
if (hasChanged || forceRefresh) {
|
||||
// 更新缓存
|
||||
setHomeGoodsCache(newData)
|
||||
|
||||
// 如果没有缓存或者数据有变化,返回最新数据
|
||||
if (!cache || forceRefresh) {
|
||||
resolve({
|
||||
...res,
|
||||
data: {
|
||||
...res.data,
|
||||
data: {
|
||||
...res.data.data,
|
||||
products: newData,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
}
|
||||
},
|
||||
fromCache: false,
|
||||
hasChanged: true
|
||||
})
|
||||
} else {
|
||||
// 如果已有缓存但数据有变化,通知更新
|
||||
resolve({
|
||||
...res,
|
||||
data: {
|
||||
...res.data,
|
||||
data: {
|
||||
...res.data.data,
|
||||
products: newData,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
}
|
||||
},
|
||||
fromCache: false,
|
||||
hasChanged: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 数据没有变化,更新缓存时间戳
|
||||
cache.timestamp = Date.now()
|
||||
resolve({
|
||||
data: {
|
||||
data: {
|
||||
products: cache.data,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
}
|
||||
},
|
||||
fromCache: true,
|
||||
hasChanged: false
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
// 如果请求失败但有缓存,返回缓存
|
||||
if (cache) {
|
||||
resolve({
|
||||
data: {
|
||||
data: {
|
||||
products: cache.data,
|
||||
has_more: false,
|
||||
next_cursor: ''
|
||||
}
|
||||
},
|
||||
fromCache: true,
|
||||
error: err
|
||||
})
|
||||
} else {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分类页商品数据(带缓存)
|
||||
* @param {Object} params - 请求参数
|
||||
* @param {Boolean} forceRefresh - 是否强制刷新
|
||||
* @returns {Promise} 商品数据
|
||||
*/
|
||||
export function getCategoryGoodsWithCache(params, forceRefresh = false) {
|
||||
const categoryId = params.type || params.category_id || ''
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const cache = getCategoryGoodsCache(categoryId)
|
||||
|
||||
// 如果有有效缓存且不强制刷新,先返回缓存数据
|
||||
if (!forceRefresh && isCacheValid(cache)) {
|
||||
resolve({
|
||||
data: cache.data,
|
||||
count: cache.data.length,
|
||||
fromCache: true
|
||||
})
|
||||
}
|
||||
|
||||
// 无论是否有缓存,都请求最新数据进行对比
|
||||
getGoodsListData(params).then(res => {
|
||||
const newData = res?.data.data?.products || res?.data || []
|
||||
const hasMore = res?.data.data?.has_more
|
||||
const nextCursor = res?.data.data?.next_cursor || ''
|
||||
const newHash = calculateDataHash(newData)
|
||||
|
||||
// 检查数据是否有变化
|
||||
const hasChanged = !cache || cache.hash !== newHash
|
||||
|
||||
if (hasChanged || forceRefresh) {
|
||||
// 更新缓存
|
||||
setCategoryGoodsCache(categoryId, newData)
|
||||
|
||||
if (!cache || forceRefresh) {
|
||||
resolve({
|
||||
...res,
|
||||
data: {
|
||||
...res.data,
|
||||
data: {
|
||||
...res.data.data,
|
||||
products: newData,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
}
|
||||
},
|
||||
fromCache: false,
|
||||
hasChanged: true
|
||||
})
|
||||
} else {
|
||||
resolve({
|
||||
...res,
|
||||
data: {
|
||||
...res.data,
|
||||
data: {
|
||||
...res.data.data,
|
||||
products: newData,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
}
|
||||
},
|
||||
fromCache: false,
|
||||
hasChanged: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 数据没有变化,更新缓存时间戳
|
||||
cache.timestamp = Date.now()
|
||||
resolve({
|
||||
data: newData,
|
||||
data: {
|
||||
products: cache.data,
|
||||
has_more: hasMore,
|
||||
next_cursor: nextCursor
|
||||
},
|
||||
count: cache.data.length,
|
||||
fromCache: true,
|
||||
hasChanged: false
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
// 如果请求失败但有缓存,返回缓存
|
||||
if (cache) {
|
||||
resolve({
|
||||
data: cache.data,
|
||||
data: {
|
||||
products: cache.data,
|
||||
has_more: false,
|
||||
next_cursor: ''
|
||||
},
|
||||
count: cache.data.length,
|
||||
fromCache: true,
|
||||
error: err
|
||||
})
|
||||
} else {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有商品缓存
|
||||
*/
|
||||
export function clearGoodsCache() {
|
||||
goodsCache.home = null
|
||||
goodsCache.category = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定分类的商品缓存
|
||||
* @param {Number|String} categoryId - 分类ID
|
||||
*/
|
||||
export function clearCategoryGoodsCache(categoryId) {
|
||||
if (goodsCache.category[categoryId]) {
|
||||
delete goodsCache.category[categoryId]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getHomeGoodsCache,
|
||||
setHomeGoodsCache,
|
||||
getCategoryGoodsCache,
|
||||
setCategoryGoodsCache,
|
||||
getHomeGoodsWithCache,
|
||||
getCategoryGoodsWithCache,
|
||||
clearGoodsCache,
|
||||
clearCategoryGoodsCache
|
||||
}
|
||||
Reference in New Issue
Block a user