Compare commits

3 Commits

Author SHA1 Message Date
duanshuwen
1f3a3c052a feat: 样式调整 2025-10-28 20:39:04 +08:00
duanshuwen
bbd975ffa7 Merge branch 'main' of https://git.nianxx.cn/zoujing/YGChatCS into fix-109 2025-10-28 20:34:52 +08:00
duanshuwen
eed2eea123 feat: 订单支付|商品详情调整 2025-10-28 20:34:18 +08:00
9 changed files with 177 additions and 205 deletions

View File

@@ -28,11 +28,16 @@
<uni-icons fontFamily="znicons" size="20" color="#333">
{{ zniconsMap["zn-refund"] }}
</uni-icons>
<text class="font-size-14 font-600 color-171717 ml-8">退订规则</text>
<text class="font-size-14 font-600 color-171717 ml-8">
{{ refundTitle }}
</text>
</view>
<view class="font-size-14 color-525866 line-height-16">
<!-- {{ commodityPurchaseInstruction.refundContent }} -->
·不予退款12小时以内取消或未入住不予退款
<view
class="font-size-14 color-525866 line-height-16 mb-4"
v-for="(item, index) in commodityPurchaseInstruction"
:key="index"
>
{{ item }}
</view>
</view>
</view>
@@ -64,9 +69,22 @@ const emit = defineEmits(["update:modelValue"]);
const popupRef = ref(null);
// 获取退款模板
const refundTitle = computed(() => {
if (props.orderData.commodityPurchaseInstruction) {
return (
props.orderData.commodityPurchaseInstruction.refundTitle || "退订规则"
);
}
return "退订规则";
});
const commodityPurchaseInstruction = computed(() => {
if (props.orderData.commodityPurchaseInstruction) {
return props.orderData.commodityPurchaseInstruction;
// 以换行符为分隔符,将字符串转换为数组
return props.orderData.commodityPurchaseInstruction.refundContent.split(
"\n"
);
}
return {};

View File

@@ -62,7 +62,11 @@
"mp-weixin": {
"appid": "wx5e79df5996572539",
"setting": {
"urlCheck": false
"urlCheck": false,
"minified": true
},
"optimization": {
"subPackages": true
},
"usingComponents": true,
"requiredPrivateInfos": ["getLocation"],

View File

@@ -27,7 +27,7 @@
<view class="right">
<input
class="border-box rounded-8 px-4 py-2 font-size-15 color-000 line-height-20"
v-model="userFormList[0].contactPhone"
v-model.trim="userFormList[0].contactPhone"
placeholder="请输入联系手机"
maxlength="11"
/>

View File

@@ -19,7 +19,7 @@
<view class="right">
<input
class="border-box rounded-8 px-4 py-2 font-size-15 color-000 line-height-20"
v-model="item.visitorName"
v-model.trim="item.visitorName"
placeholder="请输入姓名"
maxlength="11"
/>
@@ -31,7 +31,7 @@
<view class="right">
<input
class="border-box rounded-8 px-4 py-2 font-size-15 color-000 line-height-20"
v-model="userFormList[0].contactPhone"
v-model.trim="userFormList[0].contactPhone"
placeholder="请输入联系手机"
maxlength="11"
/>

View File

@@ -102,10 +102,10 @@ import UserSection from "./components/UserSection/index.vue";
import RefundPopup from "@/components/RefundPopup/index.vue";
import DetailPopup from "@/components/DetailPopup/index.vue";
import FooterSection from "./components/FooterSection/index.vue";
import { goodsDetail } from "@/request/api/GoodsApi";
import { goodsDetail, orderPay } from "@/request/api/GoodsApi";
import { useSelectedDateStore } from "@/store";
import { GOODS_TYPE } from "@/constant/type";
import { PhoneUtils } from "@/utils";
import { ThrottleUtils, PhoneUtils } from "@/utils";
const refundVisible = ref(false);
const detailVisible = ref(false);
@@ -190,18 +190,113 @@ const navigateToDetail = ({ commodityId }) => {
});
};
// 处理支付点击事件
const handlePayClick = (orderData) => {
console.log("处理支付点击事件", userFormList.value);
// 校验手机号
if (!PhoneUtils.validatePhone(userFormList.value[0].contactPhone)) {
uni.showToast({
title: "请输入正确的手机号",
icon: "none",
// 验证用户姓名
const validateUserForms = () => {
const invalidUsers = userFormList.value.filter((user) => {
return user.visitorName.trim() === "";
});
if (invalidUsers.length) {
uni.showToast({ title: "请填写住客姓名", icon: "none" });
return false;
}
return true;
};
// 处理支付点击事件
const handlePayClick = ThrottleUtils.createThrottle(async (goodsData) => {
console.log("处理支付点击事件", userFormList.value);
// 判断是酒店类型
if (goodsData.commodityTypeCode === "0") {
// 校验用户姓名
if (!validateUserForms()) {
return;
}
}
// 校验手机号
if (!PhoneUtils.validatePhone(userFormList.value[0].contactPhone)) {
uni.showToast({ title: "请输入正确的手机号", icon: "none" });
return;
}
// 购买的商品id
const commodityId = goodsData.commodityId;
// 消费者信息
const consumerInfoEntityList = userFormList.value;
// 购买数量
const purchaseAmount = consumerInfoEntityList.length;
// 支付方式 0-微信 1-支付宝 2-云闪付
const payWay = "0";
// 支付渠道 0-app 1-小程序 2-h5
const paySource = "1";
const params = {
commodityId,
purchaseAmount,
payWay,
paySource,
consumerInfoEntityList,
};
//酒店类型添加入住时间、离店时间
if (goodsData.commodityTypeCode === "0" && selectedDate.value) {
const { startDate, endDate } = selectedDate.value;
// 入住时间
params.checkInData = startDate;
// 离店时间
params.checkOutData = endDate;
}
const res = await orderPay(params);
console.log("确认订单---2:", res);
// 检查接口返回数据
if (!res || !res.data) {
uni.showToast({ title: "订单创建失败,请重试", icon: "none" });
return;
}
const { data } = res;
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
// 验证支付参数是否完整
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
// console.error("支付参数不完整:", {
// nonceStr: !!nonceStr,
// packageVal: !!packageVal,
// paySign: !!paySign,
// signType: !!signType,
// timeStamp: !!timeStamp,
// });
uni.showToast({ title: "支付参数错误,请重试", icon: "none" });
return;
}
// 调用微信支付
uni.requestPayment({
provider: "wxpay",
timeStamp: String(timeStamp), // 确保为字符串类型
nonceStr: String(nonceStr),
package: String(packageVal), // 确保为字符串类型
signType: String(signType),
paySign: String(paySign),
success: () => {
uni.showToast({
title: "支付成功",
icon: "success",
success: () => {
uni.navigateTo({
url: "/pages-order/order/list",
});
},
});
},
fail: () => {
uni.showToast({ title: "支付失败,请重试", icon: "none" });
},
});
}, 1000);
</script>
<style scoped lang="scss">

View File

@@ -11,7 +11,7 @@
</view>
<!-- 设施信息区域 -->
<view class="facilities-section">
<view class="facilities-section" v-if="facilitiesList.length">
<view class="facilities-grid">
<view
class="facility-item"

View File

@@ -43,21 +43,24 @@
</scroll-view>
<!-- 立即抢购 -->
<view class="footer">
<view class="left">
<text class="label">价格</text>
<text class="price">{{ calculatedTotalPrice }}</text>
</view>
<view class="buy-button" @click="showConfirmPopup">立即抢购</view>
<view class="footer border-top">
<view
class="amt font-size-20 font-bold color-FF3D60 line-height-28 flex flex-items-center mr-8"
>
{{ calculatedTotalPrice }}
</view>
<!-- 商品确认弹窗 -->
<GoodConfirm
ref="goodConfirmRef"
:goodsData="goodsData"
@confirm="handleConfirmOrder"
@close="handleCloseConfirm"
<view
class="btn border-box rounded-10 flex flex-items-center ml-auto pl-8"
@click="navigateToPay(goodsData)"
>
<image
class="icon"
src="https://oss.nianxx.cn/mp/static/version_101/common/btn.png"
/>
<text class="font-size-16 font-500 color-white">立即预定</text>
</view>
</view>
<!-- 日历组件 -->
<Calender
@@ -73,12 +76,8 @@
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import {
goodsDetail,
commodityDailyPriceList,
orderPay,
} from "@/request/api/GoodsApi";
import { ThrottleUtils, DateUtils } from "@/utils";
import { goodsDetail, commodityDailyPriceList } from "@/request/api/GoodsApi";
import { DateUtils } from "@/utils";
import TopNavBar from "@/components/TopNavBar/index.vue";
import ImageSwiper from "@/components/ImageSwiper/index.vue";
import GoodInfo from "./components/GoodInfo/index.vue";
@@ -94,7 +93,6 @@ import { useSelectedDateStore } from "@/store";
const navOpacity = ref(0);
const calendarVisible = ref(false);
const goodsData = ref({});
const goodConfirmRef = ref(null);
// 处理滚动事件
const handleScroll = (e) => {
@@ -160,135 +158,6 @@ const getGoodsDailyPrice = async (params) => {
priceData.value = res.data;
};
// 显示确认弹窗
const showConfirmPopup = () => {
// 当商品类型为"0"时,需要校验入住和离店日期
if (goodsData.value.commodityTypeCode === "0") {
// 检查是否已选择日期
if (
!selectedDate.value ||
!selectedDate.value.startDate ||
!selectedDate.value.endDate
) {
calendarVisible.value = true;
uni.showToast({
title: "请先选择入住和离店日期",
icon: "none",
duration: 2000,
});
return;
}
}
// 校验通过或非住宿类商品,显示确认弹窗
goodConfirmRef.value?.showPopup();
};
// 处理确认订单
const handleConfirmOrder = ThrottleUtils.createThrottle(async (orderData) => {
console.log("确认订单---1:", orderData);
const { goodsData } = orderData;
// 购买的商品id
const commodityId = goodsData.commodityId;
// 消费者信息
const consumerInfoEntityList = orderData.userFormList;
// 购买数量
const purchaseAmount = orderData.userFormList.length;
// 支付方式 0-微信 1-支付宝 2-云闪付
const payWay = "0";
// 支付渠道 0-app 1-小程序 2-h5
const paySource = "1";
const params = {
commodityId,
purchaseAmount,
payWay,
paySource,
consumerInfoEntityList,
};
//酒店类型添加入住时间、离店时间
if (goodsData.commodityTypeCode === "0" && selectedDate.value) {
const { startDate, endDate } = selectedDate.value;
// 入住时间
params.checkInData = startDate;
// 离店时间
params.checkOutData = endDate;
}
// 购买数量
const res = await orderPay(params);
console.log("确认订单---2:", res);
// 检查接口返回数据
if (!res || !res.data) {
uni.showToast({
title: "订单创建失败,请重试",
icon: "none",
duration: 2000,
});
return;
}
const { data } = res;
const { nonceStr, packageVal, paySign, signType, timeStamp } = data;
// 验证支付参数是否完整
if (!nonceStr || !packageVal || !paySign || !signType || !timeStamp) {
console.error("支付参数不完整:", {
nonceStr: !!nonceStr,
packageVal: !!packageVal,
paySign: !!paySign,
signType: !!signType,
timeStamp: !!timeStamp,
});
uni.showToast({
title: "支付参数错误,请重试",
icon: "none",
duration: 2000,
});
return;
}
// 调用微信支付
uni.requestPayment({
provider: "wxpay",
timeStamp: String(timeStamp), // 确保为字符串类型
nonceStr: String(nonceStr),
package: String(packageVal), // 确保为字符串类型
signType: String(signType),
paySign: String(paySign),
success: (res) => {
console.log("支付成功:" + JSON.stringify(res));
uni.showToast({
title: "支付成功",
icon: "success",
duration: 2000,
success: () => {
uni.navigateTo({
url: "/pages-order/order/list",
});
},
});
},
fail: (err) => {
console.error("支付失败:" + JSON.stringify(err));
uni.showToast({
title: "支付失败,请重试",
icon: "none",
duration: 2000,
});
},
});
}, 1000);
// 处理关闭弹窗
const handleCloseConfirm = () => {
console.log("关闭确认弹窗");
};
const selectedDateStore = useSelectedDateStore();
onLoad(({ commodityId = "1950766939442774018" }) => {
// 从store中获取选中的日期
@@ -374,6 +243,13 @@ const handleDateSelect = (data) => {
// 日历组件会自动关闭,无需手动设置
calendarVisible.value = false;
};
// 跳转订购
const navigateToPay = ({ commodityId }) => {
uni.navigateTo({
url: `/pages-booking/index?commodityId=${commodityId}`,
});
};
</script>
<style scoped lang="scss">

View File

@@ -68,7 +68,7 @@ $button-color: #00a6ff;
.goods-content {
border-radius: 28px 28px 0 0;
background-color: #fff;
padding: 12px;
padding: 20px 12px;
position: relative;
margin-top: -30px;
z-index: 1;
@@ -81,52 +81,27 @@ $button-color: #00a6ff;
background-color: #fff;
box-sizing: border-box;
padding: 12px 12px 24px;
// 阴影
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1);
z-index: 10;
flex-shrink: 0; // 防止被压缩
display: flex;
align-items: center;
.left {
display: flex;
align-items: baseline;
}
.label {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.price {
display: flex;
align-items: baseline;
font-size: 24px;
color: #f55726;
.amt {
&::before {
content: "¥";
font-size: $uni-font-size-sm;
font-size: 16px;
font-weight: 500;
}
}
.buy-button {
width: 160px;
background: linear-gradient(179deg, #00a6ff 0%, #0256ff 100%);
color: #fff;
border: none;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: $uni-border-radius-50px;
height: 42px;
font-size: $uni-font-size-base;
font-weight: 500;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
letter-spacing: 0.5px;
margin-left: auto;
.btn {
width: 120px;
height: 48px;
background: linear-gradient(90deg, #ff3d60 57%, #ff990c 100%);
}
.icon {
height: 48px;
width: 34px;
}
}

View File

@@ -3,6 +3,10 @@
border: 1px solid #e5e8ee;
}
.border-top {
border-top: 1px solid #e5e8ee;
}
.border-bottom {
border-bottom: 1px solid #e5e8ee;
}