Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
prd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
caoxu
prd
Commits
f09046f9
Commit
f09046f9
authored
Jan 14, 2026
by
Jose
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化数量控制:添加最少1项和最多99项的限制,显示相应提示
parent
85b0cc3d
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
107 additions
and
18 deletions
+107
-18
ServiceDetailsView.vue
src/views/ServiceDetailsView.vue
+107
-18
No files found.
src/views/ServiceDetailsView.vue
View file @
f09046f9
<
template
>
<div
class=
"service-details"
>
<!-- Toast notification -->
<div
class=
"toast"
v-if=
"showToast"
>
{{
toastMessage
}}
</div>
<!-- Header with back arrow and title -->
<div
class=
"page-header"
>
<button
class=
"back-button"
>
...
...
@@ -123,6 +126,7 @@
v-for=
"coupon in coupons"
:key=
"coupon.id"
:class=
"
{ active: selectedCoupon === coupon.id }"
@click="toggleCoupon(coupon.id)"
>
<div
class=
"coupon-info"
>
...
...
@@ -138,7 +142,7 @@
class=
"coupon-checkbox"
:id=
"`coupon-$
{coupon.id}`"
:checked="selectedCoupon === coupon.id"
@click.stop
disabled="true"
/>
<label
:for=
"`coupon-$
{coupon.id}`" class="coupon-checkbox-label">
</label>
</div>
...
...
@@ -177,6 +181,27 @@ const discountCode = ref('')
const
showCoupons
=
ref
(
false
)
const
selectedCoupon
=
ref
(
null
)
// Toast notification state
const
showToast
=
ref
(
false
)
const
toastMessage
=
ref
(
''
)
const
toastTimeout
=
ref
(
null
)
// Show toast message
const
showToastMessage
=
(
message
)
=>
{
toastMessage
.
value
=
message
showToast
.
value
=
true
// Clear any existing timeout
if
(
toastTimeout
.
value
)
{
clearTimeout
(
toastTimeout
.
value
)
}
// Hide toast after 2 seconds
toastTimeout
.
value
=
setTimeout
(()
=>
{
showToast
.
value
=
false
},
2000
)
}
// Add-ons data - initial data for anytime
const
addons
=
ref
([
{
...
...
@@ -280,12 +305,20 @@ const updateAddonsByDate = () => {
resetDiscountCode
()
// Update total price after resetting addons quantities
updateTotalPrice
()
// Show toast message only if it's not initial load
if
(
!
isInitialLoad
.
value
)
{
showToastMessage
(
'1 更新班期价格
\
n2 重置数量选择
\
n3 重置优惠券部分数据
\
n4 更新价格接口'
)
}
isInitialLoad
.
value
=
false
}
// Price related state - initial values
const
originalPrice
=
ref
(
0
)
// Original price before discount
const
originalPrice
=
ref
(
998
)
// Original price before discount, default 998
const
discountAmount
=
ref
(
0
)
// Discount amount
const
totalPrice
=
ref
(
0
)
// Final price after discount
const
totalPrice
=
ref
(
998
)
// Final price after discount, default 998
// Flag to track if it's initial load
const
isInitialLoad
=
ref
(
true
)
// Extract numeric price from price string
const
extractPrice
=
(
priceString
)
=>
{
...
...
@@ -383,21 +416,36 @@ const updateAddonQuantity = (index, change) => {
// If this is the last item with quantity >= 1 and we're trying to decrease it below 1
if
(
totalItemsWithQuantity
===
1
&&
currentQuantity
<=
1
)
{
// Show toast message
showToastMessage
(
'最少至少选中一项,禁止都变成0'
)
// Don't allow decreasing - keep it at 1
return
}
}
// Check if quantity exceeds maximum (99)
if
(
newQuantity
>
99
)
{
// Show toast message
showToastMessage
(
'最多99'
)
// Don't allow increasing beyond 99
addons
.
value
[
index
].
quantity
=
99
}
else
{
// Update quantity if valid
addons
.
value
[
index
].
quantity
=
Math
.
max
(
0
,
newQuantity
)
updateTotalPrice
()
// Reset discount code result set when addon quantity changes
// Reset discount code first
resetDiscountCode
()
// Then update total price
updateTotalPrice
()
// Show toast message when addon quantity changes
showToastMessage
(
'1 重置优惠券部分
\
n2 更新价格接口'
)
}
}
// 打开弹层的函数
const
openPopup
=
()
=>
{
showPopup
.
value
=
true
// Show toast message when opening popup
showToastMessage
(
'1 更新班期价格
\
n2 重置数量选择
\
n3 重置优惠券部分数据
\
n4 更新价格接口'
)
}
// 关闭弹层的函数
...
...
@@ -407,15 +455,16 @@ const closePopup = () => {
// 切换优惠券选择状态 - 实现单选和取消选择
const
toggleCoupon
=
(
couponId
)
=>
{
// 简化逻辑,直接切换选中状态
if
(
selectedCoupon
.
value
===
couponId
)
{
// 如果当前优惠券已选中,取消选择
selectedCoupon
.
value
=
null
}
else
{
// 否则选中当前优惠券
selectedCoupon
.
value
=
couponId
}
// 重新计算总价
updateTotalPrice
()
// Show toast message when toggling coupon selection
showToastMessage
(
'1 更新优惠券数据
\
n2 更新价格接口'
)
}
// 应用折扣码的函数
...
...
@@ -426,6 +475,8 @@ const applyDiscount = () => {
selectedCoupon
.
value
=
coupons
.
value
[
0
].
id
// 联动价格更新
updateTotalPrice
()
// Show toast message when applying discount code
showToastMessage
(
'1 更新优惠券数据
\
n2 更新价格接口'
)
}
}
...
...
@@ -796,28 +847,26 @@ const selectCoupon = (couponId) => {
.discount-input
{
flex
:
1
;
padding
:
1
2pt
;
/*
16px = 12pt */
padding
:
1
0.5pt
12pt
;
/* 14px = 10.5pt,
16px = 12pt */
border
:
0.75pt
solid
#ddd
;
/* 1px = 0.75pt */
border-radius
:
8pt
;
/* 10px = 8pt */
font-size
:
1
5pt
;
/* 20px = 1
5pt */
font-size
:
1
4.25pt
;
/* 19px = 14.2
5pt */
outline
:
none
;
transition
:
border-color
0.2s
ease
;
}
.discount-input
:focus
{
border-color
:
#42b883
;
min-width
:
0
;
/* 确保flex项能正确收缩 */
}
.apply-btn
{
padding
:
1
2pt
;
/* 16px = 12pt, 30px = 22.5
pt */
padding
:
1
0.5pt
24pt
;
/* 14px = 10.5pt, 32px = 24
pt */
background-color
:
#42b883
;
color
:
white
;
border
:
none
;
border-radius
:
8pt
;
/* 10px = 8pt */
font-size
:
1
5pt
;
/* 20px = 1
5pt */
font-size
:
1
4.25pt
;
/* 19px = 14.2
5pt */
font-weight
:
500
;
cursor
:
pointer
;
transition
:
background-color
0.2s
ease
;
white-space
:
nowrap
;
/* 防止按钮文字换行 */
}
.apply-btn
:hover
{
...
...
@@ -1124,4 +1173,44 @@ const selectCoupon = (couponId) => {
background-color
:
#369c6a
;
box-shadow
:
0
2.25pt
6pt
rgba
(
66
,
184
,
131
,
0.4
);
/* 3px = 2.25pt, 8px = 6pt */
}
/* Toast notification styles */
.toast
{
position
:
fixed
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
background-color
:
rgba
(
0
,
0
,
0
,
0.8
);
color
:
white
;
padding
:
12pt
24pt
;
border-radius
:
8pt
;
font-size
:
13pt
;
font-weight
:
500
;
z-index
:
1000
;
box-shadow
:
0
3pt
10pt
rgba
(
0
,
0
,
0
,
0.3
);
animation
:
fadeInOut
2s
ease
;
text-align
:
left
;
max-width
:
80%
;
white-space
:
pre-line
;
line-height
:
1.5
;
}
@keyframes
fadeInOut
{
0
%
{
opacity
:
0
;
transform
:
translate
(
-50%
,
-50%
)
scale
(
0.9
);
}
20
%
{
opacity
:
1
;
transform
:
translate
(
-50%
,
-50%
)
scale
(
1
);
}
80
%
{
opacity
:
1
;
transform
:
translate
(
-50%
,
-50%
)
scale
(
1
);
}
100
%
{
opacity
:
0
;
transform
:
translate
(
-50%
,
-50%
)
scale
(
0.9
);
}
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment