diff --git a/admin/inner_code_template_test.go b/admin/inner_code_template_test.go
index 7183ab1..5cb37db 100644
--- a/admin/inner_code_template_test.go
+++ b/admin/inner_code_template_test.go
@@ -50,7 +50,7 @@ func TestInnerCodeTemplate_模块状态白名单已登记(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if !strings.Contains(string(raw), `"/inner-codes": ["date", "status", "q", "page"]`) {
+ if !strings.Contains(string(raw), `"/inner-codes": ["date", "status", "q", "page", "page_size"]`) {
t.Fatal("档口入库码页面切换模块后应保持稳定筛选和页码")
}
for _, want := range []string{
diff --git a/admin/main_test.go b/admin/main_test.go
index b9dbb3b..f8f225f 100644
--- a/admin/main_test.go
+++ b/admin/main_test.go
@@ -67,8 +67,13 @@ func TestModuleNavigation_按账号保存稳定列表状态且安全回退(t *te
jsSource := string(js)
for _, want := range []string{
"var MODULE_QUERY_KEYS = {",
- "\"/shopee\": [\"q\", \"search_field\", \"status\", \"deleted\", \"unlinked\", \"page\"]",
- "\"/syb\": [\"order_no\", \"shop\", \"stage\", \"page\", \"date_from\", \"date_to\"]",
+ "\"/shopee\": [\"q\", \"search_field\", \"status\", \"deleted\", \"unlinked\", \"page\", \"page_size\"]",
+ "\"/pdd\": [\"q\", \"status\", \"page\", \"page_size\"]",
+ "\"/syb\": [\"order_no\", \"shop\", \"stage\", \"page\", \"page_size\", \"date_from\", \"date_to\"]",
+ "\"/tasks\": [\"type\", \"status\", \"creator\", \"q\", \"page\", \"page_size\"]",
+ "\"/clients\": [\"name\", \"page\", \"page_size\"]",
+ "\"/inner-codes\": [\"date\", \"status\", \"q\", \"page\", \"page_size\"]",
+ "\"/users\": [\"q\", \"status\", \"page\", \"page_size\"]",
"var MODULE_STATE_PREFIX = \"cmautobuy:module-state:\"",
"parsed.origin !== window.location.origin || parsed.pathname !== moduleRoot",
"sessionStorage.setItem(",
@@ -96,6 +101,42 @@ func TestModuleNavigation_按账号保存稳定列表状态且安全回退(t *te
}
}
+func TestPageSizeSelect_切换后自动提交且保留无脚本回退(t *testing.T) {
+ footer, err := os.ReadFile("templates/partials/footer.html")
+ if err != nil {
+ t.Fatal(err)
+ }
+ footerSource := string(footer)
+ for _, want := range []string{
+ `method="get" class="page-size-form" data-page-size-form`,
+ `name="page_size" data-page-size-select`,
+ `type="submit" data-page-size-submit>应用`,
+ } {
+ if !strings.Contains(footerSource, want) {
+ t.Errorf("公共分页缺少渐进增强回退 %q", want)
+ }
+ }
+
+ js, err := os.ReadFile("static/js/app.js")
+ if err != nil {
+ t.Fatal(err)
+ }
+ jsSource := string(js)
+ for _, want := range []string{
+ `function setupPageSizeForms()`,
+ `select.addEventListener("change"`,
+ `form.getAttribute("aria-busy") === "true"`,
+ `form.requestSubmit()`,
+ `if (beginSubmit()) form.submit()`,
+ `submit.textContent = "加载中…"`,
+ `setupPageSizeForms();`,
+ } {
+ if !strings.Contains(jsSource, want) {
+ t.Errorf("分页容量自动提交缺少交互约束 %q", want)
+ }
+ }
+}
+
func TestPurchaseModal_未选规格行保持隐藏且不提交(t *testing.T) {
files := map[string][]string{
"static/css/app.css": {
diff --git a/admin/static/js/app.js b/admin/static/js/app.js
index 9d93303..eae4e91 100644
--- a/admin/static/js/app.js
+++ b/admin/static/js/app.js
@@ -17,14 +17,14 @@
都不进入 sessionStorage。链接原始 href 保持模块根地址,因此脚本失效时
仍可正常导航。 */
var MODULE_QUERY_KEYS = {
- "/shopee": ["q", "search_field", "status", "deleted", "unlinked", "page"],
- "/pdd": ["q", "status", "page"],
- "/syb": ["order_no", "shop", "stage", "page", "date_from", "date_to"],
+ "/shopee": ["q", "search_field", "status", "deleted", "unlinked", "page", "page_size"],
+ "/pdd": ["q", "status", "page", "page_size"],
+ "/syb": ["order_no", "shop", "stage", "page", "page_size", "date_from", "date_to"],
"/shops": [],
- "/tasks": ["type", "status", "creator", "q", "page"],
- "/clients": ["name", "page"],
- "/inner-codes": ["date", "status", "q", "page"],
- "/users": ["q", "status", "page"]
+ "/tasks": ["type", "status", "creator", "q", "page", "page_size"],
+ "/clients": ["name", "page", "page_size"],
+ "/inner-codes": ["date", "status", "q", "page", "page_size"],
+ "/users": ["q", "status", "page", "page_size"]
};
var MODULE_STATE_PREFIX = "cmautobuy:module-state:";
@@ -92,6 +92,40 @@
}
}
+ /* ── 每页条数立即生效 ─────────────────────────
+ 普通 GET 表单仍是无 JavaScript 时的完整回退;脚本只做渐进增强,让采购员
+ 选择 20/50/100 后不用再点一次“应用”。select 不能禁用,否则浏览器提交时
+ 会丢掉 page_size。 */
+ function setupPageSizeForms() {
+ document.querySelectorAll("[data-page-size-form]").forEach(function (form) {
+ var select = form.querySelector("[data-page-size-select]");
+ var submit = form.querySelector("[data-page-size-submit]");
+ if (!select) return;
+
+ function beginSubmit() {
+ if (form.getAttribute("aria-busy") === "true") return false;
+ form.setAttribute("aria-busy", "true");
+ if (submit) {
+ submit.disabled = true;
+ submit.textContent = "加载中…";
+ }
+ return true;
+ }
+
+ form.addEventListener("submit", function () {
+ beginSubmit();
+ });
+ select.addEventListener("change", function () {
+ if (form.getAttribute("aria-busy") === "true") return;
+ if (typeof form.requestSubmit === "function") {
+ form.requestSubmit();
+ return;
+ }
+ if (beginSubmit()) form.submit();
+ });
+ });
+ }
+
/* ── 全选 / 反选 ──────────────────────────────
表头的勾选框控制本表格所有行的勾选框。 */
function setupCheckAll(root) {
@@ -853,6 +887,7 @@
document.addEventListener("DOMContentLoaded", function () {
setupModuleNavigationState();
+ setupPageSizeForms();
document.querySelectorAll("table").forEach(setupCheckAll);
setupConfirmDelete();
setupConfirmSubmit();
diff --git a/admin/templates/partials/footer.html b/admin/templates/partials/footer.html
index 7f9cb9d..a86bbd7 100644
--- a/admin/templates/partials/footer.html
+++ b/admin/templates/partials/footer.html
@@ -14,18 +14,18 @@
{{.Status}}
{{if .Pagination}}