From 523365960513f297024a419f94b2b42eccd9456f Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 09 四月 2026 11:21:41 +0800
Subject: [PATCH] #
---
rsf-design/src/api/asn-order-log.js | 7
rsf-design/src/views/dashboard/console/index.vue | 279 +++++--------
rsf-server/src/main/resources/mapper/manager/AsnOrderMapper.xml | 14
rsf-design/src/views/orders/asn-order-log/index.vue | 200 +++++++--
rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageResult.java | 43 ++
rsf-design/package.json | 1
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/AsnOrderMapper.java | 9
rsf-design/src/plugins/iconify.collections.js | 51 +
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java | 195 +++++++++
rsf-design/scripts/build-local-iconify-collections.mjs | 2
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderLogController.java | 30 +
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java | 140 +++++
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderLog.java | 31 -
rsf-design/pnpm-lock.yaml | 10
rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageParam.java | 68 +++
rsf-design/src/views/orders/asn-order-log/asnOrderLogPage.helpers.js | 20
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderPressureSchedules.java | 131 ++---
17 files changed, 855 insertions(+), 376 deletions(-)
diff --git a/rsf-design/package.json b/rsf-design/package.json
index 50c1f4f..d93dcac 100644
--- a/rsf-design/package.json
+++ b/rsf-design/package.json
@@ -26,6 +26,7 @@
"@iconify-json/ix": "^1.2.11",
"@iconify-json/line-md": "^1.2.16",
"@iconify-json/ri": "^1.2.10",
+ "@iconify-json/solar": "^1.2.5",
"@iconify-json/svg-spinners": "^1.2.4",
"@iconify-json/system-uicons": "^1.2.4",
"@iconify-json/vaadin": "^1.2.1",
diff --git a/rsf-design/pnpm-lock.yaml b/rsf-design/pnpm-lock.yaml
index f72aaef..6c53174 100644
--- a/rsf-design/pnpm-lock.yaml
+++ b/rsf-design/pnpm-lock.yaml
@@ -29,6 +29,9 @@
'@iconify-json/ri':
specifier: ^1.2.10
version: 1.2.10
+ '@iconify-json/solar':
+ specifier: ^1.2.5
+ version: 1.2.5
'@iconify-json/svg-spinners':
specifier: ^1.2.4
version: 1.2.4
@@ -628,6 +631,9 @@
'@iconify-json/ri@1.2.10':
resolution: {integrity: sha512-WWMhoncVVM+Xmu9T5fgu2lhYRrKTEWhKk3Com0KiM111EeEsRLiASjpsFKnC/SrB6covhUp95r2mH8tGxhgd5Q==}
+
+ '@iconify-json/solar@1.2.5':
+ resolution: {integrity: sha512-WMAiNwchU8zhfrySww6KQBRIBbsQ6SvgIu2yA+CHGyMima/0KQwT5MXogrZPJGoQF+1Ye3Qj6K+1CiyNn3YkoA==}
'@iconify-json/svg-spinners@1.2.4':
resolution: {integrity: sha512-ayn0pogFPwJA1WFZpDnoq9/hjDxN+keeCMyThaX4d3gSJ3y0mdKUxIA/b1YXWGtY9wVtZmxwcvOIeEieG4+JNg==}
@@ -3537,6 +3543,10 @@
dependencies:
'@iconify/types': 2.0.0
+ '@iconify-json/solar@1.2.5':
+ dependencies:
+ '@iconify/types': 2.0.0
+
'@iconify-json/svg-spinners@1.2.4':
dependencies:
'@iconify/types': 2.0.0
diff --git a/rsf-design/scripts/build-local-iconify-collections.mjs b/rsf-design/scripts/build-local-iconify-collections.mjs
index ca02615..e5fbd27 100644
--- a/rsf-design/scripts/build-local-iconify-collections.mjs
+++ b/rsf-design/scripts/build-local-iconify-collections.mjs
@@ -9,6 +9,7 @@
import { icons as ixIcons } from '@iconify-json/ix'
import { icons as lineMdIcons } from '@iconify-json/line-md'
import { icons as remixIcons } from '@iconify-json/ri'
+import { icons as solarIcons } from '@iconify-json/solar'
import { icons as svgSpinnersIcons } from '@iconify-json/svg-spinners'
import { icons as systemUiconsIcons } from '@iconify-json/system-uicons'
import { icons as vaadinIcons } from '@iconify-json/vaadin'
@@ -25,6 +26,7 @@
ix: ixIcons,
'line-md': lineMdIcons,
ri: remixIcons,
+ solar: solarIcons,
'svg-spinners': svgSpinnersIcons,
'system-uicons': systemUiconsIcons,
vaadin: vaadinIcons
diff --git a/rsf-design/src/api/asn-order-log.js b/rsf-design/src/api/asn-order-log.js
index e0d5bff..1fec1e2 100644
--- a/rsf-design/src/api/asn-order-log.js
+++ b/rsf-design/src/api/asn-order-log.js
@@ -1,4 +1,5 @@
import request from '@/utils/http'
+import { buildAsnOrderLogPageQueryParams } from '@/views/orders/asn-order-log/asnOrderLogPage.helpers'
function normalizeText(value) {
return typeof value === 'string' ? value.trim() : value
@@ -31,11 +32,7 @@
}
export function buildAsnOrderLogPageParams(params = {}) {
- return {
- current: params.current || 1,
- pageSize: params.pageSize || params.size || 20,
- ...filterParams(params, ['current', 'pageSize', 'size'])
- }
+ return buildAsnOrderLogPageQueryParams(params)
}
export function buildAsnOrderItemLogPageParams(params = {}) {
diff --git a/rsf-design/src/plugins/iconify.collections.js b/rsf-design/src/plugins/iconify.collections.js
index d729dbb..a8795f90 100644
--- a/rsf-design/src/plugins/iconify.collections.js
+++ b/rsf-design/src/plugins/iconify.collections.js
@@ -112,8 +112,11 @@
'book-2-line': {
body: '<path fill="currentColor" d="M21 18H6a1 1 0 1 0 0 2h15v2H6a3 3 0 0 1-3-3V4a2 2 0 0 1 2-2h16zM5 16.05q.243-.05.5-.05H19V4H5zM16 9H8V7h8z"/>'
},
- 'chat-1-line': {
- body: '<path fill="currentColor" d="M10 3h4a8 8 0 1 1 0 16v3.5c-5-2-12-5-12-11.5a8 8 0 0 1 8-8m2 14h2a6 6 0 0 0 0-12h-4a6 6 0 0 0-6 6c0 3.61 2.462 5.966 8 8.48z"/>'
+ 'chat-3-line': {
+ body: '<path fill="currentColor" d="M7.291 20.824L2 22l1.176-5.291A9.96 9.96 0 0 1 2 12C2 6.477 6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10a9.96 9.96 0 0 1-4.709-1.176m.29-2.113l.653.35A7.96 7.96 0 0 0 12 20a8 8 0 1 0-8-8c0 1.335.325 2.617.94 3.766l.349.653l-.655 2.947z"/>'
+ },
+ 'chat-history-line': {
+ body: '<path fill="currentColor" d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10a9.96 9.96 0 0 1-4.708-1.175L2 22l1.176-5.29A9.96 9.96 0 0 1 2 12C2 6.477 6.477 2 12 2m0 2a8 8 0 0 0-8 8c0 1.335.326 2.618.94 3.766l.35.654l-.656 2.946l2.948-.654l.653.349A7.96 7.96 0 0 0 12 20a8 8 0 1 0 0-16m1 3v5h4v2h-6V7z"/>'
},
'check-fill': {
body: '<path fill="currentColor" d="m10 15.17l9.192-9.191l1.414 1.414L10 17.999l-6.364-6.364l1.414-1.414z"/>'
@@ -136,6 +139,9 @@
'close-large-fill': {
body: '<path fill="currentColor" d="M10.586 12L2.793 4.207l1.414-1.414L12 10.586l7.793-7.793l1.414 1.414L13.414 12l7.793 7.793l-1.414 1.414L12 13.414l-7.793 7.793l-1.414-1.414z"/>'
},
+ 'close-line': {
+ body: '<path fill="currentColor" d="m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z"/>'
+ },
'coin-line': {
body: '<path fill="currentColor" d="M12.005 4.003c6.075 0 11 2.686 11 6v4c0 3.314-4.925 6-11 6c-5.967 0-10.824-2.591-10.995-5.823l-.005-.177v-4c0-3.314 4.925-6 11-6m0 12c-3.72 0-7.01-1.008-9-2.55v.55c0 1.882 3.883 4 9 4c5.01 0 8.838-2.03 8.995-3.882l.005-.118l.001-.55c-1.99 1.542-5.28 2.55-9.001 2.55m0-10c-5.117 0-9 2.118-9 4s3.883 4 9 4s9-2.118 9-4s-3.883-4-9-4"/>'
},
@@ -145,6 +151,9 @@
'computer-line': {
body: '<path fill="currentColor" d="M4 16h16V5H4zm9 2v2h4v2H7v-2h4v-2H2.992A1 1 0 0 1 2 16.992V4.008C2 3.451 2.455 3 2.992 3h18.016c.548 0 .992.449.992 1.007v12.985c0 .557-.455 1.008-.992 1.008z"/>'
},
+ 'cpu-line': {
+ body: '<path fill="currentColor" d="M6 18h12V6H6zm8 2h-4v2H8v-2H5a1 1 0 0 1-1-1v-3H2v-2h2v-4H2V8h2V5a1 1 0 0 1 1-1h3V2h2v2h4V2h2v2h3a1 1 0 0 1 1 1v3h2v2h-2v4h2v2h-2v3a1 1 0 0 1-1 1h-3v2h-2zM8 8h8v8H8z"/>'
+ },
'delete-bin-4-line': {
body: '<path fill="currentColor" d="M20 7v14a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7H2V5h20v2zM6 7v13h12V7zm1-5h10v2H7zm4 8h2v7h-2z"/>'
},
@@ -153,6 +162,9 @@
},
'delete-bin-6-line': {
body: '<path fill="currentColor" d="M7 4V2h10v2h5v2h-2v15a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6H2V4zM6 6v14h12V6zm3 3h2v8H9zm4 0h2v8h-2z"/>'
+ },
+ 'delete-bin-line': {
+ body: '<path fill="currentColor" d="M17 6h5v2h-2v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V8H2V6h5V3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1zm1 2H6v12h12zm-9 3h2v6H9zm4 0h2v6h-2zM9 4v2h6V4z"/>'
},
'drag-move-2-fill': {
body: '<path fill="currentColor" d="M18 11V8l4 4l-4 4v-3h-5v5h3l-4 4l-4-4h3v-5H6v3l-4-4l4-4v3h5V6H8l4-4l4 4h-3v5z"/>'
@@ -165,6 +177,9 @@
},
'edit-2-line': {
body: '<path fill="currentColor" d="M5 18.89h1.414l9.314-9.314l-1.414-1.414L5 17.476zm16 2H3v-4.243L16.435 3.212a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L9.243 18.89H21zM15.728 6.748l1.414 1.414l1.414-1.414l-1.414-1.414z"/>'
+ },
+ 'edit-line': {
+ body: '<path fill="currentColor" d="M6.414 15.89L16.556 5.748l-1.414-1.414L5 14.476v1.414zm.829 2H3v-4.243L14.435 2.212a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414zM3 19.89h18v2H3z"/>'
},
'error-warning-line': {
body: '<path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10m0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16m-1-5h2v2h-2zm0-8h2v6h-2z"/>'
@@ -193,12 +208,6 @@
'fullscreen-line': {
body: '<path fill="currentColor" d="M8 3v2H4v4H2V3zM2 21v-6h2v4h4v2zm20 0h-6v-2h4v-4h2zm0-12h-2V5h-4V3h6z"/>'
},
- 'function-line': {
- body: '<path fill="currentColor" d="M3 4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1zm0 10a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1zM13 4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1zm0 10a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1zm2-9v4h4V5zm0 10v4h4v-4zM5 5v4h4V5zm0 10v4h4v-4z"/>'
- },
- 'github-line': {
- body: '<path fill="currentColor" d="M5.884 18.653c-.3-.2-.558-.455-.86-.816a51 51 0 0 1-.466-.579c-.463-.575-.755-.841-1.056-.95a1 1 0 1 1 .675-1.882c.752.27 1.261.735 1.947 1.588c-.094-.117.34.427.433.539c.19.227.33.365.44.438c.204.137.588.196 1.15.14c.024-.382.094-.753.202-1.095c-2.968-.726-4.648-2.64-4.648-6.396c0-1.24.37-2.356 1.058-3.292c-.218-.894-.185-1.975.302-3.192a1 1 0 0 1 .63-.582c.081-.024.127-.035.208-.047c.803-.124 1.937.17 3.415 1.096a11.7 11.7 0 0 1 2.687-.308c.912 0 1.819.104 2.684.308c1.477-.933 2.614-1.227 3.422-1.096q.128.02.218.05a1 1 0 0 1 .616.58c.487 1.216.52 2.296.302 3.19c.691.936 1.058 2.045 1.058 3.293c0 3.757-1.674 5.665-4.642 6.392c.125.415.19.878.19 1.38c0 .665-.002 1.299-.007 2.01c0 .19-.002.394-.005.706a1 1 0 0 1-.018 1.958c-1.14.227-1.984-.532-1.984-1.525l.002-.447l.005-.705c.005-.707.008-1.337.008-1.997c0-.697-.184-1.152-.426-1.361c-.661-.57-.326-1.654.541-1.751c2.966-.333 4.336-1.482 4.336-4.66c0-.955-.312-1.744-.913-2.404A1 1 0 0 1 17.2 6.19c.166-.414.236-.957.095-1.614l-.01.003c-.491.139-1.11.44-1.858.949a1 1 0 0 1-.833.135a9.6 9.6 0 0 0-2.592-.349c-.89 0-1.772.118-2.592.35a1 1 0 0 1-.829-.134c-.753-.507-1.374-.807-1.87-.947c-.143.653-.072 1.194.093 1.607a1 1 0 0 1-.189 1.045c-.597.655-.913 1.458-.913 2.404c0 3.172 1.371 4.328 4.322 4.66c.865.097 1.202 1.177.545 1.748c-.193.168-.43.732-.43 1.364v3.15c0 .985-.834 1.725-1.96 1.528a1 1 0 0 1-.04-1.962v-.99c-.91.061-1.661-.088-2.254-.485"/>'
- },
'group-line': {
body: '<path fill="currentColor" d="M2 22a8 8 0 1 1 16 0h-2a6 6 0 0 0-12 0zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6s6 2.685 6 6s-2.685 6-6 6m0-2c2.21 0 4-1.79 4-4s-1.79-4-4-4s-4 1.79-4 4s1.79 4 4 4m8.284 3.703A8 8 0 0 1 23 22h-2a6 6 0 0 0-3.537-5.473zm-.688-11.29A5.5 5.5 0 0 1 21 8.5a5.5 5.5 0 0 1-5 5.478v-2.013a3.5 3.5 0 0 0 1.041-6.609z"/>'
},
@@ -226,8 +235,14 @@
'line-chart-line': {
body: '<path fill="currentColor" d="M5 3v16h16v2H3V3zm15.293 3.293l1.414 1.414L16 13.414l-3-2.999l-4.293 4.292l-1.414-1.414L13 7.586l3 2.999z"/>'
},
+ 'list-check-3': {
+ body: '<path fill="currentColor" d="M8 6v3H5V6zM3 4v7h7V4zm10 0h8v2h-8zm0 7h8v2h-8zm0 7h8v2h-8zm-2.293-1.793l-1.414-1.414L6 18.086l-1.793-1.793l-1.414 1.414L6 20.914z"/>'
+ },
'lock-line': {
body: '<path fill="currentColor" d="M19 10h1a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V11a1 1 0 0 1 1-1h1V9a7 7 0 0 1 14 0zM5 12v8h14v-8zm6 2h2v4h-2zm6-4V9A5 5 0 0 0 7 9v1z"/>'
+ },
+ 'magic-line': {
+ body: '<path fill="currentColor" d="M15.199 9.944a2.6 2.6 0 0 1-.79-1.55l-.403-3.083l-2.731 1.486a2.6 2.6 0 0 1-1.719.272L6.5 6.5l.57 3.056a2.6 2.6 0 0 1-.273 1.72l-1.486 2.73l3.083.403a2.6 2.6 0 0 1 1.55.79l2.138 2.257l1.336-2.807a2.6 2.6 0 0 1 1.23-1.231l2.808-1.336zm.025 5.564l-2.213 4.65a.6.6 0 0 1-.977.155l-3.542-3.739a.6.6 0 0 0-.358-.182l-5.106-.668a.6.6 0 0 1-.45-.881l2.462-4.524a.6.6 0 0 0 .063-.396L4.16 4.86a.6.6 0 0 1 .7-.7l5.062.943a.6.6 0 0 0 .397-.063l4.523-2.46a.6.6 0 0 1 .882.448l.668 5.107a.6.6 0 0 0 .182.357l3.739 3.542a.6.6 0 0 1-.155.977l-4.65 2.213a.6.6 0 0 0-.284.284m.797 1.927l1.414-1.414l4.243 4.242l-1.415 1.415z"/>'
},
'mail-line': {
body: '<path fill="currentColor" d="M3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1m17 4.238l-7.928 7.1L4 7.216V19h16zM4.511 5l7.55 6.662L19.502 5z"/>'
@@ -253,8 +268,8 @@
'more-2-fill': {
body: '<path fill="currentColor" d="M12 3c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2m0 14c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2m0-7c-1.1 0-2 .9-2 2s.9 2 2 2s2-.9 2-2s-.9-2-2-2"/>'
},
- 'notification-2-line': {
- body: '<path fill="currentColor" d="M22 20H2v-2h1v-6.969C3 6.043 7.03 2 12 2s9 4.043 9 9.031V18h1zM5 18h14v-6.969C19 7.148 15.866 4 12 4s-7 3.148-7 7.031zm4.5 3h5a2.5 2.5 0 0 1-5 0"/>'
+ 'node-tree': {
+ body: '<path fill="currentColor" d="M10 2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H8v2h5V9a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-1H8v6h5v-1a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-1H7a1 1 0 0 1-1-1V8H4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1zm9 16h-4v2h4zm0-8h-4v2h4zM9 4H5v2h4z"/>'
},
'notification-3-line': {
body: '<path fill="currentColor" d="M20 17h2v2H2v-2h2v-7a8 8 0 1 1 16 0zm-2 0v-7a6 6 0 0 0-12 0v7zm-9 4h6v2H9z"/>'
@@ -319,6 +334,9 @@
'search-line': {
body: '<path fill="currentColor" d="m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975z"/>'
},
+ 'send-plane-2-line': {
+ body: '<path fill="currentColor" d="M3.5 1.346a.5.5 0 0 1 .241.061l18.462 10.155a.5.5 0 0 1 0 .876L3.741 22.592A.5.5 0 0 1 3 22.154V1.846a.5.5 0 0 1 .5-.5M5 4.382V11h5v2H5v6.617L18.85 12z"/>'
+ },
'send-plane-line': {
body: '<path fill="currentColor" d="m21.727 2.957l-5.454 19.086c-.15.529-.475.553-.717.07L11 13L1.923 9.37c-.51-.205-.503-.51.034-.689L21.043 2.32c.529-.176.832.12.684.638m-2.692 2.14L6.812 9.17l5.637 2.255l3.04 6.08z"/>'
},
@@ -333,6 +351,9 @@
},
'shield-check-line': {
body: '<path fill="currentColor" d="m12 1l8.217 1.826a1 1 0 0 1 .783.976v9.987a6 6 0 0 1-2.672 4.992L12 23l-6.328-4.219A6 6 0 0 1 3 13.79V3.802a1 1 0 0 1 .783-.976zm0 2.049L5 4.604v9.185a4 4 0 0 0 1.781 3.328L12 20.597l5.219-3.48A4 4 0 0 0 19 13.79V4.604zm4.452 5.173l1.415 1.414L11.503 16L7.26 11.757l1.414-1.414l2.828 2.828z"/>'
+ },
+ 'sidebar-unfold-line': {
+ body: '<path fill="currentColor" d="M5 5h8v14H5zm14 14h-4V5h4zM4 3a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm7 9L7 8.5v7z"/>'
},
'smartphone-line': {
body: '<path fill="currentColor" d="M7 4v16h10V4zM6 2h12a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1m6 15a1 1 0 1 1 0 2a1 1 0 0 1 0-2"/>'
@@ -389,6 +410,16 @@
prefix: 'ri',
width: 24
},
+ solar: {
+ height: 24,
+ icons: {
+ 'double-alt-arrow-right-linear': {
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"><path d="m11 19l6-7l-6-7"/><path d="m7 19l6-7l-6-7"/></g>'
+ }
+ },
+ prefix: 'solar',
+ width: 24
+ },
vaadin: {
icons: {
'ctrl-a': {
diff --git a/rsf-design/src/views/dashboard/console/index.vue b/rsf-design/src/views/dashboard/console/index.vue
index 1a2f229..9bfbcc2 100644
--- a/rsf-design/src/views/dashboard/console/index.vue
+++ b/rsf-design/src/views/dashboard/console/index.vue
@@ -1,143 +1,114 @@
<template>
- <div class="art-full-height flex flex-col gap-6">
- <section class="grid gap-6 md:grid-cols-2 xl:grid-cols-4" v-loading="sectionLoading.summary">
+ <div class="art-full-height flex flex-col gap-6 lg:min-h-0 lg:overflow-hidden lg:gap-2">
+ <section class="grid gap-3 md:grid-cols-2 lg:grid-cols-4 lg:shrink-0" v-loading="sectionLoading.summary">
<div
v-for="item in summaryCardItems"
:key="item.title"
- class="art-card flex items-start justify-between rounded-3xl px-7 py-6"
+ class="art-card flex items-start justify-between rounded-3xl px-4 py-4 lg:px-4 lg:py-3 xl:px-5"
>
- <div class="min-w-0 pr-6">
- <p class="text-sm font-medium text-g-700">{{ item.title }}</p>
- <ArtCountTo class="mt-3 block text-[2.3rem] font-semibold leading-none text-g-900" :target="item.count" :duration="1400" />
- <div class="mt-4 flex items-center gap-2 text-sm">
- <span :class="item.metaTone">{{ item.metaLabel }}</span>
- <span class="text-g-500">{{ item.metaValue }}</span>
+ <div class="min-w-0 flex-1 pr-3">
+ <p class="truncate text-sm font-medium text-g-700 lg:text-[13px]">{{ item.title }}</p>
+ <ArtCountTo
+ class="mt-1 block truncate text-[1.95rem] font-semibold leading-none text-g-900 lg:text-[1.72rem] xl:text-[1.92rem]"
+ :target="item.count"
+ :duration="1400"
+ />
+ <div class="mt-1.5 flex items-center gap-1 text-xs lg:text-[12px] xl:text-sm">
+ <span :class="item.metaTone" class="shrink-0">{{ item.metaLabel }}</span>
+ <span class="truncate text-g-500">{{ item.metaValue }}</span>
</div>
</div>
- <div class="flex size-13 shrink-0 items-center justify-center rounded-2xl" :class="item.iconBoxClass">
- <ArtSvgIcon :icon="item.icon" class="text-2xl" :class="item.iconClass" />
+ <div class="flex size-10 shrink-0 items-center justify-center rounded-2xl lg:size-9 xl:size-11" :class="item.iconBoxClass">
+ <ArtSvgIcon :icon="item.icon" class="text-xl xl:text-2xl" :class="item.iconClass" />
</div>
</div>
</section>
- <section class="grid gap-6 xl:grid-cols-[1.35fr_1fr]">
- <div class="art-card h-115 overflow-hidden p-6 box-border">
- <div class="art-card-header">
- <div class="title">
- <h4>杩� 30 澶╁嚭鍏ュ簱瓒嬪娍</h4>
- <p>鐪熷疄閾捐矾 <span class="text-success">宸叉帴閫�</span></p>
+ <section class="flex min-h-0 flex-1 flex-col gap-2">
+ <div class="grid min-h-0 flex-1 gap-2 lg:grid-cols-[1.35fr_1fr]">
+ <div class="art-card box-border flex h-full min-h-0 flex-col overflow-hidden p-4 lg:p-5">
+ <div class="art-card-header">
+ <div class="title">
+ <h4>杩� 30 澶╁嚭鍏ュ簱瓒嬪娍</h4>
+ <p>鐪熷疄閾捐矾 <span class="text-success">宸叉帴閫�</span></p>
+ </div>
+ </div>
+ <div class="mt-3 min-h-0 flex-1">
+ <ArtBarChart
+ height="100%"
+ :loading="sectionLoading.trend"
+ :data="trendChartSeries"
+ :x-axis-data="trendChartXAxisData"
+ :show-axis-line="false"
+ :show-legend="true"
+ :show-split-line="true"
+ legend-position="top"
+ bar-width="38%"
+ />
</div>
</div>
- <div class="h-[calc(100%-4.5rem)]">
- <ArtBarChart
- height="22rem"
- :loading="sectionLoading.trend"
- :data="trendChartSeries"
- :x-axis-data="trendChartXAxisData"
- :show-axis-line="false"
- :show-legend="true"
- :show-split-line="true"
- legend-position="top"
- bar-width="38%"
- />
- </div>
- </div>
- <div class="art-card h-115 overflow-hidden p-6 box-border" v-loading="sectionLoading.locUsage">
- <div class="art-card-header">
- <div class="title">
- <h4>搴撲綅浣跨敤鍒嗗竷</h4>
- <p>{{ usageLegendCount }} 涓淮搴�</p>
+ <div class="art-card box-border flex h-full min-h-0 flex-col overflow-hidden p-4 lg:p-5" v-loading="sectionLoading.locUsage">
+ <div class="art-card-header">
+ <div class="title">
+ <h4>搴撲綅浣跨敤鍒嗗竷</h4>
+ <p>{{ usageLegendCount }} 涓淮搴�</p>
+ </div>
</div>
- </div>
- <div class="grid h-[calc(100%-4.5rem)] gap-6 lg:grid-cols-[1fr_0.95fr] lg:items-center">
- <ArtRingChart
- height="21rem"
- :data="locUsageList"
- center-text="搴撲綅鍗犳瘮"
- :show-legend="false"
- :show-label="false"
- />
-
- <div class="space-y-1">
- <div
- v-for="item in usageLegend"
- :key="item.name"
- class="flex items-center justify-between border-b border-[var(--art-border-color)] py-4 last:border-b-0"
- >
- <div class="flex items-center gap-3">
- <span class="size-2.5 rounded-full" :style="{ backgroundColor: item.color }"></span>
- <span class="text-sm text-[var(--art-gray-900)]">{{ item.name }}</span>
- </div>
- <span class="text-sm font-medium text-[var(--art-gray-700)]">{{ item.value }}%</span>
+ <div class="mt-3 grid min-h-0 flex-1 gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(220px,0.92fr)] lg:items-center">
+ <div class="min-h-0 h-full">
+ <ArtRingChart
+ height="100%"
+ :data="locUsageList"
+ center-text="搴撲綅鍗犳瘮"
+ :show-legend="false"
+ :show-label="false"
+ />
</div>
- <ElEmpty v-if="!locUsageList.length" description="鏆傛棤搴撲綅浣跨敤鏁版嵁" :image-size="88" />
- </div>
- </div>
- </div>
- </section>
-
- <section class="grid gap-6 xl:grid-cols-[0.95fr_1.05fr]">
- <div class="art-card h-98 p-5 box-border" v-loading="sectionLoading.tasks">
- <div class="art-card-header">
- <div class="title">
- <h4>鎵ц涓换鍔�</h4>
- <p>{{ taskSubtitle }}</p>
- </div>
- </div>
-
- <div class="mt-3 h-[calc(100%-3.75rem)] overflow-hidden">
- <ElScrollbar>
- <div
- v-for="item in taskCardItems"
- :key="`${item.time}-${item.title}`"
- class="flex gap-4 border-b border-g-300 py-4 last:border-b-0"
- >
- <div class="flex flex-col items-center pt-1">
- <span class="size-3 rounded-full bg-[var(--el-color-primary)]"></span>
- <span class="mt-2 min-h-10 w-px bg-[var(--art-border-color)]"></span>
- </div>
- <div class="min-w-0 flex-1">
- <p class="text-xs text-g-500">{{ item.time }}</p>
- <div class="mt-2 flex items-center gap-2">
- <p class="truncate text-base font-medium text-[var(--art-gray-900)]">
- {{ item.title }}
- </p>
- <ElTag size="small" effect="light" :type="item.tagType">{{ item.tagText }}</ElTag>
+ <div class="min-h-0 overflow-hidden">
+ <div
+ v-for="item in usageLegend"
+ :key="item.name"
+ class="flex items-center justify-between gap-3 border-b border-[var(--art-border-color)] py-3 last:border-b-0"
+ >
+ <div class="flex items-center gap-3">
+ <span class="size-2.5 rounded-full" :style="{ backgroundColor: item.color }"></span>
+ <span class="truncate text-sm text-[var(--art-gray-900)]">{{ item.name }}</span>
</div>
- <p class="mt-2 text-sm text-g-600">{{ item.subtitle }}</p>
+ <span class="text-sm font-medium text-[var(--art-gray-700)]">{{ item.value }}%</span>
</div>
+
+ <ElEmpty v-if="!locUsageList.length" description="鏆傛棤搴撲綅浣跨敤鏁版嵁" :image-size="88" />
</div>
- </ElScrollbar>
+ </div>
</div>
</div>
- <div class="art-card h-98 p-5 box-border" v-loading="sectionLoading.deadStock">
+ <div class="art-card box-border flex shrink-0 flex-col p-4 lg:p-3.5">
<div class="art-card-header">
<div class="title">
- <h4>搴撳瓨鏈�杩戝姩鎬�</h4>
- <p>{{ deadStockSubtitle }}</p>
+ <h4>蹇嵎璺宠浆</h4>
+ <p>蹇�熻繘鍏ヤ换鍔¢〉鍜屽簱瀛橀〉</p>
</div>
</div>
- <div class="mt-3 h-[calc(100%-3.75rem)] overflow-hidden">
- <ElScrollbar>
- <div
- v-for="item in stockCardItems"
- :key="`${item.title}-${item.time}`"
- class="flex items-center gap-4 border-b border-g-300 py-4 last:border-b-0"
- >
- <div class="size-12 rounded-2xl bg-[var(--el-color-primary-light-9)] flex-cc">
- <ArtSvgIcon :icon="item.icon" class="text-xl text-[var(--el-color-primary)]" />
- </div>
- <div class="min-w-0 flex-1">
- <p class="truncate text-base font-medium text-[var(--art-gray-900)]">{{ item.title }}</p>
- <p class="mt-1 text-sm text-g-500">{{ item.status }}</p>
- </div>
- <div class="max-w-40 text-right text-sm text-g-500">{{ item.time }}</div>
+ <div class="mt-2.5 grid gap-2 md:grid-cols-2">
+ <button
+ v-for="item in quickLinkCards"
+ :key="item.title"
+ type="button"
+ class="flex items-start justify-between rounded-3xl border border-[var(--art-border-color)] bg-[var(--art-main-bg-color)] px-4 py-3 text-left transition hover:border-[var(--el-color-primary-light-5)] hover:bg-[var(--el-color-primary-light-9)]"
+ @click="navigateTo(item.path)"
+ >
+ <div class="min-w-0 pr-4">
+ <p class="text-base font-medium text-[var(--art-gray-900)]">{{ item.title }}</p>
+ <p class="mt-0.5 text-sm text-g-500">{{ item.description }}</p>
</div>
- </ElScrollbar>
+ <div class="flex size-11 shrink-0 items-center justify-center rounded-2xl" :class="item.iconBoxClass">
+ <ArtSvgIcon :icon="item.icon" class="text-xl" :class="item.iconClass" />
+ </div>
+ </button>
</div>
</div>
</section>
@@ -145,44 +116,55 @@
</template>
<script setup>
+ import { useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/store/modules/user'
import {
fetchDashboardHeader,
fetchDashboardTrend,
- fetchDashboardDeadStock,
- fetchDashboardLocUsage,
- fetchDashboardTasks
+ fetchDashboardLocUsage
} from '@/api/dashboard'
import {
EMPTY_SUMMARY,
- buildDashboardDeadStockQuery,
- buildDashboardTaskQuery,
normalizeDashboardSummary,
normalizeDashboardTrend,
- normalizeDashboardTaskList,
normalizeDashboardLocUsage,
- normalizeDashboardDeadStockList,
withDashboardRequestGuard
} from './consolePage.helpers'
defineOptions({ name: 'Console' })
+ const router = useRouter()
const summary = ref({ ...EMPTY_SUMMARY })
const trendModel = ref(normalizeDashboardTrend())
- const taskList = ref([])
- const deadStockList = ref([])
const locUsageList = ref([])
const sectionLoading = reactive({
summary: false,
trend: false,
- deadStock: false,
- locUsage: false,
- tasks: false
+ locUsage: false
})
const userStore = useUserStore()
const { getUserInfo } = storeToRefs(userStore)
+
+ const quickLinkCards = [
+ {
+ title: '浠诲姟椤�',
+ description: '鏌ョ湅鍜屽鐞嗕换鍔$鐞嗘暟鎹�',
+ path: '/manager/task',
+ icon: 'ri:task-line',
+ iconBoxClass: 'bg-[var(--el-color-primary-light-9)]',
+ iconClass: 'text-[var(--el-color-primary)]'
+ },
+ {
+ title: '搴撳瓨椤�',
+ description: '鏌ョ湅褰撳墠搴撳瓨涓庡簱瀛樻槑缁�',
+ path: '/manager/stock',
+ icon: 'ri:archive-stack-line',
+ iconBoxClass: 'bg-[rgba(20,222,186,0.14)]',
+ iconClass: 'text-[#14DEBA]'
+ }
+ ]
const currentUser = computed(() => getUserInfo.value || {})
const currentUserName = computed(() => {
@@ -291,8 +273,6 @@
})
const trendChartXAxisData = computed(() => trendDisplayModel.value.xAxisData)
const trendChartSeries = computed(() => trendDisplayModel.value.series)
- const taskSubtitle = computed(() => `鏈�杩� ${taskList.value.length} 鏉′换鍔″姩鎬乣)
- const deadStockSubtitle = computed(() => `鏈�杩� ${deadStockList.value.length} 鏉″簱瀛樿褰昤)
const usageLegendCount = computed(() => locUsageList.value.length)
const usageLegend = computed(() => {
const palette = ['#5B8FF9', '#5AD8A6', '#5D7092', '#F6BD16', '#E8684A', '#6DC8EC']
@@ -301,16 +281,6 @@
color: palette[index % palette.length]
}))
})
- const taskCardItems = computed(() =>
- taskList.value.slice(0, 6).map((item) => ({
- title: item.title,
- time: item.time,
- subtitle: item.status,
- tagText: resolveTaskTagText(item.status),
- tagType: resolveTaskTagType(item.class)
- }))
- )
- const stockCardItems = computed(() => deadStockList.value.slice(0, 6))
onMounted(() => {
loadDashboard()
@@ -319,9 +289,7 @@
function loadDashboard() {
void loadSummarySection()
void loadTrendSection()
- void loadDeadStockSection()
void loadLocUsageSection()
- void loadTaskSection()
}
async function loadSummarySection() {
@@ -338,16 +306,6 @@
sectionLoading.trend = false
}
- async function loadDeadStockSection() {
- sectionLoading.deadStock = true
- const payload = await withDashboardRequestGuard(
- fetchDashboardDeadStock(buildDashboardDeadStockQuery()),
- {}
- )
- deadStockList.value = normalizeDashboardDeadStockList(payload || {})
- sectionLoading.deadStock = false
- }
-
async function loadLocUsageSection() {
sectionLoading.locUsage = true
const payload = await withDashboardRequestGuard(fetchDashboardLocUsage(), null)
@@ -355,29 +313,8 @@
sectionLoading.locUsage = false
}
- async function loadTaskSection() {
- sectionLoading.tasks = true
- const payload = await withDashboardRequestGuard(
- fetchDashboardTasks(buildDashboardTaskQuery()),
- {}
- )
- taskList.value = normalizeDashboardTaskList(payload || {})
- sectionLoading.tasks = false
- }
-
- function resolveTaskTagType(statusClass) {
- const text = String(statusClass || '')
- if (text.includes('emerald')) return 'success'
- if (text.includes('rose')) return 'danger'
- return 'primary'
- }
-
- function resolveTaskTagText(statusText) {
- const text = String(statusText || '')
- .replace(/\b\d+\./g, '')
- .replace(/\s+/g, ' ')
- .trim()
- const parts = text.split('路').map((item) => item.trim()).filter(Boolean)
- return parts[parts.length - 1] || '澶勭悊涓�'
+ function navigateTo(path) {
+ if (!path) return
+ router.push(path)
}
</script>
diff --git a/rsf-design/src/views/orders/asn-order-log/asnOrderLogPage.helpers.js b/rsf-design/src/views/orders/asn-order-log/asnOrderLogPage.helpers.js
index 49a1d8c..3c8a7d5 100644
--- a/rsf-design/src/views/orders/asn-order-log/asnOrderLogPage.helpers.js
+++ b/rsf-design/src/views/orders/asn-order-log/asnOrderLogPage.helpers.js
@@ -6,6 +6,7 @@
density: 'compact',
showSequence: true
}
+export const DEFAULT_ASN_ORDER_LOG_PAGE_SIZE = 20
const RLE_STATUS_META = {
0: { text: '姝e父', type: 'info' },
@@ -33,6 +34,14 @@
}
const parsed = Number(value)
return Number.isNaN(parsed) ? fallback : parsed
+}
+
+function normalizePositiveInteger(value, fallback) {
+ const parsed = normalizeNumber(value, fallback)
+ if (!Number.isInteger(parsed) || parsed <= 0) {
+ return fallback
+ }
+ return parsed
}
function normalizeDateText(value) {
@@ -119,8 +128,13 @@
export function buildAsnOrderLogPageQueryParams(params = {}) {
return {
- current: params.current || 1,
- pageSize: params.pageSize || params.size || 20,
+ pageSize: normalizePositiveInteger(
+ params.pageSize ?? params.size,
+ DEFAULT_ASN_ORDER_LOG_PAGE_SIZE
+ ),
+ ...(params.cursor !== undefined && params.cursor !== null && params.cursor !== ''
+ ? { cursor: normalizeNumber(params.cursor) }
+ : {}),
...buildAsnOrderLogSearchParams(params)
}
}
@@ -129,7 +143,7 @@
return {
logId: params.logId,
current: params.current || 1,
- pageSize: params.pageSize || params.size || 20
+ pageSize: params.pageSize || params.size || DEFAULT_ASN_ORDER_LOG_PAGE_SIZE
}
}
diff --git a/rsf-design/src/views/orders/asn-order-log/index.vue b/rsf-design/src/views/orders/asn-order-log/index.vue
index 968c48a..d1fc896 100644
--- a/rsf-design/src/views/orders/asn-order-log/index.vue
+++ b/rsf-design/src/views/orders/asn-order-log/index.vue
@@ -34,6 +34,7 @@
:data="data"
:columns="columns"
:pagination="pagination"
+ :pagination-options="mainPaginationOptions"
@selection-change="handleSelectionChange"
@pagination:size-change="handleSizeChange"
@pagination:current-change="handleCurrentChange"
@@ -59,20 +60,20 @@
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/store/modules/user'
- import { useTable } from '@/hooks/core/useTable'
+ import { useTableColumns } from '@/hooks/core/useTableColumns'
import { usePrintExportPage } from '@/views/system/common/usePrintExportPage'
import ListExportPrint from '@/components/biz/list-export-print/index.vue'
import { defaultResponseAdapter } from '@/utils/table/tableUtils'
import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
import { fetchDictDataPage } from '@/api/system-manage'
import {
+ DEFAULT_ASN_ORDER_LOG_PAGE_SIZE,
buildAsnOrderLogDetailQueryParams,
buildAsnOrderLogPageQueryParams,
buildAsnOrderLogPrintRows,
buildAsnOrderLogReportMeta,
buildAsnOrderLogSearchParams,
createAsnOrderLogSearchState,
- getAsnOrderLogExceStatusOptions,
getAsnOrderLogNtyStatusOptions,
getAsnOrderLogRleStatusOptions,
getAsnOrderLogStatusOptions,
@@ -101,6 +102,8 @@
const reportTitle = ASN_ORDER_LOG_REPORT_TITLE
const searchForm = ref(createAsnOrderLogSearchState())
const selectedRows = ref([])
+ const data = ref([])
+ const loading = ref(false)
const detailDrawerVisible = ref(false)
const detailLoading = ref(false)
const detailItemsLoading = ref(false)
@@ -111,6 +114,10 @@
const wkTypeOptions = ref([])
const exceStatusOptions = ref([])
const detailItemColumns = createAsnOrderItemLogColumns()
+ const pageSize = ref(DEFAULT_ASN_ORDER_LOG_PAGE_SIZE)
+ const cursorHistory = ref([null])
+ const nextCursor = ref(null)
+ const hasNext = ref(false)
const detailPagination = reactive({
current: 1,
@@ -119,6 +126,22 @@
})
const reportQueryParams = computed(() => buildAsnOrderLogSearchParams(searchForm.value))
+ const mainPaginationOptions = {
+ layout: 'prev, next, sizes',
+ hideOnSinglePage: false
+ }
+ const pagination = computed(() => {
+ const current = Math.max(1, cursorHistory.value.length || 1)
+ const size = Number(pageSize.value) > 0 ? Number(pageSize.value) : DEFAULT_ASN_ORDER_LOG_PAGE_SIZE
+ const recordCount = Math.max(0, Number(data.value.length) || 0)
+ const total = hasNext.value ? current * size + 1 : (current - 1) * size + recordCount
+
+ return {
+ current,
+ size,
+ total
+ }
+ })
const searchItems = computed(() => [
{
@@ -236,10 +259,48 @@
}
])
- function updatePaginationState(target, response, fallbackCurrent, fallbackSize) {
- target.total = Number(response?.total || 0)
- target.current = Number(response?.current || fallbackCurrent || 1)
- target.size = Number(response?.size || fallbackSize || target.size || 20)
+ const { columns, columnChecks } = useTableColumns(() =>
+ createAsnOrderLogTableColumns({ handleView: openDetail })
+ )
+
+ async function loadMainList({ history = cursorHistory.value } = {}) {
+ loading.value = true
+ try {
+ const normalizedHistory =
+ Array.isArray(history) && history.length > 0 ? [...history] : [null]
+ const response = await guardRequestWithMessage(
+ fetchAsnOrderLogPage(
+ buildAsnOrderLogPageQueryParams({
+ ...searchForm.value,
+ cursor: normalizedHistory[normalizedHistory.length - 1] ?? null,
+ pageSize: pageSize.value
+ })
+ ),
+ {
+ records: [],
+ pageSize: pageSize.value,
+ nextCursor: null,
+ hasNext: false
+ },
+ {
+ timeoutMessage: '鍘嗗彶閫氱煡鍗曞垪琛ㄥ姞杞借秴鏃讹紝宸插仠姝㈢瓑寰�'
+ }
+ )
+
+ cursorHistory.value = normalizedHistory
+ data.value = Array.isArray(response?.records)
+ ? response.records.map((item) => normalizeAsnOrderLogRow(item))
+ : []
+ nextCursor.value = response?.nextCursor ?? null
+ hasNext.value = Boolean(
+ response?.hasNext && response?.nextCursor !== null && response?.nextCursor !== undefined
+ )
+ selectedRows.value = []
+ } catch (error) {
+ ElMessage.error(error?.message || '鑾峰彇鍘嗗彶閫氱煡鍗曞垪琛ㄥけ璐�')
+ } finally {
+ loading.value = false
+ }
}
function openDetail(row) {
@@ -248,30 +309,6 @@
detailDrawerVisible.value = true
loadDetailResources()
}
-
- const {
- columns,
- columnChecks,
- data,
- loading,
- pagination,
- replaceSearchParams,
- resetSearchParams,
- handleSizeChange,
- handleCurrentChange,
- refreshData,
- getData
- } = useTable({
- core: {
- apiFn: fetchAsnOrderLogPage,
- apiParams: buildAsnOrderLogPageQueryParams(searchForm.value),
- columnsFactory: () => createAsnOrderLogTableColumns({ handleView: openDetail })
- },
- transform: {
- dataTransformer: (records) =>
- Array.isArray(records) ? records.map((item) => normalizeAsnOrderLogRow(item)) : []
- }
- })
async function loadDetailResources() {
if (!activeLogId.value) {
@@ -309,12 +346,9 @@
detailItemRows.value = Array.isArray(itemResult.records)
? itemResult.records.map((item) => normalizeAsnOrderItemLogRow(item))
: []
- updatePaginationState(
- detailPagination,
- itemResult,
- detailPagination.current,
- detailPagination.size
- )
+ detailPagination.total = Number(itemResult?.total || 0)
+ detailPagination.current = Number(itemResult?.current || detailPagination.current || 1)
+ detailPagination.size = Number(itemResult?.size || detailPagination.size || 20)
} catch (error) {
detailDrawerVisible.value = false
detailData.value = {}
@@ -330,18 +364,56 @@
selectedRows.value = Array.isArray(rows) ? rows : []
}
- function handleSearch(params) {
+ async function handleSearch(params) {
searchForm.value = {
...searchForm.value,
...params
}
- replaceSearchParams(buildAsnOrderLogSearchParams(searchForm.value))
- getData()
+ await loadMainList({ history: [null] })
}
- function handleReset() {
+ async function handleReset() {
searchForm.value = createAsnOrderLogSearchState()
- resetSearchParams()
+ await loadMainList({ history: [null] })
+ }
+
+ async function handleSizeChange(size) {
+ if (Number(size) <= 0) {
+ return
+ }
+ pageSize.value = Number(size)
+ await loadMainList({ history: [null] })
+ }
+
+ async function handleCurrentChange(current) {
+ const targetPage = Number(current)
+ const currentPage = Number(pagination.value.current)
+
+ if (!Number.isInteger(targetPage) || targetPage <= 0 || targetPage === currentPage) {
+ return
+ }
+ if (loading.value) {
+ return
+ }
+
+ if (targetPage === currentPage + 1) {
+ if (!hasNext.value || nextCursor.value === null || nextCursor.value === undefined) {
+ return
+ }
+ const nextHistory = [...cursorHistory.value, Number(nextCursor.value)]
+ await loadMainList({ history: nextHistory })
+ return
+ }
+
+ if (targetPage === currentPage - 1) {
+ await loadMainList({
+ history: cursorHistory.value.length > 1 ? cursorHistory.value.slice(0, -1) : [null]
+ })
+ }
+ }
+
+ async function refreshData() {
+ await loadMainList()
}
function handleDetailSizeChange(size) {
@@ -368,18 +440,41 @@
}
}
+ async function fetchAllPrintableRecords(queryParams = {}, maxResults = 1000) {
+ const records = []
+ let cursor = null
+ const batchSize = Math.max(Number(pageSize.value) || DEFAULT_ASN_ORDER_LOG_PAGE_SIZE, 100)
+
+ while (records.length < maxResults) {
+ const response = await fetchAsnOrderLogPage(
+ buildAsnOrderLogPageQueryParams({
+ ...queryParams,
+ cursor,
+ pageSize: batchSize
+ })
+ )
+ const pageRecords = Array.isArray(response?.records) ? response.records : []
+
+ if (pageRecords.length === 0) {
+ break
+ }
+
+ records.push(...pageRecords)
+
+ if (!response?.hasNext || response?.nextCursor === null || response?.nextCursor === undefined) {
+ break
+ }
+ cursor = response.nextCursor
+ }
+
+ return records.slice(0, maxResults)
+ }
+
async function resolvePrintRecords(payload) {
if (Array.isArray(payload?.ids) && payload.ids.length > 0) {
return defaultResponseAdapter(await fetchGetAsnOrderLogMany(payload.ids)).records
}
- return defaultResponseAdapter(
- await fetchAsnOrderLogPage({
- ...reportQueryParams.value,
- current: 1,
- pageSize:
- Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20
- })
- ).records
+ return fetchAllPrintableRecords(reportQueryParams.value)
}
const {
@@ -463,6 +558,11 @@
}
onMounted(async () => {
- await Promise.allSettled([loadTypeOptions(), loadWkTypeOptions(), loadExceStatusOptions()])
+ await Promise.allSettled([
+ loadTypeOptions(),
+ loadWkTypeOptions(),
+ loadExceStatusOptions(),
+ loadMainList()
+ ])
})
</script>
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageParam.java
new file mode 100644
index 0000000..34406db
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageParam.java
@@ -0,0 +1,68 @@
+package com.vincent.rsf.server.common.domain;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Map;
+
+/**
+ * 閫氱敤娓告爣鍒嗛〉鍙傛暟銆�
+ *
+ * <p>杩欎釜绫诲湪鐜版湁 {@link BaseParam} 鐨勫熀纭�涓婂彧澧炲姞涓�涓� {@code cursor} 瀛楁锛�
+ * 鐢ㄦ潵琛ㄧず鈥滀笅涓�椤典粠鍝噷缁х画鏌モ�濄��</p>
+ *
+ * <p>褰撳墠椤圭洰閲岀殑鏅�氬垎椤垫帴鍙eぇ澶氳繕鏄� {@code current + pageSize} 妯″紡锛�
+ * 浣嗘父鏍囧垎椤靛彧渚濊禆锛�</p>
+ * <ul>
+ * <li>{@code pageSize}锛氭瘡椤靛ぇ灏�</li>
+ * <li>{@code cursor}锛氫笂涓�椤垫渶鍚庝竴鏉¤褰曠殑娓告爣鍊�</li>
+ * </ul>
+ *
+ * <p>杩欓噷浠嶇劧缁ф壙 {@link BaseParam}锛岀洰鐨勬槸缁х画澶嶇敤鍘熸湁鐨勶細</p>
+ * <ul>
+ * <li>绛涢�夋潯浠惰В鏋�</li>
+ * <li>{@code condition / timeStart / timeEnd} 绛夐�氱敤鍙傛暟</li>
+ * <li>鍜� {@link com.vincent.rsf.server.common.domain.PageParam} 鐨勫崗浣滆兘鍔�</li>
+ * </ul>
+ *
+ * <p>娉ㄦ剰锛氬墠绔嵆浣跨户缁紶 {@code current}锛岃繖閲屼篃涓嶄細鎶ラ敊锛�
+ * {@link BaseParam#syncMap(Map)} 浼氭甯歌В鏋愬畠锛屼絾鍚庣画閫氱敤娓告爣鍒嗛〉閫昏緫涓嶄細浣跨敤瀹冦��</p>
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CursorPageParam extends BaseParam {
+
+ /**
+ * 褰撳墠椤电殑璧峰娓告爣銆�
+ *
+ * <p>绾﹀畾鍚箟鏄細鍙煡璇⑩�滄瘮杩欎釜娓告爣鏇存棫鈥濈殑鏁版嵁锛�
+ * 渚嬪鎸� {@code id desc} 缈婚〉鏃讹紝浼氱敓鎴� {@code id < cursor} 鐨勬潯浠躲��</p>
+ */
+ private Long cursor;
+
+ @Override
+ public void syncMap(Map<String, Object> map) {
+ // 鍏堝鐢� BaseParam 鐨勯�氱敤鍙傛暟瑙f瀽鑳藉姏锛�
+ // 淇濊瘉 pageSize銆乧ondition銆乼imeStart銆乼imeEnd 绛夊瓧娈电収甯稿伐浣溿��
+ super.syncMap(map);
+ if (map == null) {
+ return;
+ }
+ Object cursorValue = map.get("cursor");
+ if (cursorValue == null) {
+ return;
+ }
+ String normalizedValue = String.valueOf(cursorValue).trim();
+ if (normalizedValue.isEmpty()) {
+ // 绌哄瓧绗︿覆娓告爣绛変环浜庘�滈灞忔病鏈夋父鏍団�濓紝杩欓噷鐩存帴绉婚櫎锛岄伩鍏嶅悗缁鍙備笌 SQL銆�
+ map.remove("cursor");
+ return;
+ }
+ // 鐩墠閫氱敤鏂规缁熶竴鎶婃父鏍囩害鏉熶负 Long锛�
+ // 杩欐牱鍙互瑕嗙洊褰撳墠鎸変富閿�/鏁板瓧瀛楁鍊掑簭缈婚〉鐨勪笟鍔″満鏅��
+ this.cursor = Long.parseLong(normalizedValue);
+ // 瑙f瀽瀹屾垚鍚庤浠� map 涓Щ闄わ紝閬垮厤 PageParam.buildWrapper(true)
+ // 鎶� cursor 褰撴垚鏅�氱瓫閫夊瓧娈靛啀娆℃嫾杩� where 鏉′欢銆�
+ map.remove("cursor");
+ }
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageResult.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageResult.java
new file mode 100644
index 0000000..e3a6c21
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/domain/CursorPageResult.java
@@ -0,0 +1,43 @@
+package com.vincent.rsf.server.common.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 閫氱敤娓告爣鍒嗛〉杩斿洖浣撱��
+ *
+ * <p>瀵瑰鍝嶅簲缁撴瀯鍒绘剰淇濇寔绠�鍗曪紝鍙毚闇叉父鏍囧垎椤电湡姝i渶瑕佺殑 4 涓瓧娈碉紝
+ * 涓嶅啀杩斿洖浼犵粺椤电爜鍒嗛〉閲岀殑 {@code total/current/pages}銆�</p>
+ *
+ * <p>瀛楁璇箟绾﹀畾锛�</p>
+ * <ul>
+ * <li>{@code records}锛氬綋鍓嶉〉瀹為檯杩斿洖鐨勬暟鎹�</li>
+ * <li>{@code pageSize}锛氭湰娆℃煡璇㈡渶缁堥噰鐢ㄧ殑鍒嗛〉澶у皬锛堝寘鍚粯璁ゅ�煎洖閫�鍚庣殑缁撴灉锛�</li>
+ * <li>{@code nextCursor}锛氫笅涓�椤靛簲褰撲娇鐢ㄧ殑娓告爣锛涙病鏈変笅涓�椤垫椂涓� {@code null}</li>
+ * <li>{@code hasNext}锛氭槸鍚﹁繕鏈変笅涓�椤�</li>
+ * </ul>
+ *
+ * <p>杩欐牱璁捐鐨勭洰鐨勬槸璁� controller 鐩存帴 {@code R.ok().add(result)}锛�
+ * 鍚屾椂璁╁墠绔彧鍏冲績鈥滄湁娌℃湁涓嬩竴椤碘�濆拰鈥滀笅涓�椤佃甯︿粈涔� cursor鈥濄��</p>
+ */
+@Data
+public class CursorPageResult<T> {
+
+ /** 褰撳墠椤垫暟鎹垪琛ㄣ�� */
+ private List<T> records;
+
+ /** 褰撳墠璇锋眰鏈�缁堢敓鏁堢殑鍒嗛〉澶у皬銆� */
+ private Integer pageSize;
+
+ /**
+ * 涓嬩竴椤佃鎼哄甫鐨勬父鏍囧�笺��
+ *
+ * <p>绾﹀畾鍙栤�滃綋鍓嶉〉鏈�鍚庝竴鏉¤褰曗�濈殑娓告爣瀛楁鍊笺��
+ * 濡傛灉娌℃湁涓嬩竴椤碉紝鍒欒繑鍥� null銆�</p>
+ */
+ private Long nextCursor;
+
+ /** 鏄惁杩樺瓨鍦ㄤ笅涓�椤点�� */
+ private Boolean hasNext;
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderLogController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderLogController.java
index fcf243d..2b8aea5 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderLogController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/AsnOrderLogController.java
@@ -8,11 +8,11 @@
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.utils.ExcelUtil;
import com.vincent.rsf.server.common.annotation.OperationLog;
-import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.CursorPageParam;
import com.vincent.rsf.server.common.domain.KeyValVo;
-import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.entity.AsnOrderLog;
import com.vincent.rsf.server.manager.service.AsnOrderLogService;
+import com.vincent.rsf.server.manager.utils.buildPageRowsUtils;
import com.vincent.rsf.server.system.controller.BaseController;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,15 +25,35 @@
@RestController
public class AsnOrderLogController extends BaseController {
+ private static final int DEFAULT_CURSOR_PAGE_SIZE = 20;
+
@Autowired
private AsnOrderLogService asnOrderLogService;
@PreAuthorize("hasAuthority('manager:asnOrderLog:list')")
@PostMapping("/asnOrderLog/page")
public R page(@RequestBody Map<String, Object> map) {
- BaseParam baseParam = buildParam(map, BaseParam.class);
- PageParam<AsnOrderLog, BaseParam> pageParam = new PageParam<>(baseParam, AsnOrderLog.class);
- return R.ok().add(asnOrderLogService.page(pageParam, pageParam.buildWrapper(true)));
+ // 杩欓噷宸茬粡涓嶅啀鎵嬪啓娓告爣鍒嗛〉缁嗚妭锛岃�屾槸鐩存帴澶嶇敤 BaseController 鐨勯�氱敤瀹炵幇銆�
+ //
+ // 褰撳墠杩欏嚑涓弬鏁板垎鍒〃杈撅細
+ // 1. map锛氬墠绔師濮嬭姹傚弬鏁�
+ // 2. CursorPageParam.class锛氶�氱敤娓告爣鍙傛暟瑙f瀽鍣�
+ // 3. AsnOrderLog.class锛氱敤浜庨�氱敤绛涢�夊拰 condition 妯$硦鎼滅储
+ // 4. asnOrderLogService锛氬疄闄呮墽琛屾煡璇㈢殑 service
+ // 5. "id"锛氭湰鎺ュ彛鐨勬父鏍囧瓧娈碉紝鍥哄畾鎸� id desc 鍋氬垎椤�
+ // 6. DEFAULT_CURSOR_PAGE_SIZE锛氶粯璁ゆ瘡椤靛ぇ灏�
+ // 7. null锛氬綋鍓嶆病鏈夐澶栫殑 where 鏉′欢鎵╁睍
+ // 8. buildPageRowsUtils::userNameMap锛氱粨鏋滃悗澶勭悊锛屾壒閲忚ˉ createBy$/updateBy$
+ return R.ok().add(cursorPage(
+ map,
+ CursorPageParam.class,
+ AsnOrderLog.class,
+ asnOrderLogService,
+ "id",
+ DEFAULT_CURSOR_PAGE_SIZE,
+ null,
+ buildPageRowsUtils::userNameMap
+ ));
}
@PreAuthorize("hasAuthority('manager:asnOrderLog:list')")
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderLog.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderLog.java
index 9389780..406b882 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderLog.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/AsnOrderLog.java
@@ -3,22 +3,19 @@
import java.text.SimpleDateFormat;
import java.util.*;
+import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.vincent.rsf.server.system.constant.DictTypeCode;
import com.vincent.rsf.server.system.entity.DictData;
import com.vincent.rsf.server.system.service.DictDataService;
import org.springframework.format.annotation.DateTimeFormat;
-import com.baomidou.mybatisplus.annotation.TableLogic;
+
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Date;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -141,6 +138,9 @@
@ApiModelProperty(value= "娣诲姞浜哄憳")
private Long createBy;
+ @TableField(exist = false)
+ private String createBy$;
+
/**
* 娣诲姞鏃堕棿
*/
@@ -154,6 +154,9 @@
*/
@ApiModelProperty(value= "淇敼浜哄憳")
private Long updateBy;
+
+ @TableField(exist = false)
+ private String updateBy$;
/**
* 淇敼鏃堕棿
@@ -296,29 +299,11 @@
}
}
- public String getCreateBy$(){
- UserService service = SpringUtils.getBean(UserService.class);
- User user = service.getById(this.createBy);
- if (!Cools.isEmpty(user)){
- return String.valueOf(user.getNickname());
- }
- return null;
- }
-
public String getCreateTime$(){
if (Cools.isEmpty(this.createTime)){
return "";
}
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
- }
-
- public String getUpdateBy$(){
- UserService service = SpringUtils.getBean(UserService.class);
- User user = service.getById(this.updateBy);
- if (!Cools.isEmpty(user)){
- return String.valueOf(user.getNickname());
- }
- return null;
}
public String getUpdateTime$(){
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/AsnOrderMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/AsnOrderMapper.java
index 1b0f90e..731dba0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/AsnOrderMapper.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/AsnOrderMapper.java
@@ -1,14 +1,9 @@
package com.vincent.rsf.server.manager.mapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.vincent.rsf.server.manager.controller.dto.DashboardDto;
import com.vincent.rsf.server.manager.controller.dto.StockTransItemDto;
-import com.vincent.rsf.server.manager.entity.StockStatistic;
import com.vincent.rsf.server.manager.entity.WkOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -17,7 +12,5 @@
@Repository
public interface AsnOrderMapper extends BaseMapper<WkOrder> {
- DashboardDto getDashbord(@Param("type") String type, @Param("taskType") String taskType);
-
- List<StockTransItemDto> getStockTrand(@Param(Constants.WRAPPER) LambdaQueryWrapper<StockStatistic> queryWrapper);
+ List<StockTransItemDto> getStockTrand();
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderPressureSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderPressureSchedules.java
index 2262b15..7d4818e 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderPressureSchedules.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/AsnOrderPressureSchedules.java
@@ -2,11 +2,11 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.manager.entity.AsnOrderItemLog;
+import com.vincent.rsf.server.manager.entity.AsnOrderLog;
import com.vincent.rsf.server.manager.entity.Matnr;
-import com.vincent.rsf.server.manager.entity.WkOrder;
-import com.vincent.rsf.server.manager.entity.WkOrderItem;
-import com.vincent.rsf.server.manager.service.AsnOrderItemService;
-import com.vincent.rsf.server.manager.service.AsnOrderService;
+import com.vincent.rsf.server.manager.service.AsnOrderItemLogService;
+import com.vincent.rsf.server.manager.service.AsnOrderLogService;
import com.vincent.rsf.server.manager.service.MatnrService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -22,7 +22,9 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -41,9 +43,9 @@
private final AtomicBoolean running = new AtomicBoolean(false);
@Autowired
- private AsnOrderService asnOrderService;
+ private AsnOrderLogService asnOrderLogService;
@Autowired
- private AsnOrderItemService asnOrderItemService;
+ private AsnOrderItemLogService asnOrderItemLogService;
@Autowired
private MatnrService matnrService;
@@ -87,23 +89,33 @@
LocalDateTime nowTime = LocalDateTime.now();
double totalQty = itemCountPerOrder * itemQty;
- List<WkOrder> orders = new ArrayList<>(orderCountPerRun);
+ List<AsnOrderLog> orders = new ArrayList<>(orderCountPerRun);
for (int i = 0; i < orderCountPerRun; i++) {
orders.add(buildOrder(now, nowTime, totalQty, i));
}
- if (!asnOrderService.saveBatch(orders, 200)) {
+ if (!asnOrderLogService.saveBatch(orders, 200)) {
throw new CoolException("ASN鍘嬫祴涓诲崟鎻掑叆澶辫触");
}
- List<WkOrderItem> items = new ArrayList<>(orderCountPerRun * itemCountPerOrder);
+ List<AsnOrderLog> persistedOrders = asnOrderLogService.list(new LambdaQueryWrapper<AsnOrderLog>()
+ .in(AsnOrderLog::getCode, extractOrderCodes(orders)));
+ Map<String, AsnOrderLog> orderMap = new HashMap<>(persistedOrders.size());
+ for (AsnOrderLog order : persistedOrders) {
+ orderMap.put(order.getCode(), order);
+ }
+
+ List<AsnOrderItemLog> items = new ArrayList<>(orderCountPerRun * itemCountPerOrder);
for (int orderIndex = 0; orderIndex < orders.size(); orderIndex++) {
- WkOrder order = orders.get(orderIndex);
+ AsnOrderLog order = orderMap.get(orders.get(orderIndex).getCode());
+ if (order == null) {
+ throw new CoolException("ASN鍘嬫祴涓诲崟鍥炴煡澶辫触");
+ }
for (int itemIndex = 0; itemIndex < itemCountPerOrder; itemIndex++) {
Matnr matnr = matnrs.get((orderIndex * itemCountPerOrder + itemIndex) % matnrs.size());
items.add(buildOrderItem(order, matnr, now, orderIndex, itemIndex));
}
}
- if (!asnOrderItemService.saveBatch(items, 500)) {
+ if (!asnOrderItemLogService.saveBatch(items, 500)) {
throw new CoolException("ASN鍘嬫祴鏄庣粏鎻掑叆澶辫触");
}
@@ -126,89 +138,69 @@
.last("limit " + needCount));
}
- private WkOrder buildOrder(Date now, LocalDateTime nowTime, double totalQty, int sequence) {
+ private List<String> extractOrderCodes(List<AsnOrderLog> orders) {
+ List<String> codes = new ArrayList<>(orders.size());
+ for (AsnOrderLog order : orders) {
+ codes.add(order.getCode());
+ }
+ return codes;
+ }
+
+ private AsnOrderLog buildOrder(Date now, LocalDateTime nowTime, double totalQty, int sequence) {
String suffix = String.format("%04d", sequence + 1);
String code = "erp" + nowTime.format(ORDER_CODE_FORMATTER) + suffix;
long serialNo = System.currentTimeMillis() * 1000 + sequence;
- return new WkOrder()
- .setCode(code)
- .setPoCode(code)
- .setPoId(serialNo)
- .setType(ORDER_TYPE)
- .setWkType(ORDER_WORK_TYPE)
- .setAnfme(totalQty)
- .setQty(totalQty)
- .setWorkQty(0.0)
- .setCheckType(0)
- .setRleStatus((short) 0)
- .setNtyStatus(0)
- .setExceStatus((short) 4)
- .setStatus(1)
- .setDeleted(0)
- .setTenantId(TENANT_ID)
- .setCreateBy(USER_ID)
- .setCreateTime(now)
- .setUpdateBy(USER_ID)
- .setUpdateTime(now)
- .setMemo(MEMO)
- .setReportOnce(4)
- .setBusinessTime(now)
- .setStationId("1215")
- .setOrderInternalCode(String.valueOf(serialNo))
- .setStockDirect("stockDirect")
- .setCustomerId("custom1")
- .setCustomerName("瀹㈡埛1")
- .setSupplierId("gongys1")
- .setSupplierName("渚涘簲鍟�1")
- .setStockOrgId("stockYH")
- .setStockOrgName("娴欐睙閾舵箹绠卞寘鏈夐檺鍏徃浠撳簱")
- .setPurchaseOrgId("yhcaigou")
- .setPurchaseOrgName("娴欐睙閾舵箹绠卞寘鏈夐檺鍏徃閲囪喘")
- .setPurchaseUserId("caigouyuan1")
- .setPurchaseUserName("閲囪喘鍛�1")
- .setPrdOrgId("prdYH")
- .setPrdOrgName("娴欐睙閾舵箹绠卞寘鏈夐檺鍏徃")
- .setSaleOrgId("sale1")
- .setSaleOrgName("鐢熶骇缁�1")
- .setSaleUserId("shengchanyuan1")
- .setSaleUserName("鐢熶骇鍛�1")
- .setVersion(0);
+ AsnOrderLog order = new AsnOrderLog();
+ order.setCode(code);
+ order.setPoCode(code);
+ order.setPoId(serialNo);
+ order.setType(ORDER_TYPE);
+ order.setWkType(ORDER_WORK_TYPE);
+ order.setAnfme(totalQty);
+ order.setQty(totalQty);
+ order.setRleStatus((short) 0);
+ order.setNtyStatus((short) 0);
+ order.setExceStatus((short) 4);
+ order.setStatus(1);
+ order.setDeleted(0);
+ order.setTenantId(TENANT_ID);
+ order.setCreateBy(USER_ID);
+ order.setCreateTime(now);
+ order.setUpdateBy(USER_ID);
+ order.setUpdateTime(now);
+ order.setMemo(MEMO);
+ return order;
}
- private WkOrderItem buildOrderItem(WkOrder order, Matnr matnr, Date now, int orderIndex, int itemIndex) {
+ private AsnOrderItemLog buildOrderItem(AsnOrderLog order, Matnr matnr, Date now, int orderIndex, int itemIndex) {
String stockUnit = StringUtils.firstNonBlank(matnr.getStockUnit(), matnr.getPurUnit(), matnr.getUnit(), matnr.getBaseUnit());
String purUnit = StringUtils.firstNonBlank(matnr.getPurUnit(), matnr.getUnit(), matnr.getStockUnit(), matnr.getBaseUnit());
- String baseUnit = StringUtils.firstNonBlank(matnr.getBaseUnit(), matnr.getUnit(), matnr.getStockUnit(), matnr.getPurUnit());
String batchCode = "B" + new SimpleDateFormat("yyyyMMddHHmmss").format(now)
+ String.format("%02d%02d", orderIndex + 1, itemIndex + 1);
String trackCode = "T" + System.currentTimeMillis() + String.format("%02d%02d", orderIndex + 1, itemIndex + 1);
- return new WkOrderItem()
- .setOrderId(order.getId())
- .setOrderCode(order.getCode())
+ return new AsnOrderItemLog()
+ .setLogId(order.getId())
+ .setAsnId(order.getAsnId())
+ .setAsnCode(order.getCode())
.setPlatItemId("M" + (itemIndex + 1))
.setPoCode(order.getPoCode())
.setFieldsIndex(matnr.getFieldsIndex())
.setMatnrId(matnr.getId())
.setMatnrCode(matnr.getCode())
.setMaktx(matnr.getName())
- .setSpec(matnr.getSpec())
- .setModel(matnr.getModel())
.setAnfme(itemQty)
- .setWorkQty(0.0)
.setPurQty(itemQty)
.setQty(itemQty)
.setStockUnit(stockUnit)
.setPurUnit(purUnit)
- .setBatch(batchCode)
.setSplrBatch(batchCode)
.setSplrCode("gongys1")
.setSplrName("渚涘簲鍟�1")
.setTrackCode(trackCode)
.setBarcode(trackCode)
- .setProdTime(new SimpleDateFormat("yyyy-MM-dd").format(now))
- .setNtyStatus(0)
+ .setNtyStatus((short) 0)
.setStatus(1)
.setDeleted(0)
.setTenantId(TENANT_ID)
@@ -216,11 +208,6 @@
.setCreateTime(now)
.setUpdateBy(USER_ID)
.setUpdateTime(now)
- .setMemo(MEMO)
- .setBaseUnit(baseUnit)
- .setUseOrgId(matnr.getUseOrgId())
- .setUseOrgName(matnr.getUseOrgName())
- .setErpClsId(matnr.getErpClsId())
- .setPriceUnitId(baseUnit);
+ .setMemo(MEMO);
}
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
index ab223ec..c74cd30 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/AsnOrderServiceImpl.java
@@ -8,6 +8,7 @@
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.entity.dto.PoItemsDto;
import com.vincent.rsf.server.api.service.ReportMsgService;
+import com.vincent.rsf.server.common.service.RedisService;
import com.vincent.rsf.server.common.utils.DateUtils;
import com.vincent.rsf.server.manager.controller.dto.DashboardDto;
import com.vincent.rsf.server.manager.controller.dto.StockTrandDto;
@@ -17,12 +18,14 @@
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.enums.*;
import com.vincent.rsf.server.manager.mapper.AsnOrderMapper;
+import com.vincent.rsf.server.manager.mapper.TaskLogMapper;
import com.vincent.rsf.server.manager.mapper.TaskMapper;
import com.vincent.rsf.server.manager.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.mapper.SerialRuleMapper;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +33,9 @@
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
@@ -43,8 +49,16 @@
* @return
* @time 2025/3/7 08:02
*/
+@Slf4j
@Service("asnOrderService")
public class AsnOrderServiceImpl extends ServiceImpl<AsnOrderMapper, WkOrder> implements AsnOrderService {
+
+ private static final String DASHBOARD_HEADER_CACHE_FLAG = "DASHBOARD_HEADER";
+ private static final String DASHBOARD_HEADER_CACHE_FRESH_SUFFIX = "FRESH";
+ private static final String DASHBOARD_HEADER_CACHE_STALE_SUFFIX = "STALE";
+ private static final int DASHBOARD_HEADER_CACHE_FRESH_TTL_SECONDS = 300;
+ private static final int DASHBOARD_HEADER_CACHE_STALE_TTL_SECONDS = 86400;
+ private static final DateTimeFormatter DASHBOARD_CACHE_DATE_FORMATTER = DateTimeFormatter.BASIC_ISO_DATE;
@Autowired
private ReportMsgService reportMsgService;
@@ -65,6 +79,10 @@
private PurchaseItemService purchaseItemService;
@Autowired
private TaskMapper taskMapper;
+ @Autowired
+ private TaskLogMapper taskLogMapper;
+ @Autowired
+ private RedisService redisService;
@Override
public boolean notifyInspect(List<WkOrder> orders) {
@@ -430,21 +448,29 @@
*/
@Override
public R getDashbord() {
- DashboardDto dto = new DashboardDto();
- //鑾峰彇鍏ュ簱鏁伴噺
- DashboardDto trandDto = this.baseMapper.getDashbord(OrderType.ORDER_IN.type, TaskType.TASK_TYPE_IN.type + "");
- dto.setInAnf(trandDto.getAnfme()).setTaskIn(trandDto.getRealAnfme()).setTotalIn(trandDto.getAnfme() + trandDto.getRealAnfme());
-
- //鑾峰彇鍑哄簱鍗曟暟閲�
- DashboardDto outTrand = this.baseMapper.getDashbord(OrderType.ORDER_OUT.type, TaskType.TASK_TYPE_OUT.type + "");
- dto.setOutAnf(outTrand.getAnfme()).setTaskOut(outTrand.getRealAnfme()).setTotalOut(outTrand.getAnfme() + outTrand.getRealAnfme());
-
- //鑾峰彇鎵ц涓换鍔℃暟閲�
- List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<>());
- if (!tasks.isEmpty()) {
- dto.setTaskQty(tasks.size());
+ String freshCacheKey = buildDashboardCacheKey(DASHBOARD_HEADER_CACHE_FRESH_SUFFIX);
+ DashboardDto freshSnapshot = getDashboardCache(freshCacheKey);
+ if (freshSnapshot != null) {
+ return R.ok().add(freshSnapshot);
}
- return R.ok().add(dto);
+ String staleCacheKey = buildDashboardCacheKey(DASHBOARD_HEADER_CACHE_STALE_SUFFIX);
+ Exception dbException = null;
+ try {
+ DashboardDto snapshot = buildDashboardSnapshot();
+ cacheDashboard(freshCacheKey, snapshot, DASHBOARD_HEADER_CACHE_FRESH_TTL_SECONDS);
+ cacheDashboard(staleCacheKey, snapshot, DASHBOARD_HEADER_CACHE_STALE_TTL_SECONDS);
+ return R.ok().add(snapshot);
+ } catch (Exception ex) {
+ dbException = ex;
+ log.warn("Load dashboard snapshot from database failed, fallback to stale cache. message={}", ex.getMessage(), ex);
+ }
+
+ DashboardDto staleSnapshot = getDashboardCache(staleCacheKey);
+ if (staleSnapshot != null) {
+ return R.ok().add(staleSnapshot);
+ }
+ log.error("Load dashboard snapshot failed, returning empty snapshot.", dbException);
+ return R.ok().add(emptyDashboardSnapshot());
}
/**
@@ -454,9 +480,7 @@
@Override
public R getStockTrand() {
List<String> days = DateUtils.getLastMonthDays("yyyy-MM-dd");
- LambdaQueryWrapper<StockStatistic> queryWrapper = new LambdaQueryWrapper<StockStatistic>()
- .in(StockStatistic::getTaskType, Arrays.asList(TaskType.TASK_TYPE_IN.type, TaskType.TASK_TYPE_OUT.type));
- List<StockTransItemDto> items = this.baseMapper.getStockTrand(queryWrapper);
+ List<StockTransItemDto> items = this.baseMapper.getStockTrand();
if (items.isEmpty()) {
return R.ok();
}
@@ -542,4 +566,86 @@
throw new CoolException("鍘熷崟鎹垹闄ゅけ璐ワ紒锛�");
}
}
+
+ private DashboardDto buildDashboardSnapshot() {
+ Date[] todayRange = buildTodayRange();
+ Date todayStart = todayRange[0];
+ Date tomorrowStart = todayRange[1];
+
+ int inAnf = safeToInt(this.count(new LambdaQueryWrapper<WkOrder>()
+ .eq(WkOrder::getType, OrderType.ORDER_IN.type)
+ .ge(WkOrder::getCreateTime, todayStart)
+ .lt(WkOrder::getCreateTime, tomorrowStart)));
+ int outAnf = safeToInt(this.count(new LambdaQueryWrapper<WkOrder>()
+ .eq(WkOrder::getType, OrderType.ORDER_OUT.type)
+ .ge(WkOrder::getCreateTime, todayStart)
+ .lt(WkOrder::getCreateTime, tomorrowStart)));
+ int taskIn = safeToInt(taskLogMapper.selectCount(new LambdaQueryWrapper<TaskLog>()
+ .eq(TaskLog::getTaskType, TaskType.TASK_TYPE_IN.type)
+ .ge(TaskLog::getCreateTime, todayStart)
+ .lt(TaskLog::getCreateTime, tomorrowStart)));
+ int taskOut = safeToInt(taskLogMapper.selectCount(new LambdaQueryWrapper<TaskLog>()
+ .eq(TaskLog::getTaskType, TaskType.TASK_TYPE_OUT.type)
+ .ge(TaskLog::getCreateTime, todayStart)
+ .lt(TaskLog::getCreateTime, tomorrowStart)));
+ int taskQty = safeToInt(taskMapper.selectCount(new LambdaQueryWrapper<Task>()));
+
+ return new DashboardDto()
+ .setInAnf(inAnf)
+ .setOutAnf(outAnf)
+ .setTaskIn(taskIn)
+ .setTaskOut(taskOut)
+ .setTaskQty(taskQty)
+ .setTotalIn(inAnf + taskIn)
+ .setTotalOut(outAnf + taskOut);
+ }
+
+ private DashboardDto getDashboardCache(String cacheKey) {
+ try {
+ String cacheValue = redisService.getValue(DASHBOARD_HEADER_CACHE_FLAG, cacheKey);
+ if (StringUtils.isBlank(cacheValue)) {
+ return null;
+ }
+ return JSONObject.parseObject(cacheValue, DashboardDto.class);
+ } catch (Exception ex) {
+ log.warn("Read dashboard cache failed, key={}, message={}", cacheKey, ex.getMessage(), ex);
+ return null;
+ }
+ }
+
+ private void cacheDashboard(String cacheKey, DashboardDto dto, int ttlSeconds) {
+ try {
+ redisService.setValue(DASHBOARD_HEADER_CACHE_FLAG, cacheKey, JSONObject.toJSONString(dto), ttlSeconds);
+ } catch (Exception ex) {
+ log.warn("Write dashboard cache failed, key={}, message={}", cacheKey, ex.getMessage(), ex);
+ }
+ }
+
+ private String buildDashboardCacheKey(String suffix) {
+ String dateBucket = LocalDate.now().format(DASHBOARD_CACHE_DATE_FORMATTER);
+ return dateBucket + "." + suffix;
+ }
+
+ private Date[] buildTodayRange() {
+ ZoneId zoneId = ZoneId.systemDefault();
+ LocalDate today = LocalDate.now(zoneId);
+ Date todayStart = Date.from(today.atStartOfDay(zoneId).toInstant());
+ Date tomorrowStart = Date.from(today.plusDays(1).atStartOfDay(zoneId).toInstant());
+ return new Date[]{todayStart, tomorrowStart};
+ }
+
+ private DashboardDto emptyDashboardSnapshot() {
+ return new DashboardDto()
+ .setInAnf(0)
+ .setOutAnf(0)
+ .setTaskIn(0)
+ .setTaskOut(0)
+ .setTaskQty(0)
+ .setTotalIn(0)
+ .setTotalOut(0);
+ }
+
+ private int safeToInt(Long count) {
+ return count == null ? 0 : count.intValue();
+ }
}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java
index abd9cef..1511caf 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/BaseController.java
@@ -1,16 +1,27 @@
package com.vincent.rsf.server.system.controller;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.common.utils.Utils;
import com.vincent.rsf.framework.common.Cools;
import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.CursorPageParam;
+import com.vincent.rsf.server.common.domain.CursorPageResult;
+import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.system.entity.User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* Created by vincent on 1/30/2024
@@ -105,5 +116,189 @@
return true;
}
+ /**
+ * 閫氱敤娓告爣鍒嗛〉瀹炵幇銆�
+ *
+ * <p>杩欎釜鏂规硶鐨勭洰鏍囦笉鏄浛浠f墍鏈夊垎椤碉紝鑰屾槸鎶娾�滃崟瀛楁銆佸�掑簭銆佸悜鍚庣炕椤碘�濈殑娓告爣鍒嗛〉
+ * 鏀舵暃鎴愪竴濂楃粺涓�瀹炵幇锛岄伩鍏嶅悇涓� controller 閲嶅鍐欎笅闈㈣繖浜涙牱鏉块�昏緫锛�</p>
+ * <ul>
+ * <li>buildParam</li>
+ * <li>蹇界暐鍓嶇浼犲叆鐨� orderBy</li>
+ * <li>buildWrapper(true) 鏋勫缓閫氱敤绛涢��</li>
+ * <li>cursor 鏉′欢</li>
+ * <li>鎸夊浐瀹氬瓧娈靛�掑簭</li>
+ * <li>澶氭煡涓�鏉″垽鏂� hasNext</li>
+ * <li>鎴柇缁撴灉骞剁敓鎴� nextCursor</li>
+ * </ul>
+ *
+ * <p>閫傜敤鍓嶆彁锛�</p>
+ * <ul>
+ * <li>娓告爣瀛楁鏄崟涓�瀛楁</li>
+ * <li>娓告爣瀛楁鐨勫�肩ǔ瀹氥�佸彲姣旇緝锛屽苟涓旇兘鏄犲皠鎴� Long</li>
+ * <li>鍒嗛〉鏂瑰悜鍥哄畾涓衡�滄寜璇ュ瓧娈靛�掑簭锛屽悜鏇村皬鐨勫�肩炕椤碘��</li>
+ * </ul>
+ *
+ * <p>鍙傛暟璇存槑锛�</p>
+ * <ul>
+ * <li>{@code map}锛氬師濮嬭姹傚弬鏁�</li>
+ * <li>{@code paramClass}锛氭父鏍囧弬鏁扮被鍨嬶紝閫氬父浼� {@link CursorPageParam}</li>
+ * <li>{@code entityClass}锛氬疄浣撶被锛岀敤浜� PageParam 鏉′欢鏋勫缓鍜� condition 妯$硦鏌ヨ</li>
+ * <li>{@code service}锛歁yBatis-Plus 鐨� IService锛岃礋璐f墽琛� page 鏌ヨ</li>
+ * <li>{@code cursorField}锛氬疄浣撳瓧娈靛悕锛屼笉鏄暟鎹簱鍒楀悕锛屼緥濡備紶 {@code id}</li>
+ * <li>{@code defaultPageSize}锛氬綋鍓嶆帴鍙g殑榛樿鍒嗛〉澶у皬</li>
+ * <li>{@code wrapperConsumer}锛氬彲閫夌殑棰濆 where 鏉′欢鎵╁睍閽╁瓙</li>
+ * <li>{@code recordsConsumer}锛氬彲閫夌殑缁撴灉鍚庡鐞嗛挬瀛愶紝渚嬪琛ュ厖 createBy$/updateBy$</li>
+ * </ul>
+ */
+ protected <T, U extends CursorPageParam> CursorPageResult<T> cursorPage(
+ Map<String, Object> map,
+ Class<U> paramClass,
+ Class<T> entityClass,
+ IService<T> service,
+ String cursorField,
+ int defaultPageSize,
+ Consumer<QueryWrapper<T>> wrapperConsumer,
+ Consumer<List<T>> recordsConsumer
+ ) {
+ // 鍏佽 controller 浼� null锛屽唴閮ㄧ粺涓�鍏滃簳鎴愮┖ map锛�
+ // 杩欐牱 buildParam 涓嶉渶瑕佹瘡涓皟鐢ㄦ柟鑷繁鍏堝垽绌恒��
+ U baseParam = buildParam(map == null ? new HashMap<>() : map, paramClass);
+
+ // 娓告爣鍒嗛〉涓嶅厑璁稿鎴风鑷畾涔夋帓搴忥紝
+ // 鍚﹀垯鈥滀笂涓�椤垫渶鍚庝竴鏉′綔涓轰笅涓�椤垫父鏍団�濈殑鍓嶆彁浼氳鐮村潖銆�
+ baseParam.setOrderBy(null);
+
+ // pageSize 鍏佽浠庤姹傞噷甯﹀叆锛屼絾闈炴硶鍊硷紙null銆�0銆佽礋鏁帮級缁熶竴鍥為��鍒版帴鍙i粯璁ゅ�笺��
+ int pageSize = resolveCursorPageSize(baseParam.getPageSize(), defaultPageSize);
+
+ // controller 浼犵殑鏄疄浣撳瓧娈靛悕锛屼緥濡� "id" / "poId"锛�
+ // 杩欓噷缁熶竴杞垚鏁版嵁搴撳垪鍚嶅苟琛ュ弽寮曞彿锛岄伩鍏嶆瘡涓笟鍔¤嚜宸辨墜鍐� SQL 鐗囨銆�
+ String cursorColumn = resolveCursorColumn(cursorField);
+
+ // 鍏堝鐢ㄧ郴缁熺幇鏈夌殑 PageParam + buildWrapper(true) 鏈哄埗锛�
+ // 淇濈暀鍘熸潵鐨勬潯浠惰В鏋愩�佹椂闂磋寖鍥淬�乧ondition 妯$硦鎼滅储绛夎兘鍔涖��
+ PageParam<T, U> pageParam = new PageParam<>(baseParam, entityClass);
+ QueryWrapper<T> wrapper = pageParam.buildWrapper(true);
+
+ // 缁欎笟鍔¢鐣欓澶� where 鏉′欢鐨勬墿灞曠偣锛�
+ // 濡傛灉鏌愪釜鎺ュ彛闄や簡閫氱敤绛涢�夊锛岃繕瑕佹嫾鎺ラ澶栭檺鍒讹紝鍙互鍦ㄨ繖閲岃ˉ銆�
+ if (wrapperConsumer != null) {
+ wrapperConsumer.accept(wrapper);
+ }
+
+ // 娓告爣鍒嗛〉鐨勬牳蹇冩潯浠讹細
+ // 褰撳墠绾﹀畾鏄�滄寜 cursorField 鍊掑簭鏌ョ湅鏇存棫鐨勬暟鎹�濓紝鎵�浠ユ潯浠跺浐瀹氫负 < cursor銆�
+ if (baseParam.getCursor() != null) {
+ wrapper.lt(cursorColumn, baseParam.getCursor());
+ }
+
+ // 寮哄埗鎸夋父鏍囧瓧娈靛�掑簭鎺掑簭锛屼繚璇佹瘡涓�椤电殑鏁版嵁椤哄簭绋冲畾銆�
+ wrapper.orderByDesc(cursorColumn);
+
+ // 澶氭煡涓�鏉℃槸娓告爣鍒嗛〉鍒ゆ柇 hasNext 鐨勫父瑙佸仛娉曪細
+ // 瀹為檯瑕� 20 鏉★紝灏辨煡 21 鏉★紱澶氬嚭鏉ラ偅涓�鏉″彧鐢ㄦ潵鍒ゆ柇鏄惁杩樻湁涓嬩竴椤点��
+ Page<T> queryPage = new Page<>(1L, pageSize + 1L, false);
+ List<T> records = service.page(queryPage, wrapper).getRecords();
+ List<T> pageRecords = Cools.isEmpty(records) ? new ArrayList<>() : new ArrayList<>(records);
+
+ // 濡傛灉鏌ュ嚭鏉ョ殑鏁伴噺澶т簬 pageSize锛岃鏄庤嚦灏戣繕鏈変笅涓�椤点��
+ boolean hasNext = pageRecords.size() > pageSize;
+ if (hasNext) {
+ // 鍙妸鐪熸闇�瑕佽繑鍥炵粰鍓嶇鐨� pageSize 鏉℃暟鎹暀鍦ㄥ綋鍓嶉〉銆�
+ pageRecords = new ArrayList<>(pageRecords.subList(0, pageSize));
+ }
+
+ // 缁欎笟鍔′晶涓�涓�滅粨鏋滃嚭搴撳墠澶勭悊鈥濈殑鏈轰細銆�
+ // 鍏稿瀷鍦烘櫙鏄壒閲忚ˉ鍏呯敤鎴峰悕銆佸瓧鍏告枃鏈�佺紦瀛樺瓧娈电瓑锛�
+ // 杩欐牱鍏叡鍒嗛〉閫昏緫涓嶅叧蹇冧笟鍔$粏鑺傦紝浣嗕笟鍔′篃涓嶉渶瑕佸洖鍒� controller 鑷繁閲嶅啓鍒嗛〉銆�
+ if (recordsConsumer != null && !Cools.isEmpty(pageRecords)) {
+ recordsConsumer.accept(pageRecords);
+ }
+
+ CursorPageResult<T> result = new CursorPageResult<>();
+ result.setRecords(pageRecords);
+ result.setPageSize(pageSize);
+ result.setHasNext(hasNext);
+ // nextCursor 鍙湁鍦ㄨ繕鏈変笅涓�椤垫椂鎵嶆湁鎰忎箟锛�
+ // 绾﹀畾鍙栤�滃綋鍓嶉〉鏈�鍚庝竴鏉¤褰曗�濈殑娓告爣瀛楁鍊笺��
+ result.setNextCursor(hasNext ? extractCursorValue(pageRecords, cursorField) : null);
+ return result;
+ }
+
+ /**
+ * 缁熶竴瑙f瀽褰撳墠鎺ュ彛瀹為檯浣跨敤鐨� pageSize銆�
+ *
+ * <p>鍙鍓嶇娌′紶銆佷紶浜� 0銆佹垨鑰呬紶浜嗚礋鏁帮紝灏卞洖閫�鍒� controller 浼犲叆鐨勯粯璁ゅ�笺��</p>
+ */
+ private int resolveCursorPageSize(Integer pageSize, int defaultPageSize) {
+ if (pageSize == null || pageSize <= 0) {
+ return defaultPageSize;
+ }
+ return pageSize;
+ }
+
+ /**
+ * 鎶婂疄浣撳瓧娈靛悕杞崲鎴愭暟鎹簱鍒楀悕銆�
+ *
+ * <p>渚嬪锛�</p>
+ * <ul>
+ * <li>{@code id -> `id`}</li>
+ * <li>{@code poId -> `po_id`}</li>
+ * </ul>
+ *
+ * <p>杩欐牱 controller 璋冪敤鏃跺彧闇�瑕佸叧蹇� Java 瀛楁鍚嶏紝涓嶉渶瑕佽嚜宸辨嫾 SQL銆�</p>
+ */
+ private String resolveCursorColumn(String cursorField) {
+ return "`" + Utils.toSymbolCase(cursorField, '_') + "`";
+ }
+
+ /**
+ * 浠庡綋鍓嶉〉鏈�鍚庝竴鏉¤褰曚腑鎻愬彇 nextCursor銆�
+ *
+ * <p>杩欓噷浣跨敤鍙嶅皠鑰屼笉鏄澶栧畾涔夋帴鍙o紝鐩殑鏄檷浣庢帴鍏ユ垚鏈細
+ * 鍙瀹炰綋閲屽瓨鍦ㄥ悓鍚嶅瓧娈碉紝灏辫兘鐩存帴澶嶇敤閫氱敤鏂规硶銆�</p>
+ *
+ * <p>鏀寔鐨勫瓧娈靛�肩被鍨嬶細</p>
+ * <ul>
+ * <li>{@link Long}</li>
+ * <li>鍏朵粬 {@link Number}</li>
+ * <li>鍙浆鎴� Long 鐨勫瓧绗︿覆</li>
+ * </ul>
+ *
+ * <p>濡傛灉瀛楁涓嶅瓨鍦ㄣ�佷负绌恒�佹垨鏃犳硶杞垚 Long锛屽垯杩斿洖 null銆�</p>
+ */
+ private <T> Long extractCursorValue(List<T> records, String cursorField) {
+ if (Cools.isEmpty(records)) {
+ return null;
+ }
+ T lastRecord = records.get(records.size() - 1);
+ if (lastRecord == null || Cools.isEmpty(cursorField)) {
+ return null;
+ }
+ Field field = Cools.getField(lastRecord.getClass(), cursorField);
+ if (field == null) {
+ return null;
+ }
+ boolean accessible = field.isAccessible();
+ try {
+ field.setAccessible(true);
+ Object value = field.get(lastRecord);
+ if (value instanceof Long) {
+ return (Long) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).longValue();
+ }
+ if (value instanceof String && !((String) value).trim().isEmpty()) {
+ return Long.parseLong(((String) value).trim());
+ }
+ } catch (IllegalAccessException | NumberFormatException ignored) {
+ return null;
+ } finally {
+ field.setAccessible(accessible);
+ }
+ return null;
+ }
+
}
diff --git a/rsf-server/src/main/resources/mapper/manager/AsnOrderMapper.xml b/rsf-server/src/main/resources/mapper/manager/AsnOrderMapper.xml
index 01399ca..24ded44 100644
--- a/rsf-server/src/main/resources/mapper/manager/AsnOrderMapper.xml
+++ b/rsf-server/src/main/resources/mapper/manager/AsnOrderMapper.xml
@@ -1,17 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vincent.rsf.server.manager.mapper.AsnOrderMapper">
- <select id="getDashbord" resultType="com.vincent.rsf.server.manager.controller.dto.DashboardDto">
- SELECT
- ( SELECT COUNT( 1 ) FROM man_asn_order WHERE DATE(create_time) = CURRENT_DATE() AND `type` = #{type} ) AS anfme,
- COUNT( id ) AS real_anfme
- FROM
- man_task_log
- WHERE
- DATE(create_time) = CURRENT_DATE()
- AND task_type = #{taskType}
- </select>
-
<select id="getStockTrand" resultType="com.vincent.rsf.server.manager.controller.dto.StockTransItemDto">
SELECT * FROM
(
@@ -26,11 +15,12 @@
FROM
view_stock_statistic
WHERE
+ task_type IN (1, 101)
+ AND
`day_time` BETWEEN ( CURDATE() - INTERVAL 1 MONTH )
AND CURDATE()
GROUP BY
`day_time`, task_type,id
) t
- ${ew.customSqlSegment}
</select>
</mapper>
--
Gitblit v1.9.1