From 7cdc0bc3a1783c172be11a15331fe8061aac8ef0 Mon Sep 17 00:00:00 2001 From: yueli Date: Fri, 4 Sep 2026 10:51:49 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=BA=93=E4=BD=8D=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=99=A8=E6=94=B9=E4=B8=BA=E6=8C=89=E9=9C=80=E6=87=92=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E2=80=94=E2=80=94=E6=96=B0=E5=A2=9E=20/warehouse/chil?= =?UTF-8?q?dren=20=E6=8E=A5=E5=8F=A3=EF=BC=8CWarehouseSelector=20=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=85=A8=E9=87=8F=E6=A0=91=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory-backend/app/api/v1/warehouse.py | 35 ++++ inventory-web/src/api/common/warehouse.ts | 9 + .../src/components/WarehouseSelector.vue | 155 +++++++++--------- inventory-web/src/views/stock/inbound/buy.vue | 21 +-- .../src/views/stock/inbound/product.vue | 22 +-- .../src/views/stock/inbound/semi.vue | 21 +-- 6 files changed, 124 insertions(+), 139 deletions(-) diff --git a/inventory-backend/app/api/v1/warehouse.py b/inventory-backend/app/api/v1/warehouse.py index f002e2e..6b7a351 100644 --- a/inventory-backend/app/api/v1/warehouse.py +++ b/inventory-backend/app/api/v1/warehouse.py @@ -54,6 +54,41 @@ def get_tree(): }), 500 +@warehouse_bp.route('/children', methods=['GET']) +def get_children(): + """ + 懒加载:获取指定库位的直接子节点(parent_id 省略/为空 = 顶层)。 + 每个节点附带 has_children 标记,前端据此渲染「进入下级」而非点进去才知道。 + 与 /tree 行为一致(不额外过滤 is_enabled、按 name 升序)。 + """ + try: + parent_id = request.args.get('parent_id', type=int) + if parent_id is None: + nodes = SysWarehouseLocation.query.filter( + SysWarehouseLocation.parent_id.is_(None) + ).order_by(SysWarehouseLocation.name.asc()).all() + else: + nodes = SysWarehouseLocation.query.filter( + SysWarehouseLocation.parent_id == parent_id + ).order_by(SysWarehouseLocation.name.asc()).all() + + # 一次查询所有"有子节点"的 parent_id,用于 has_children 判断(避免 N+1) + parent_with_children = set( + cid for (cid,) in db.session.query(SysWarehouseLocation.parent_id) + .filter(SysWarehouseLocation.parent_id.isnot(None)).distinct().all() + ) + + data = [] + for node in nodes: + d = node.to_dict() + d['has_children'] = node.id in parent_with_children + data.append(d) + + return jsonify({'code': 200, 'msg': 'success', 'data': data}) + except Exception as e: + return jsonify({'code': 500, 'msg': str(e), 'data': None}), 500 + + @warehouse_bp.route('', methods=['POST']) @jwt_required() @audit_log( diff --git a/inventory-web/src/api/common/warehouse.ts b/inventory-web/src/api/common/warehouse.ts index 955b7da..c3685bc 100644 --- a/inventory-web/src/api/common/warehouse.ts +++ b/inventory-web/src/api/common/warehouse.ts @@ -8,6 +8,15 @@ export function getWarehouseTree() { }) } +// 懒加载:获取指定库位的直接子节点(parentId 省略/为空 = 顶层) +export function getWarehouseChildren(parentId?: number | null) { + return request({ + url: '/v1/warehouse/children', + method: 'get', + params: parentId != null ? { parent_id: parentId } : {} + }) +} + // 创建库位 export function createWarehouse(data: any) { return request({ diff --git a/inventory-web/src/components/WarehouseSelector.vue b/inventory-web/src/components/WarehouseSelector.vue index 4e3f9f2..ced5383 100644 --- a/inventory-web/src/components/WarehouseSelector.vue +++ b/inventory-web/src/components/WarehouseSelector.vue @@ -69,18 +69,18 @@
{{ item.name }} - +
- + 末级 diff --git a/inventory-web/src/views/stock/inbound/product.vue b/inventory-web/src/views/stock/inbound/product.vue index 611106c..d8c72ea 100644 --- a/inventory-web/src/views/stock/inbound/product.vue +++ b/inventory-web/src/views/stock/inbound/product.vue @@ -354,10 +354,7 @@ - + @@ -620,7 +617,6 @@ import WarehouseSelector from '@/components/WarehouseSelector.vue' import SmartScannerDialog from '@/components/SmartScannerDialog.vue' import TrackScanDialog from '@/components/TrackScanDialog.vue' import { getLabelPreview, executePrint } from '@/api/common/print' -import { getWarehouseTree } from '@/api/common/warehouse' import { usePasteUpload } from '@/hooks/usePasteUpload' import { useUserStore } from '@/stores/user' @@ -759,9 +755,6 @@ const scannerDialogVisible = ref(false) // 顶部扫码入库面板 (Track 身份证自动填充物料+序列号+订单号) const trackScanVisible = ref(false) -// 库位级联选择器数据 -const warehouseOptions = ref([]) - // ================= 第一步:声明基础数据 ================= // [核心优化] 所有列定义 @@ -1208,18 +1201,6 @@ const buildCategoryTree = (categories: string[]) => { return root; }; -// 加载库位树数据 -const loadWarehouseTree = async () => { - try { - const res = await getWarehouseTree() - if (res.code === 200) { - warehouseOptions.value = res.data || [] - } - } catch (e) { - console.error('加载库位树失败', e) - } -} - const resetQuery = () => { queryParams.keyword = '' queryParams.searchField = 'all' @@ -1532,7 +1513,6 @@ onMounted(() => { initColumnPermissions() fetchData() fetchOptions() - loadWarehouseTree() }) // 成本计算监听 diff --git a/inventory-web/src/views/stock/inbound/semi.vue b/inventory-web/src/views/stock/inbound/semi.vue index 4bc46e3..44469d8 100644 --- a/inventory-web/src/views/stock/inbound/semi.vue +++ b/inventory-web/src/views/stock/inbound/semi.vue @@ -393,10 +393,7 @@ - + @@ -664,7 +661,6 @@ import WarehouseSelector from '@/components/WarehouseSelector.vue' import SmartScannerDialog from '@/components/SmartScannerDialog.vue' import TrackScanDialog from '@/components/TrackScanDialog.vue' import {getLabelPreview, executePrint} from '@/api/common/print' -import { getWarehouseTree } from '@/api/common/warehouse' import { usePasteUpload } from '@/hooks/usePasteUpload' import { useUserStore } from '@/stores/user' @@ -826,9 +822,6 @@ const scannerDialogVisible = ref(false) // 顶部扫码入库面板 (Track 身份证自动填充物料+序列号) const trackScanVisible = ref(false) -// 库位级联选择器数据 -const warehouseOptions = ref([]) - const entryMode = ref('batch') const modeLocked = ref(false) @@ -1312,17 +1305,6 @@ const buildCategoryTree = (categories: string[]) => { return root; }; -// 加载库位树数据 -const loadWarehouseTree = async () => { - try { - const res = await getWarehouseTree() - if (res.code === 200) { - warehouseOptions.value = res.data || [] - } - } catch (e) { - console.error('加载库位树失败', e) - } -} const resetQuery = () => { queryParams.keyword = '' @@ -1649,7 +1631,6 @@ onMounted(() => { initColumnPermissions() fetchData() fetchOptions() - loadWarehouseTree() })