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

View File

@@ -16,10 +16,7 @@ Page({
tabStatus: { tabStatus: {
coupon: !1, coupon: !1,
shop: !1 shop: !1
}, }
showOneTimeOptions: !1,
oneTimeOptions: [],
oneTimeLoading: !1
}, },
bindViewTap: function () { bindViewTap: function () {
wx.navigateTo({ wx.navigateTo({
@@ -93,12 +90,10 @@ Page({
getData: function () { getData: function () {
var a = this; 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({ a.setData({
user: e.data || [], user: e.data || [],
}); });
// 存储进度订单
wx.setStorageSync('progressorder', e.data.progressorder || []);
}); });
}, },
load: function (e) { load: function (e) {
@@ -128,19 +123,7 @@ Page({
}), (this.getData(), this.isneedUpload = !1); }), (this.getData(), this.isneedUpload = !1);
}, },
toPage: function (t) { toPage: function (t) {
console.info(t);
if (t.currentTarget.dataset.phone) {
// 打开客服聊天窗口
return wx.openCustomerServiceChat();
// 增加打电话
wx.makePhoneCall({
phoneNumber: "" + t.currentTarget.dataset.phone
});
return;
}
var a = t.currentTarget.dataset, i = a.url, o = a.needlogin, n = a.showimg; var a = t.currentTarget.dataset, i = a.url, o = a.needlogin, n = a.showimg;
if (console.log("showImg", n), i) { if (console.log("showImg", n), i) {
this.isneedUpload = !0; this.isneedUpload = !0;
@@ -164,10 +147,8 @@ Page({
success: function (i) { success: function (i) {
console.log(i), wx.showLoading({ console.log(i), wx.showLoading({
title: "" title: ""
}), e.globalData.qrcode = i.result, t.request("/miniprogram/identify/index", i, !0).then(function (t) { }), e.globalData.qrcode = i.result, t.request("/miniprogram/identify", i, !0).then(function (t) {
console.log("data", t), wx.hideLoading(), console.log("data", t), wx.hideLoading(), e.globalData.devicecode = t.data.devicecode || e.globalData.devicecode,
e.globalData.deviceData = t.data || e.globalData.deviceData || {};
e.globalData.devicecode = t.data.devicecode || e.globalData.devicecode;
a.setData({ a.setData({
isScan: !!t.data.devicecode isScan: !!t.data.devicecode
}); });
@@ -187,140 +168,41 @@ Page({
e.globalData.needJumpUrl = !1, this.isneedUpload = !0; e.globalData.needJumpUrl = !1, this.isneedUpload = !0;
var t = this; var t = this;
if (console.log("this.isSubmit", this.isSubmit), this.isSubmit) return !1; if (console.log("this.isSubmit", this.isSubmit), this.isSubmit) return !1;
wx.showActionSheet({ if (t.data.user.money <= 0) return t.startup(), !1;
itemList: ["单次消费", "立即启动"], if (t.data.user.money < 10) {
success: function (res) { if (this.isshowModal) return t.startup(), !1;
if (res.tapIndex === 0) { this.isshowModal = !0, wx.showModal({
t.openOneTimeOptions();
} else {
if (t.data.user.money == 0) {
wx.showModal({
title: "提示", title: "提示",
content: "您的洗车金额为0元是否需要购买洗车金额", content: "账户余额小于10元是否立即充值",
confirmText: "去购买", confirmText: "去充值",
cancelText: "取消", cancelText: "立即启动",
success: function (m) { success: function (e) {
if (m.confirm) { e.confirm ? (wx.navigateTo({
wx.navigateTo({
url: "/pages/voucher/voucher" url: "/pages/voucher/voucher"
}), t.isneedUpload = !0; }), t.isneedUpload = !0) : t.startup();
}
}
});
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 () { fail: function (e) {
var a = this; console.log("fail:", e);
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({
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 || ""
});
} }
}); });
}; } else t.startup();
poll();
}
});
}).catch(function () {
wx.hideLoading();
});
}, },
startup: function () { startup: function () {
var a = this; var a = this;
wx.showModal({ wx.showModal({
title: "提示", title: "提示",
content: "你当前将要使用的机器编号是:".concat(e.globalData.deviceData.title || e.globalData.deviceData.devicecode, ",确认开机吗?"), content: "你当前将要使用的机器编号是:".concat(e.globalData.devicecode, ",确认开机吗?"),
success: function (i) { success: function (i) {
i.confirm && (a.isSubmit = !0, wx.showLoading({ i.confirm && (a.isSubmit = !0, wx.showLoading({
title: "正在启动" 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({ a.isSubmit = !1, wx.hideLoading(), 200 == e.code && (wx.showModal({
title: "", title: "",
content: e.message content: e.message
}), a.data.tmplIds.length > 0 && a.requestSubscribeMessage(), wx.redirectTo({ }), a.data.tmplIds.length > 0 && a.requestSubscribeMessage(), wx.redirectTo({
// url: "/pages/washing/washing" url: "/pages/user/user"
url: "/pages/index/index"
}), a.isneedUpload = !0), 888 == e.code && (wx.navigateTo({ }), a.isneedUpload = !0), 888 == e.code && (wx.navigateTo({
url: "/pages/voucher/voucher" url: "/pages/voucher/voucher"
}), a.isneedUpload = !0); }), a.isneedUpload = !0);

View File

@@ -6,35 +6,19 @@
<view class="money"> <view class="money">
<my-money user="{{user}}"></my-money> <my-money user="{{user}}"></my-money>
<view class="marquee-wrap" wx:if="{{notice}}"> <view class="marquee-wrap" wx:if="{{notice}}">
<view bindtap="toPage" class="marquee-content" data-refresh="1" data-url="{{noticeurl}}"> <view bindtap="toPage" class="marquee-content" data-refresh="1" data-url="{{noticeurl}}"> {{notice}} </view>
{{notice}}
</view> </view>
</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="pageList" data="{{urlList:urlList}}"></template>
<template is="wangdianList" data="{{wangdianList:wangdianList}}"></template> <template is="wangdianList" data="{{wangdianList:wangdianList}}"></template>
<service-tel></service-tel> <service-tel></service-tel>
<view bindtap="toScan" class="scan-btn" wx:if="{{!isScan}}"> <view bindtap="toScan" class="scan-btn" wx:if="{{!isScan}}"><view class="sha">扫码启动</view></view>
<view class="sha">扫码启动</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>
<view bindtap="toStart" class="scan-btn" wx:if="{{isScan}}"> <view bindtap="toStart" class="two-btns yue">
<view class="sha">立即启动</view> <view>余额启动</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> </view>

View File

@@ -32,6 +32,17 @@
position: static; 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 { .start-btn-box .scan-subscribe {
margin-right: 10rpx; margin-right: 10rpx;
} }
@@ -118,7 +129,7 @@
top: -20rpx; top: -20rpx;
color: #fff; color: #fff;
background-color: #0056A3; background-color: #0056A3;
font-size: 22rpx; font-size: 24rpx;
padding: 0 12rpx; padding: 0 12rpx;
line-height: 36rpx; line-height: 36rpx;
border-radius: 0 0 0 20rpx; border-radius: 0 0 0 20rpx;
@@ -158,68 +169,3 @@
display: block; display: block;
background-color: #37CE05; 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({ Page({
data: { data: {
banner: [], banner: [],
selectIndex: 0 list: [],
loading: !1,
message: "",
selectItemID: null,
approve: !0,
protocol: {
url: "",
name: "聚美汽服购买协议"
},
isSubmit: !1
},
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: "网络异常,请稍后重试"
});
});
}, },
onLoad: function(n) {},
onReady: function() {},
onShow: function() {},
onHide: function() {},
onUnload: function() {},
onPullDownRefresh: function() {},
onReachBottom: function() {},
onShareAppMessage: function() {},
selectItem: function (n) { 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({ this.setData({
selectIndex: n.currentTarget.dataset.index approve: 1 == i
}); });
} }
}); });

View File

@@ -1,12 +1,44 @@
<view class="container"> <view class="container">
<head-swiper banner="{{banner}}"></head-swiper> <head-swiper banner="{{banner}}"></head-swiper>
<view class="title-tips">请选择单次洗车金额</view> <view class="title-tips">请选择单次洗车金额</view>
<view class="list"> <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>
<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> <service-tel tel="{{servicetel}}"></service-tel>
<view class="footer-btn-box">
<view class="btn yellow">余额洗车</view>
<view class="btn">单次启动</view>
</view>
</view> </view>

View File

@@ -11,42 +11,163 @@
padding: 0; padding: 0;
} }
.item { .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;
}
.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;
}
.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; background-color: #fff;
border-radius: 18rpx; }
box-shadow: 0 0rpx 9rpx 4rpx hsla(0,0%,40%,.3);
color: #333; .list .item .j {
font-size: 87rpx; left: 158rpx;
height: 180rpx; top: 0;
line-height: 180rpx; height: 153rpx;
margin-bottom: 32rpx; width: 138rpx;
font-size: 66rpx;
line-height: 108rpx;
text-align: center; text-align: center;
} }
.item.active { .list .item .j .p {
box-shadow: 0 0rpx 9rpx 4rpx rgba(255,102,0,.3); font-size: 26rpx;
color: #f60; line-height: 1;
} }
.footer-btn-box { .list .item .t {
bottom: 0; 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; color: #fff;
display: flex; display: flex;
font-size: 44rpx; font-size: 33rpx;
left: 0; height: 91rpx;
position: fixed;
width: 100vw;
}
.footer-btn-box .btn {
align-items: center;
background: #4cadf1;
display: inline-flex;
flex: 1;
height: 104rpx;
justify-content: center; justify-content: center;
margin-top: 3rpx;
} }
.btn.yellow { .tobuy-btn.disabled {
background: #fccaa9; 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;
} }