feat(单次洗车): 实现单次洗车功能并优化界面样式

- 新增单次洗车页面,包含金额选择、协议勾选和注意事项
- 调整首页扫码启动按钮为单次启动和余额启动双按钮
- 优化单次洗车页面样式和交互逻辑
- 移除首页单次消费弹窗及相关逻辑
This commit is contained in:
2026-01-03 22:12:29 +08:00
parent ad4e2228a6
commit 30e8122c21
7 changed files with 371 additions and 290 deletions

View File

@@ -125,7 +125,7 @@
bottom: 0;
color: #fff;
font-size: 44rpx;
height: 126rpx;
height: 136rpx;
left: 0;
line-height: 106rpx;
position: fixed;
@@ -133,6 +133,7 @@
width: 100vw;
z-index: 6;
border-radius: 40rpx 40rpx 0 0;
overflow: hidden;
}
.scan-btn .sha {
animation: shake 2s infinite;
@@ -183,7 +184,6 @@
font-size: 26rpx;
justify-content: center;
line-height: 40rpx;
border:none;
}
.index-href-box,.service-tel {
@@ -208,6 +208,15 @@
background-image: linear-gradient(to bottom, #C7E1F9, #fff);
}
.index-href-box button.item {
border: 0;
padding: 0;
}
.index-href-box button.item .name {
line-height: 40rpx;
}
.index-href-box .item_b {
width: 100%;
height: 100%;

View File

@@ -16,10 +16,7 @@ Page({
tabStatus: {
coupon: !1,
shop: !1
},
showOneTimeOptions: !1,
oneTimeOptions: [],
oneTimeLoading: !1
}
},
bindViewTap: function () {
wx.navigateTo({
@@ -93,18 +90,16 @@ Page({
getData: function () {
var a = this;
// 获取首页数据
t.request('/miniprogram/index/balance', e.globalData.deviceData, !0).then(function (e) {
t.request('/miniprogram/index/balance', {}, !0).then(function (e) {
a.setData({
user: e.data || [],
});
// 存储进度订单
wx.setStorageSync('progressorder', e.data.progressorder || []);
});
},
load: function (e) {
console.log(e);
},
openLocation: function (e) {
openLocation: function(e) {
var latitude = Number(e.currentTarget.dataset.latitude);
var longitude = Number(e.currentTarget.dataset.longitude);
var name = e.currentTarget.dataset.name;
@@ -128,19 +123,7 @@ Page({
}), (this.getData(), this.isneedUpload = !1);
},
toPage: function (t) {
if (t.currentTarget.dataset.phone) {
// 打开客服聊天窗口
return wx.openCustomerServiceChat();
// 增加打电话
wx.makePhoneCall({
phoneNumber: "" + t.currentTarget.dataset.phone
});
return;
}
console.info(t);
var a = t.currentTarget.dataset, i = a.url, o = a.needlogin, n = a.showimg;
if (console.log("showImg", n), i) {
this.isneedUpload = !0;
@@ -164,13 +147,11 @@ Page({
success: function (i) {
console.log(i), wx.showLoading({
title: ""
}), e.globalData.qrcode = i.result, t.request("/miniprogram/identify/index", i, !0).then(function (t) {
console.log("data", t), wx.hideLoading(),
e.globalData.deviceData = t.data || e.globalData.deviceData || {};
e.globalData.devicecode = t.data.devicecode || e.globalData.devicecode;
a.setData({
isScan: !!t.data.devicecode
});
}), e.globalData.qrcode = i.result, t.request("/miniprogram/identify", i, !0).then(function (t) {
console.log("data", t), wx.hideLoading(), e.globalData.devicecode = t.data.devicecode || e.globalData.devicecode,
a.setData({
isScan: !!t.data.devicecode
});
}).catch(function (e) {
wx.hideLoading();
});
@@ -187,140 +168,41 @@ Page({
e.globalData.needJumpUrl = !1, this.isneedUpload = !0;
var t = this;
if (console.log("this.isSubmit", this.isSubmit), this.isSubmit) return !1;
wx.showActionSheet({
itemList: ["单次消费", "立即启动"],
success: function (res) {
if (res.tapIndex === 0) {
t.openOneTimeOptions();
} else {
if (t.data.user.money == 0) {
wx.showModal({
title: "提示",
content: "您的洗车金额为0元是否需要购买洗车金额",
confirmText: "去购买",
cancelText: "取消",
success: function (m) {
if (m.confirm) {
wx.navigateTo({
url: "/pages/voucher/voucher"
}), t.isneedUpload = !0;
}
}
});
return;
}
else if (t.data.user.money < 10) {
wx.showModal({
title: "提示",
content: "洗车金额不足10元是否需要购买洗车金额还是直接开机",
confirmText: "去购买",
cancelText: "直接开机",
success: function (m) {
if (m.confirm) {
wx.navigateTo({
url: "/pages/voucher/voucher"
}), t.isneedUpload = !0;
} else {
t.startup();
}
}
});
return;
}
t.startup();
}
}
});
},
openOneTimeOptions: function () {
var a = this;
if (a.data.oneTimeLoading) return !1;
a.setData({ oneTimeLoading: !0 });
// 获取单次洗车配置
t.request('/miniprogram/single/getAgentConfig', e.globalData.deviceData || {}, !0).then(function (res) {
a.setData({
oneTimeOptions: (res.data && Array.isArray(res.data)) ? res.data : (res.data && res.data.list ? res.data.list : []),
showOneTimeOptions: !0,
oneTimeLoading: !1
});
}).catch(function () {
a.setData({ oneTimeLoading: !1 });
});
},
closeOneTimeOptions: function () {
this.setData({ showOneTimeOptions: !1 });
},
payOneTime: function (evt) {
var a = this, i = evt.currentTarget.dataset.token;
if (!i) return !1;
wx.showLoading({ title: "" });
t.request('/miniprogram/single/create', {
token: i
}, !0).then(function (res) {
if (wx.hideLoading(), 200 != res.code) return wx.showModal({
if (t.data.user.money <= 0) return t.startup(), !1;
if (t.data.user.money < 10) {
if (this.isshowModal) return t.startup(), !1;
this.isshowModal = !0, wx.showModal({
title: "提示",
content: res.message || ""
}), !1;
var r = res.data.result;
var orderid = res.data.orderid;
wx.requestPayment({
timeStamp: r.timeStamp,
nonceStr: r.nonceStr,
package: r.package,
signType: r.signType,
paySign: r.paySign,
success: function () {
a.setData({ showOneTimeOptions: !1 });
var poll = function () {
t.request('/miniprogram/single/notify', {
orderid: orderid
}, !0).then(function (res) {
if (200 == res.code) {
wx.showModal({
title: "提示",
content: "支付成功"
});
wx.navigateTo({
url: "/pages/voucher/voucher"
});
return;
}
}).catch(function (err) {
if (err && err.code == 202) {
setTimeout(poll, 1500);
return;
}
if (err && err.code == 201) {
wx.showModal({
title: "提示",
content: err.message || ""
});
}
});
};
poll();
content: "账户余额小于10元是否立即充值",
confirmText: "去充值",
cancelText: "立即启动",
success: function (e) {
e.confirm ? (wx.navigateTo({
url: "/pages/voucher/voucher"
}), t.isneedUpload = !0) : t.startup();
},
fail: function (e) {
console.log("fail:", e);
}
});
}).catch(function () {
wx.hideLoading();
});
} else t.startup();
},
startup: function () {
var a = this;
wx.showModal({
title: "提示",
content: "你当前将要使用的机器编号是:".concat(e.globalData.deviceData.title || e.globalData.deviceData.devicecode, ",确认开机吗?"),
content: "你当前将要使用的机器编号是:".concat(e.globalData.devicecode, ",确认开机吗?"),
success: function (i) {
i.confirm && (a.isSubmit = !0, wx.showLoading({
title: "正在启动"
}), t.request('/miniprogram/' + e.globalData.deviceData.type + '/startup', e.globalData.deviceData || {}, !0).then(function (e) {
}), t.request(e.globalData.config.machine.startup, {
washcode: a.data.selectID
}, !0).then(function (e) {
a.isSubmit = !1, wx.hideLoading(), 200 == e.code && (wx.showModal({
title: "",
content: e.message
}), a.data.tmplIds.length > 0 && a.requestSubscribeMessage(), wx.redirectTo({
// url: "/pages/washing/washing"
url: "/pages/index/index"
url: "/pages/user/user"
}), a.isneedUpload = !0), 888 == e.code && (wx.navigateTo({
url: "/pages/voucher/voucher"
}), a.isneedUpload = !0);
@@ -345,4 +227,4 @@ Page({
});
},
onShareAppMessage: function () { }
});
});

View File

@@ -6,35 +6,19 @@
<view class="money">
<my-money user="{{user}}"></my-money>
<view class="marquee-wrap" wx:if="{{notice}}">
<view bindtap="toPage" class="marquee-content" data-refresh="1" data-url="{{noticeurl}}">
{{notice}}
</view>
<view bindtap="toPage" class="marquee-content" data-refresh="1" data-url="{{noticeurl}}"> {{notice}} </view>
</view>
<navigator class="washing" hoverClass="hover" url="/pages/washing/washing" wx:if="{{user.progressorder}}">
<view class="l">您有一笔洗车订单进行中...</view>
<view class="r">点击查看></view>
</navigator>
</view>
<template is="pageList" data="{{urlList:urlList}}"></template>
<template is="wangdianList" data="{{wangdianList:wangdianList}}"></template>
<service-tel></service-tel>
<view bindtap="toScan" class="scan-btn" wx:if="{{!isScan}}">
<view class="sha">扫码启动</view>
<view bindtap="toScan" class="scan-btn" wx:if="{{!isScan}}"><view class="sha">扫码启动</view></view>
<view class="scan-btn two-btn" wx:if="{{isScan}}">
<view bindtap="toPage" data-needlogin="true" data-refresh="" data-showimg="" data-url="singleStart/singleStart" class="two-btns danci">
<view>单次启动</view>
</view>
<view bindtap="toStart" class="two-btns yue">
<view>余额启动</view>
</view>
</view>
<view bindtap="toStart" class="scan-btn" wx:if="{{isScan}}">
<view class="sha">立即启动</view>
</view>
<view class="one-time-modal" wx:if="{{showOneTimeOptions}}">
<view class="one-time-inner">
<view class="one-time-title">选择单次消费档位</view>
<view class="one-time-tip">限单次洗车</view>
<view class="one-time-list">
<view class="one-time-item" wx:for="{{oneTimeOptions}}" wx:key="index" bindtap="payOneTime" data-token="{{item.token}}">
<view>{{item.title}}</view>
<view>支付{{item.actualprice}}元 · 洗车时间最长{{item.usetime}}分钟</view>
</view>
</view>
<view bindtap="closeOneTimeOptions" class="one-time-cancel">取消</view>
</view>
</view>
</view>
</view>

View File

@@ -32,6 +32,17 @@
position: static;
}
.two-btn .two-btns {
float: left;
width: 50%;
height: 126rpx;
padding-top: 10rpx;
}
.two-btns.yue {
background-color: #f60;
}
.start-btn-box .scan-subscribe {
margin-right: 10rpx;
}
@@ -118,7 +129,7 @@
top: -20rpx;
color: #fff;
background-color: #0056A3;
font-size: 22rpx;
font-size: 24rpx;
padding: 0 12rpx;
line-height: 36rpx;
border-radius: 0 0 0 20rpx;
@@ -157,69 +168,4 @@
right: 0;
display: block;
background-color: #37CE05;
}
.washing {
justify-content: space-between;
margin: 30rpx 0 0;
padding: 20rpx 28rpx;
display: flex;
background-color: #0056A3;
color: #fff;
font-size: 28rpx;
}
.washing .l {
flex: 1;
}
/* 单次消费弹窗 */
.one-time-modal {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
}
.one-time-inner {
width: 84%;
background: #fff;
border-radius: 16rpx;
padding: 24rpx 24rpx 16rpx;
box-shadow: 0 10rpx 30rpx rgba(0,0,0,.2);
}
.one-time-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
text-align: center;
}
.one-time-tip {
font-size: 24rpx;
color: #999;
text-align: center;
margin-top: 8rpx;
}
.one-time-list {
margin-top: 20rpx;
}
.one-time-item {
border: 1px solid #eee;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 16rpx;
}
.one-time-cancel {
margin-top: 8rpx;
background-color: #06a2b3;
color: #fff;
text-align: center;
line-height: 80rpx;
height: 80rpx;
border-radius: 12rpx;
}
}

View File

@@ -1,19 +1,126 @@
var e = getApp(), t = require("../../utils/login.js");
Page({
data: {
banner: [],
selectIndex: 0
list: [],
loading: !1,
message: "",
selectItemID: null,
approve: !0,
protocol: {
url: "",
name: "聚美汽服购买协议"
},
isSubmit: !1
},
onLoad: function(n) {},
onReady: function() {},
onShow: function() {},
onHide: function() {},
onUnload: function() {},
onPullDownRefresh: function() {},
onReachBottom: function() {},
onShareAppMessage: function() {},
selectItem: function(n) {
onLoad: function () {
this.getAgentConfig();
},
getAgentConfig: function () {
var a = this;
if (a.data.loading) return !1;
a.setData({ loading: !0 });
var payload = {
number: e.globalData.deviceData.number || e.globalData.devicecode || "",
agentid: e.globalData.deviceData.agentid || "",
method: "POST"
};
t.request('/miniprogram/single/getAgentConfig', payload, !0).then(function (res) {
a.setData({ loading: !1 });
if (res.code != 200) {
a.setData({
list: [],
message: res.message || "加载失败"
});
return;
}
var list = (res.data || []).map(function (x, idx) {
x.selected = idx === 0;
return x;
});
a.setData({
list: list,
selectItemID: list.length ? list[0].id : null,
message: ""
});
}).catch(function () {
a.setData({
loading: !1,
list: [],
message: "网络异常,请稍后重试"
});
});
},
selectItem: function (n) {
var id = n.currentTarget.dataset.id;
var list = (this.data.list || []).map(function (x) {
x.selected = x.id == id;
return x;
});
this.setData({ selectItemID: id, list: list });
},
tobuyNow: function () {
if (!this.data.approve) return wx.showToast({
title: "请勾选同意相关条款",
icon: "none"
}), !1;
if (!this.data.selectItemID || this.data.isSubmit) return wx.showToast({
title: "请选择单次洗车金额~",
icon: "none"
}), !1;
var i = this, sel = (this.data.list || []).find(function (x) { return x.id == i.data.selectItemID; });
if (!sel || !sel.token) return wx.showToast({
title: "请选择有效档位~",
icon: "none"
}), !1;
this.setData({ isSubmit: !0 }), wx.showLoading({ title: "" });
t.request('/miniprogram/single/create', {
token: sel.token,
method: "POST"
}, !0).then(function (res) {
wx.hideLoading(), i.setData({ isSubmit: !1 });
if (200 != res.code) return wx.showModal({
title: "提示",
content: res.message || "下单失败"
}), !1;
var p = res.data.result || {};
var orderid = res.data.orderid || p.orderid || "";
wx.requestPayment({
timeStamp: p.timeStamp,
nonceStr: p.nonceStr,
package: p.package,
signType: p.signType,
paySign: p.paySign,
success: function () {
if (orderid) {
t.request('/miniprogram/single/notify', {
orderid: orderid,
method: "POST"
}, !0).then(function () {
wx.redirectTo({
url: "/pages/washing/washing"
});
}).catch(function () {
wx.redirectTo({
url: "/pages/washing/washing"
});
});
} else {
wx.redirectTo({
url: "/pages/washing/washing"
});
}
}
});
}).catch(function () {
wx.hideLoading(), i.setData({ isSubmit: !1 });
});
},
change: function (t) {
var i = t.detail.value.length;
this.setData({
selectIndex: n.currentTarget.dataset.index
approve: 1 == i
});
}
});
});

View File

@@ -1,12 +1,44 @@
<view class="container">
<head-swiper banner="{{banner}}"></head-swiper>
<view class="title-tips">请选择单次洗车金额</view>
<view class="list">
<view bindtap="selectItem" class="{{selectIndex==index?'active item':'item'}}" data-index="{{index}}" wx:for="{{5}}" wx:key="index"> 6.00元 </view>
<view bindtap="selectItem" class="item {{item.selected?'active':''}} {{item.isrecommend?'select':''}}" data-id="{{item.id}}" wx:for="{{list}}" wx:key="id">
<view class="g">{{item.price}}元<view class="u">购</view></view>
<view class="j">{{item.actualprice}}<view class="p">洗车金</view></view>
<view class="t">
<text>1、洗车金用完机器自动停止。\n 2、洗车金没用完到达[ <text class="b">{{item.usetime}}分钟</text> ]机器自动停止。</text>
</view>
</view>
</view>
<view class="no-content" wx:if="{{list.length==0&&!loading}}">
<image src="/img/nocontent.png"></image>
<view>{{message||'暂无相关数据'}}</view>
</view>
<view bindtap="tobuyNow" class="tobuy-btn {{approve?'':'disabled'}}">立即启动·单次洗车</view>
<checkbox-group bindchange="change">
<label class="provision">
<checkbox checked value="{{approve}}"></checkbox> 启动单次洗车表示同意 <navigator class="text" url="/pages/webview/webview?url={{protocol.url}}">《聚美汽服购买协议》</navigator>
</label>
</checkbox-group>
<view class="warm-prompt">
<view class="title">注意事项:</view>
<view class="content">
<view>1、<b>没有完成洗车,请勿按红色“结束”按钮</b></view>
<view>2、单次洗车不支持余额支付</view>
<view>3、单次洗车仅限1次洗车不得分开多次使用</view>
<view>4、购买单次洗车后将获得相应的洗车金和洗车时长</view>
<view>5、购买单次洗车后洗车机将立即启动请确保你在洗车机前</view>
<view>6、洗车金为本次最多可用金额按量扣费</view>
<view>7、洗车时长为本次最长可用时间洗车机启动后开始计时</view>
<view>8、当洗车金为0或达到洗车时长洗车机将自动结束洗车</view>
</view>
</view>
<service-tel tel="{{servicetel}}"></service-tel>
<view class="footer-btn-box">
<view class="btn yellow">余额洗车</view>
<view class="btn">单次启动</view>
</view>
</view>

View File

@@ -11,42 +11,163 @@
padding: 0;
}
.item {
background-color: #fff;
border-radius: 18rpx;
box-shadow: 0 0rpx 9rpx 4rpx hsla(0,0%,40%,.3);
color: #333;
font-size: 87rpx;
height: 180rpx;
line-height: 180rpx;
margin-bottom: 32rpx;
text-align: center;
.list .item {
position: relative;
padding-left: 286rpx;
background: #fff;
border: 5rpx solid #0281db;
border-radius: 26rpx;
box-sizing: border-box;
color: #0281db;
flex-direction: column;
height: 158rpx;
justify-content: center;
margin: 0 0 28rpx;
width: 100%;
overflow: hidden;
}
.item.active {
box-shadow: 0 0rpx 9rpx 4rpx rgba(255,102,0,.3);
color: #f60;
.list .item .g, .list .item .j {
position: absolute;
}
.list .item .g {
left: 0;
top: 0;
height: 153rpx;
width: 158rpx;
line-height: 153rpx;
text-align: center;
background-color: #0281db;
color: #fff;
font-size: 50rpx;
}
.footer-btn-box {
bottom: 0;
color: #fff;
display: flex;
font-size: 44rpx;
left: 0;
position: fixed;
width: 100vw;
.list .item .g .u {
position: absolute;
right: -25rpx;
top: 55rpx;
width: 40rpx;
height: 40rpx;
font-size: 26rpx;
line-height: 40rpx;
border-radius: 100rpx;
border: 5rpx solid #0281db;
color: #0281db;
background-color: #fff;
}
.footer-btn-box .btn {
align-items: center;
background: #4cadf1;
display: inline-flex;
flex: 1;
height: 104rpx;
justify-content: center;
.list .item .j {
left: 158rpx;
top: 0;
height: 153rpx;
width: 138rpx;
font-size: 66rpx;
line-height: 108rpx;
text-align: center;
}
.btn.yellow {
background: #fccaa9;
.list .item .j .p {
font-size: 26rpx;
line-height: 1;
}
.list .item .t {
font-size: 25rpx;
height: 153rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 0 20rpx;
background-color: #eee;
}
.list .item .t .b {
font-weight: 700;
color: #1baa1c;
}
.list .item.select, .list .item.select .g .u {
border-color: #f50;
color: #f50;
}
.list .item.select .g {
background-color: #f50;
}
.list .item.active, .list .item.active .g .u {
border-color: #4cadf1;
color: #4cadf1;
}
.list .item.active .g {
background-color: #4cadf1;
}
.list .item.active.select, .list .item.active.select .g .u {
border-color: #f90;
color: #f90;
}
.list .item.active.select .g {
background-color: #f90;
}
.tobuy-btn {
align-items: center;
background: #1baa1c;
border: 2rpx solid #218721;
border-radius: 18rpx;
color: #fff;
display: flex;
font-size: 33rpx;
height: 91rpx;
justify-content: center;
margin-top: 3rpx;
}
.tobuy-btn.disabled {
opacity: .7;
}
.provision {
display: block;
margin: 40rpx 0 0;
font-size: 26rpx;
}
.provision .text {
color: #0281db;
display: inline-block;
}
.warm-prompt {
padding: 60rpx 0;
}
.warm-prompt .title {
color: #f30;
font-size: 32rpx;
font-weight: 600;
margin-bottom: 16rpx;
}
.warm-prompt .content {
color: #666;
font-size: 26rpx;
line-height: 1.8;
}
.warm-prompt .content .view {
margin-bottom: 10rpx;
}
.warm-prompt .content view b {
font-weight: 700;
color: red;
}
.scan-btn {
background-color: #218721;
}