style: 压缩顺运宝工具条 (#219)
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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 采集中"},
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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%; }
|
||||||
|
|||||||
@@ -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)同步`,
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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` 显示“核对采购订单”,
|
||||||
并在详情中明确提示可能已经下单、必须先核对。两种状态都不允许勾选或重新采购。
|
并在详情中明确提示可能已经下单、必须先核对。两种状态都不允许勾选或重新采购。
|
||||||
|
|||||||
Reference in New Issue
Block a user