fix(v1.8.1): 按次显示已完成/总次数、隐藏已开通套餐、已结束订阅置灰置底
1) 按次计费显示口径 - 订阅卡片、列表、大屏 TOP 都从「剩 x / y 次」改为「已完成 x / y 次」 - 进度条改为按已用次数计算 2) 开通订阅下拉过滤 - 客户详情「开通订阅」下拉自动隐藏该客户已开通的套餐,延期只能走「追加」入口,避免新开叠加 - 若客户已开通全部套餐,下拉只剩占位项 3) 已结束订阅置灰置底 - 客户详情的订阅卡片按「进行中 → 已结束」排序,已结束排到最后 - 已结束卡片降低透明度、降低饱和度,鼠标悬停恢复部分可见 数据库:无变更 测试: - 功能验证 5 项:按次文案、已开通套餐不在下拉、未开通仍可选、已结束卡片置灰、已结束排在最后 - 119 项验收回归全绿(8 条按次断言随之更新为新口径) - 无头 Chrome 实拍客户详情页;版本号 1.8.1
This commit is contained in:
@@ -323,12 +323,32 @@ func (s *Server) handleCustomerDetail(w http.ResponseWriter, r *http.Request) {
|
|||||||
pauses, _ := s.db.PausesForSubs(ids)
|
pauses, _ := s.db.PausesForSubs(ids)
|
||||||
|
|
||||||
users, _ := s.db.ActiveUsers()
|
users, _ := s.db.ActiveUsers()
|
||||||
|
// 已开通的套餐不再出现在「开通订阅」下拉里,延期走追加
|
||||||
|
owned := map[int64]bool{}
|
||||||
|
for _, sub := range subs {
|
||||||
|
owned[sub.PackageID] = true
|
||||||
|
}
|
||||||
|
available := make([]store.Package, 0, len(pkgs))
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if !owned[pkg.ID] {
|
||||||
|
available = append(available, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sorted := append([]store.Subscription{}, subs...)
|
||||||
|
sort.SliceStable(sorted, func(i, j int) bool {
|
||||||
|
ai := sorted[i].Status == domain.StatusClosed
|
||||||
|
aj := sorted[j].Status == domain.StatusClosed
|
||||||
|
if ai != aj {
|
||||||
|
return !ai
|
||||||
|
}
|
||||||
|
return sorted[i].ID < sorted[j].ID
|
||||||
|
})
|
||||||
data := &customerDetailData{
|
data := &customerDetailData{
|
||||||
Users: users,
|
Users: users,
|
||||||
CustCal: s.buildCustomerCal(c, r.URL.Query().Get("cm"), today),
|
CustCal: s.buildCustomerCal(c, r.URL.Query().Get("cm"), today),
|
||||||
Customer: c,
|
Customer: c,
|
||||||
Subs: subViews(subs, today, warn),
|
Subs: subViews(sorted, today, warn),
|
||||||
Packages: pkgs,
|
Packages: available,
|
||||||
Timeline: buildTimeline(subs, pauses, today),
|
Timeline: buildTimeline(subs, pauses, today),
|
||||||
AdjSubName: map[int64]string{},
|
AdjSubName: map[int64]string{},
|
||||||
AdjSubColor: map[int64]string{},
|
AdjSubColor: map[int64]string{},
|
||||||
|
|||||||
@@ -1109,3 +1109,13 @@ fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
|
|||||||
.season-band.start { border-top-left-radius: 3px; border-bottom-left-radius: 3px; left: 2px; }
|
.season-band.start { border-top-left-radius: 3px; border-bottom-left-radius: 3px; left: 2px; }
|
||||||
.season-band.end { border-top-right-radius: 3px; border-bottom-right-radius: 3px; right: 2px; }
|
.season-band.end { border-top-right-radius: 3px; border-bottom-right-radius: 3px; right: 2px; }
|
||||||
.cal-cell.has-due .season-band { bottom: 4px; }
|
.cal-cell.has-due .season-band { bottom: 4px; }
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- v1.8.1:已结束订阅置灰 ---------- */
|
||||||
|
|
||||||
|
.subcard.is-closed {
|
||||||
|
opacity: 0.55;
|
||||||
|
filter: saturate(0.5);
|
||||||
|
background: var(--surface-2);
|
||||||
|
}
|
||||||
|
.subcard.is-closed:hover { opacity: 0.8; }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "sub-card"}}
|
{{define "sub-card"}}
|
||||||
<article class="subcard" id="sub-{{.ID}}" style="--tag:{{.PackageColor}}">
|
<article class="subcard{{if eq .Status "closed"}} is-closed{{end}}" id="sub-{{.ID}}" style="--tag:{{.PackageColor}}">
|
||||||
<div class="subcard-head">
|
<div class="subcard-head">
|
||||||
<span class="tag"></span>
|
<span class="tag"></span>
|
||||||
<h3>{{.PackageName}}</h3>
|
<h3>{{.PackageName}}</h3>
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ func newSubView(s store.Subscription, today time.Time, warnDays int) SubView {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
v.UnitLabel = "按次"
|
v.UnitLabel = "按次"
|
||||||
v.RemainText = fmt.Sprintf("剩 %d / %d 次", e.RemainingCount, s.TotalCount)
|
v.RemainText = fmt.Sprintf("已完成 %d / %d 次", s.UsedCount, s.TotalCount)
|
||||||
v.RemainShort = fmt.Sprintf("%d 次", e.RemainingCount)
|
v.RemainShort = fmt.Sprintf("%d/%d 次", s.UsedCount, s.TotalCount)
|
||||||
v.PeriodText = s.StartDate + " 起"
|
v.PeriodText = s.StartDate + " 起"
|
||||||
if s.EndDate != "" {
|
if s.EndDate != "" {
|
||||||
v.PeriodText += " · 有效期至 " + s.EndDate
|
v.PeriodText += " · 有效期至 " + s.EndDate
|
||||||
@@ -112,6 +112,7 @@ func newSubView(s store.Subscription, today time.Time, warnDays int) SubView {
|
|||||||
v.PeriodText += " · 无有效期"
|
v.PeriodText += " · 无有效期"
|
||||||
}
|
}
|
||||||
if s.TotalCount > 0 {
|
if s.TotalCount > 0 {
|
||||||
|
v.Progress = clampPct(s.UsedCount * 100 / s.TotalCount)
|
||||||
v.Progress = clampPct(e.RemainingCount * 100 / s.TotalCount)
|
v.Progress = clampPct(e.RemainingCount * 100 / s.TotalCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
"daili/internal/web"
|
"daili/internal/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "1.8.0"
|
const version = "1.8.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfgFlag := flag.String("config", "", "配置文件路径(默认:exe 同级的 "+config.FileName+")")
|
cfgFlag := flag.String("config", "", "配置文件路径(默认:exe 同级的 "+config.FileName+")")
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ $r = Send $admin 'POST' "/customers/$custID/subscriptions" @{ package_id = '2';
|
|||||||
Check 'U-02' '开通按次订阅(10 次 / 有效期 T+10)' ((Has $r.Content '已开通')) "flash=$(Flash $r.Content)"
|
Check 'U-02' '开通按次订阅(10 次 / 有效期 T+10)' ((Has $r.Content '已开通')) "flash=$(Flash $r.Content)"
|
||||||
$r = Send $admin 'GET' "/customers/$custID"
|
$r = Send $admin 'GET' "/customers/$custID"
|
||||||
$p2ID = (SubIDs $r.Content)[1]
|
$p2ID = (SubIDs $r.Content)[1]
|
||||||
Check 'U-02b' '按次剩余 10/10 次' ((Has $r.Content '剩 10 / 10 次')) ""
|
Check 'U-02b' '按次已完成 0/10 次' ((Has $r.Content '已完成 0 / 10 次')) ""
|
||||||
|
|
||||||
$r = Send $admin 'POST' "/customers/$custID/subscriptions" @{ package_id = '1'; start_date = $today; days = '30' }
|
$r = Send $admin 'POST' "/customers/$custID/subscriptions" @{ package_id = '1'; start_date = $today; days = '30' }
|
||||||
Check 'U-03' '重复订阅被拦截' ((Has $r.Content '已订阅此套餐')) "flash=$(Flash $r.Content)"
|
Check 'U-03' '重复订阅被拦截' ((Has $r.Content '已订阅此套餐')) "flash=$(Flash $r.Content)"
|
||||||
@@ -239,7 +239,7 @@ $before = (Send $admin 'GET' "/customers/$custID").Content
|
|||||||
$r = Send $admin 'POST' '/packages' @{ name = '副本五次'; unit = 'count'; default_amount = '5'; price = '120'; color = '#41556B'; note = '无有效期'; sort_order = '3' }
|
$r = Send $admin 'POST' '/packages' @{ name = '副本五次'; unit = 'count'; default_amount = '5'; price = '120'; color = '#41556B'; note = '无有效期'; sort_order = '3' }
|
||||||
Check 'P-05' '新增套餐 D 成功' ((Has $r.Content '套餐已创建')) ""
|
Check 'P-05' '新增套餐 D 成功' ((Has $r.Content '套餐已创建')) ""
|
||||||
$after = (Send $admin 'GET' "/customers/$custID").Content
|
$after = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'P-05b' '新增套餐后既有订阅剩余量不变' ((Has $after '剩 30 天') -and (Has $after '剩 10 / 10 次')) ""
|
Check 'P-05b' '新增套餐后既有订阅进度不变' ((Has $after '剩 30 天') -and (Has $after '已完成 0 / 10 次')) ""
|
||||||
|
|
||||||
$r = Send $admin 'POST' "/customers/$custID/subscriptions" @{ package_id = '3'; start_date = $today; total_count = '5' }
|
$r = Send $admin 'POST' "/customers/$custID/subscriptions" @{ package_id = '3'; start_date = $today; total_count = '5' }
|
||||||
Check 'U-04' '开通第三个套餐(无有效期按次)' ((Has $r.Content '已开通')) "flash=$(Flash $r.Content)"
|
Check 'U-04' '开通第三个套餐(无有效期按次)' ((Has $r.Content '已开通')) "flash=$(Flash $r.Content)"
|
||||||
@@ -313,7 +313,7 @@ Check 'E-07' '已结束订阅不可追加' ((Has $r.Content '请先「重新启
|
|||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/extend" @{ add_count = '5'; note = '加购 5 次'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/extend" @{ add_count = '5'; note = '加购 5 次'; back = "/customers/$custID" }
|
||||||
$d4 = (Send $admin 'GET' "/customers/$custID").Content
|
$d4 = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'E-08' '按次追加次数' ((Has $r.Content '已追加 5 次') -and (Has $d4 '剩 15 / 15 次')) "flash=$(Flash $r.Content)"
|
Check 'E-08' '按次追加次数' ((Has $r.Content '已追加 5 次') -and (Has $d4 '已完成 0 / 15 次')) "flash=$(Flash $r.Content)"
|
||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/extend" @{ add_count = '5'; new_end_opt = (D 30); note = '加次并延期'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/extend" @{ add_count = '5'; new_end_opt = (D 30); note = '加次并延期'; back = "/customers/$custID" }
|
||||||
$d5 = (Send $admin 'GET' "/customers/$custID").Content
|
$d5 = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
@@ -365,22 +365,22 @@ Check 'K-02' '按日打卡不扣天数' ((Has $d '剩 30 天')) ""
|
|||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'K-03' '按次打卡扣 1 次' ((Has $d '剩 19 / 20 次')) ""
|
Check 'K-03' '按次打卡扣 1 次' ((Has $d '已完成 1 / 20 次')) ""
|
||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'K-04' '同日重复打卡不重复扣次' ((Has $d '剩 19 / 20 次')) ""
|
Check 'K-04' '同日重复打卡不重复扣次' ((Has $d '已完成 1 / 20 次')) ""
|
||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'skipped'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'skipped'; back = "/customers/$custID" }
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'K-05' '改为跳过返还 1 次' ((Has $d '剩 20 / 20 次')) ""
|
Check 'K-05' '改为跳过返还 1 次' ((Has $d '已完成 0 / 20 次')) ""
|
||||||
|
|
||||||
Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" } | Out-Null
|
Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" } | Out-Null
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
$ciID = (Dbtool @('scalar', $Db, "SELECT id FROM checkins WHERE sub_id=$p2ID AND service_date='$today'")).Trim()
|
$ciID = (Dbtool @('scalar', $Db, "SELECT id FROM checkins WHERE sub_id=$p2ID AND service_date='$today'")).Trim()
|
||||||
$r = Send $admin 'POST' "/checkins/$ciID/delete" @{ back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/checkins/$ciID/delete" @{ back = "/customers/$custID" }
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'K-06' '撤销打卡返还次数' ((Has $r.Content '已撤销') -and (Has $d '剩 20 / 20 次')) "flash=$(Flash $r.Content)"
|
Check 'K-06' '撤销打卡返还次数' ((Has $r.Content '已撤销') -and (Has $d '已完成 0 / 20 次')) "flash=$(Flash $r.Content)"
|
||||||
|
|
||||||
Dbtool @('exec', $Db, "UPDATE subscriptions SET used_count=total_count WHERE id=$p2ID") | Out-Null
|
Dbtool @('exec', $Db, "UPDATE subscriptions SET used_count=total_count WHERE id=$p2ID") | Out-Null
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p2ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
||||||
@@ -395,7 +395,7 @@ Check 'K-11' '无有效期订阅卡片有「今日打卡」按钮' ((Has $r.Cont
|
|||||||
|
|
||||||
$r = Send $admin 'POST' "/subscriptions/$p3ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
$r = Send $admin 'POST' "/subscriptions/$p3ID/checkin" @{ date = $today; status = 'done'; back = "/customers/$custID" }
|
||||||
$d = (Send $admin 'GET' "/customers/$custID").Content
|
$d = (Send $admin 'GET' "/customers/$custID").Content
|
||||||
Check 'K-09' '无有效期按次订阅可打卡扣次' ((Has $d '剩 4 / 5 次')) "flash=$(Flash $r.Content)"
|
Check 'K-09' '无有效期按次订阅可打卡扣次' ((Has $d '已完成 1 / 5 次')) "flash=$(Flash $r.Content)"
|
||||||
Check 'K-10' '打卡历史含日期/备注/操作人' ((Has $d '今日已打') -or (Has $d '完成')) ""
|
Check 'K-10' '打卡历史含日期/备注/操作人' ((Has $d '今日已打') -or (Has $d '完成')) ""
|
||||||
|
|
||||||
Write-Host "`n=== 11. 日历(L) ===" -ForegroundColor Cyan
|
Write-Host "`n=== 11. 日历(L) ===" -ForegroundColor Cyan
|
||||||
|
|||||||
Reference in New Issue
Block a user