style: 压缩顺运宝工具条 (#219)

This commit is contained in:
chengma
2026-08-13 15:28:45 +08:00
parent d2cb2b6d1a
commit 1ba5c88604
7 changed files with 106 additions and 12 deletions
+8
View File
@@ -372,6 +372,14 @@ func TestSybPage_紧凑筛选和可见横向滚动(t *testing.T) {
`body.syb-page-body`, `body.syb-page-body`,
`height: 100dvh`, `height: 100dvh`,
`body.syb-page-body > .page`, `body.syb-page-body > .page`,
`.visually-hidden`,
`.syb-date-separator`,
`@media (min-width: 1360px)`,
`.syb-toolbar`,
`flex-wrap: nowrap`,
`.syb-toolbar .syb-filter-form`,
`width: 116px`,
`width: 138px`,
} { } {
if !strings.Contains(string(css), want) { if !strings.Contains(string(css), want) {
t.Errorf("顺运宝紧凑列表样式缺少 %q", want) t.Errorf("顺运宝紧凑列表样式缺少 %q", want)
+1 -1
View File
@@ -1097,7 +1097,7 @@ type SybStageOption struct {
func SybStageOptions() []SybStageOption { func SybStageOptions() []SybStageOption {
return []SybStageOption{ return []SybStageOption{
{Value: "", Text: "全部"}, {Value: "", Text: "全部"},
{Value: SybStageSpecMissing, Text: "采购数据异常:顺运宝未提供规格"}, {Value: SybStageSpecMissing, Text: "顺运宝未提供规格"},
{Value: SybStagePddMissing, Text: "未关联 PDD"}, {Value: SybStagePddMissing, Text: "未关联 PDD"},
{Value: SybStagePddPending, Text: "PDD 待采集"}, {Value: SybStagePddPending, Text: "PDD 待采集"},
{Value: SybStagePddCollecting, Text: "PDD 采集中"}, {Value: SybStagePddCollecting, Text: "PDD 采集中"},
+24 -1
View File
@@ -167,12 +167,35 @@ func TestSybStageFor_全部筛选阶段与逐行推导一致(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
stage, text, _, action := sybStageFor(tc.context) stage, text, _, action := sybStageFor(tc.context)
if stage != tc.want || text != SybStageLabel(tc.want) || action != tc.action { wantText := SybStageLabel(tc.want)
if tc.want == SybStageSpecMissing {
// 筛选项为了工具条宽度使用短文案,行详情继续明确这是采购数据异常。
wantText = "采购数据异常:顺运宝未提供规格"
}
if stage != tc.want || text != wantText || action != tc.action {
t.Fatalf("阶段 %s 推导错误: stage=%s text=%q action=%q", tc.want, stage, text, action) t.Fatalf("阶段 %s 推导错误: stage=%s text=%q action=%q", tc.want, stage, text, action)
} }
} }
} }
func TestSybStageOptions_缺规格筛选文案简洁且详情原因完整(t *testing.T) {
var filterText string
for _, option := range SybStageOptions() {
if option.Value == SybStageSpecMissing {
filterText = option.Text
break
}
}
if filterText != "顺运宝未提供规格" {
t.Fatalf("缺规格筛选文案错误: %q", filterText)
}
stage, stageText, help, _ := sybStageFor(repository.SybOrderContext{})
if stage != SybStageSpecMissing || stageText != "采购数据异常:顺运宝未提供规格" ||
!strings.Contains(help, "不能匹配或创建采购任务") {
t.Fatalf("缩短筛选项不得丢失详情原因: stage=%q text=%q help=%q", stage, stageText, help)
}
}
func TestSybOrderViewFor_批量动作能力按阶段隔离(t *testing.T) { func TestSybOrderViewFor_批量动作能力按阶段隔离(t *testing.T) {
base := repository.SybOrderContext{ base := repository.SybOrderContext{
Order: model.SybOrder{SybID: "SYB-1", SpecKey: "黑色,M", Quantity: 1}, Order: model.SybOrder{SybID: "SYB-1", SpecKey: "黑色,M", Quantity: 1},
+47
View File
@@ -7,6 +7,19 @@
* { box-sizing: border-box; } * { box-sizing: border-box; }
/* 视觉上隐藏,但继续让屏幕阅读器读取。表单控件不能只剩占位符或装饰文字。 */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
body { body {
margin: 0; margin: 0;
font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif; font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
@@ -155,6 +168,40 @@ body.syb-page-body > .page {
resize: vertical; resize: vertical;
} }
.syb-order-search-input[aria-invalid="true"] { border-color: #b42318; } .syb-order-search-input[aria-invalid="true"] { border-color: #b42318; }
/* SYB 工具条在 1366px 桌面窗口压成一行。所有规则都限定在本页面,避免影响
其他主列表;窄于该断点时继续使用通用 toolbar 的自然换行。 */
.syb-date-separator { color: #667085; }
@media (min-width: 1360px) {
.syb-toolbar {
flex-wrap: nowrap;
gap: 4px;
padding: 8px 10px;
}
.syb-toolbar .inline { gap: 4px; }
.syb-toolbar button,
.syb-toolbar .button-link {
padding-right: 7px;
padding-left: 7px;
}
.syb-toolbar input,
.syb-toolbar select,
.syb-toolbar textarea,
.syb-toolbar button,
.syb-toolbar .button-link { font-size: 13px; }
.syb-toolbar .sync-range-form input[type="date"] {
width: 116px;
min-width: 116px;
}
.syb-toolbar .syb-filter-form {
flex: 1 1 auto;
min-width: 0;
}
.syb-toolbar .syb-filter-form select {
width: 138px;
min-width: 138px;
}
}
/* 蝦皮工具条同时放商品和店铺两个搜索框,各占剩余工具条的约 20%。 /* 蝦皮工具条同时放商品和店铺两个搜索框,各占剩余工具条的约 20%。
min-width 继续由通用输入框规则提供,窄窗口时交给工具条自然换行。 */ min-width 继续由通用输入框规则提供,窄窗口时交给工具条自然换行。 */
.toolbar input[type="text"].shopee-search-field { flex: 0 1 20%; } .toolbar input[type="text"].shopee-search-field { flex: 0 1 20%; }
+10 -1
View File
@@ -86,8 +86,15 @@ func TestSybListTemplate_区分标题图片与阶段动作(t *testing.T) {
`data-select-action="collect"`, `data-select-action="collect"`,
`form="syb-collect-form"`, `form="syb-collect-form"`,
`id="syb-collect-modal"`, `id="syb-collect-modal"`,
`>创建采集任务</button>`, `aria-label="创建采集任务">创建采集</button>`,
`aria-label="创建采购任务">创建采购</button>`,
`<h2 id="syb-collect-modal-title">创建采集任务</h2>`, `<h2 id="syb-collect-modal-title">创建采集任务</h2>`,
`<h2 id="purchase-modal-title">确认创建采购任务</h2>`,
`class="toolbar syb-toolbar"`,
`class="visually-hidden" for="sync-date-from">开始日期</label>`,
`class="syb-date-separator" aria-hidden="true">-</span>`,
`class="visually-hidden" for="sync-date-to">结束日期</label>`,
`class="inline grow syb-filter-form"`,
`class="syb-search-input"`, `class="syb-search-input"`,
`订单号(可多条)`, `订单号(可多条)`,
`textarea id="q" name="order_no" rows="1"`, `textarea id="q" name="order_no" rows="1"`,
@@ -121,6 +128,8 @@ func TestSybListTemplate_区分标题图片与阶段动作(t *testing.T) {
`<td>SYB-READY</td>`, `<td>SYB-READY</td>`,
`>创建 PDD 采集任务</button>`, `>创建 PDD 采集任务</button>`,
`<h2 id="syb-collect-modal-title">创建 PDD 采集任务</h2>`, `<h2 id="syb-collect-modal-title">创建 PDD 采集任务</h2>`,
`data-need-checked="collect">创建采集任务</button>`,
`data-purchase-open>创建采购任务</button>`,
`每行只显示当前最需要完成的下一步`, `每行只显示当前最需要完成的下一步`,
`按顺运宝货运单创建日期(UTC+8)同步`, `按顺运宝货运单创建日期(UTC+8)同步`,
} { } {
+7 -6
View File
@@ -1,17 +1,18 @@
{{define "syb/list"}} {{define "syb/list"}}
{{template "header" .}} {{template "header" .}}
<div class="toolbar"> <div class="toolbar syb-toolbar">
<form class="inline sync-range-form" method="post" action="/syb/sync" data-syb-sync-form> <form class="inline sync-range-form" method="post" action="/syb/sync" data-syb-sync-form>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}"> <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="order_no" value="{{.Keyword}}"> <input type="hidden" name="order_no" value="{{.Keyword}}">
<input type="hidden" name="shop" value="{{.ShopFilter}}"> <input type="hidden" name="shop" value="{{.ShopFilter}}">
<input type="hidden" name="stage" value="{{.StageFilter}}"> <input type="hidden" name="stage" value="{{.StageFilter}}">
<input type="hidden" name="page" value="{{.CurrentPage}}"> <input type="hidden" name="page" value="{{.CurrentPage}}">
<label for="sync-date-from">开始日期</label> <label class="visually-hidden" for="sync-date-from">开始日期</label>
<input id="sync-date-from" type="date" name="date_from" <input id="sync-date-from" type="date" name="date_from"
value="{{.SyncDateFrom}}" max="{{.Today}}" required> value="{{.SyncDateFrom}}" max="{{.Today}}" required>
<label for="sync-date-to">结束日期</label> <span class="syb-date-separator" aria-hidden="true">-</span>
<label class="visually-hidden" for="sync-date-to">结束日期</label>
<input id="sync-date-to" type="date" name="date_to" <input id="sync-date-to" type="date" name="date_to"
value="{{.SyncDateTo}}" max="{{.Today}}" required> value="{{.SyncDateTo}}" max="{{.Today}}" required>
<button type="submit" class="primary" data-syb-sync-submit <button type="submit" class="primary" data-syb-sync-submit
@@ -30,12 +31,12 @@
<input type="hidden" name="page" value="{{.CurrentPage}}" form="syb-collect-form"> <input type="hidden" name="page" value="{{.CurrentPage}}" form="syb-collect-form">
<button type="button" data-modal-open="syb-collect-modal" data-collect-open <button type="button" data-modal-open="syb-collect-modal" data-collect-open
data-collect-form="syb-collect-form" data-collect-action="collect" data-collect-form="syb-collect-form" data-collect-action="collect"
data-need-checked="collect">创建采集任务</button> data-need-checked="collect" aria-label="创建采集任务">创建采集</button>
<button type="button" data-need-checked="purchase" data-modal-open="purchase-modal" <button type="button" data-need-checked="purchase" data-modal-open="purchase-modal"
data-purchase-open>创建采购任务</button> data-purchase-open aria-label="创建采购任务">创建采购</button>
<form class="inline grow" method="get" action="/syb"> <form class="inline grow syb-filter-form" method="get" action="/syb">
<label for="stage">处理阶段</label> <label for="stage">处理阶段</label>
<select id="stage" name="stage"> <select id="stage" name="stage">
{{range .StageOptions}} {{range .StageOptions}}
+9 -3
View File
@@ -475,10 +475,16 @@ Go 的 map 是无序的,不靠它定顺序的话,同一个商品每次刷新
### 6.1 工具条 ### 6.1 工具条
```text ```text
开始日期 [2026-08-08] 结束日期 [2026-08-09] [同步] [同步记录] [2026-08-08] - [2026-08-09] [同步] [同步记录] [创建采集] [创建采购]
[创建采集任务] [创建采购任务] 处理阶段 [全部] 店铺 [___] 订单号 [___] [清除] [搜索] [删除] 处理阶段 [全部] 店铺 [___] 订单号 [___] [清除] [搜索] [删除]
``` ```
1366×768 及更宽的桌面窗口中,上述控件保持在同一行;更窄窗口允许自然换行,不得为了
强制单行产生水平溢出。紧凑间距、日期和阶段宽度只能通过 SYB 专用 class 调整,不能修改
其他模块共用的 `.toolbar`。日期不显示“开始日期/结束日期”文字,以 `-` 作为视觉分隔,
但两个日期 input 必须继续关联完整的视觉隐藏 label。列表批量按钮使用短文案“创建采集”
和“创建采购”,其无障碍名称与确认弹窗标题仍保留完整的“创建…任务”语义。
日期始终显示在主工具条,按 UTC+8 解释且两端都包含。首次打开页面固定默认昨天 日期始终显示在主工具条,按 UTC+8 解释且两端都包含。首次打开页面固定默认昨天
到今天,不因覆盖游标位置自动扩大范围;需要补历史缺口时由采购员明确选择日期。 到今天,不因覆盖游标位置自动扩大范围;需要补历史缺口时由采购员明确选择日期。
同步日期规则和当前启用店铺数量不再使用常驻说明占用列表空间;日期错误、同步警告、 同步日期规则和当前启用店铺数量不再使用常驻说明占用列表空间;日期错误、同步警告、
@@ -559,7 +565,7 @@ HTML 片段,只替换弹窗内部的表格、总数和分页。主货运单表
图片加载失败时显示可读提示。`[必须]` 只存 URL,不代理、缓存或把图片塞进数据库。 图片加载失败时显示可读提示。`[必须]` 只存 URL,不代理、缓存或把图片塞进数据库。
- 处理阶段不作为独立列表列显示,但顶部筛选、勾选门禁、下一步路由和详情说明继续使用。 - 处理阶段不作为独立列表列显示,但顶部筛选、勾选门禁、下一步路由和详情说明继续使用。
阶段按当前关联事实**算出来**,不是存一份容易过期的状态字段。阶段至少区分: 阶段按当前关联事实**算出来**,不是存一份容易过期的状态字段。阶段至少区分:
采购数据异常(顺运宝未提供规格)、未关联 PDD、PDD 待采集、采集中、采集中(超时)、 顺运宝未提供规格、未关联 PDD、PDD 待采集、采集中、采集中(超时)、
采集失败、规格待匹配、可采购、已创建任务、采购完成和采购待人工核对。 采集失败、规格待匹配、可采购、已创建任务、采购完成和采购待人工核对。
- 成功采购任务的下一步显示“查看采购结果”;`manual_review` 显示“核对采购订单”, - 成功采购任务的下一步显示“查看采购结果”;`manual_review` 显示“核对采购订单”,
并在详情中明确提示可能已经下单、必须先核对。两种状态都不允许勾选或重新采购。 并在详情中明确提示可能已经下单、必须先核对。两种状态都不允许勾选或重新采购。