diff --git a/inventory-backend/app/api/v1/inbound/base.py b/inventory-backend/app/api/v1/inbound/base.py index 2cefcba..81cbf08 100644 --- a/inventory-backend/app/api/v1/inbound/base.py +++ b/inventory-backend/app/api/v1/inbound/base.py @@ -98,6 +98,24 @@ def search_base(): return jsonify({"code": 500, "msg": str(e)}), 500 +# ============================================================================== +# 1.1 计量单位字典接口 (GET /api/v1/inbound/base/units) +# ============================================================================== +@inbound_base_bp.route('/units', methods=['GET']) +@permission_required('material_list') +def get_unit_dict(): + """ + 获取所有已存在的非空计量单位(去重 + 排序),用于前端 + 新增/编辑弹窗中"计量单位"下拉框的历史记录。 + """ + try: + units = MaterialBaseService.get_distinct_units() + return jsonify({"code": 200, "msg": "success", "data": units}) + except Exception as e: + traceback.print_exc() + return jsonify({"code": 500, "msg": str(e)}), 500 + + # ============================================================================== # 2. 列表接口 (GET /api/v1/inbound/base/list) # ============================================================================== diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index f6086ec..c3e28f0 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -528,6 +528,29 @@ class MaterialBaseService: traceback.print_exc() return {"categories": [], "types": [], "companies": []} + @staticmethod + def get_distinct_units(): + """ + 获取所有已存在且非空的计量单位(去重 + 排序)。 + 用于前端"基础信息"新增/编辑弹窗的"计量单位"下拉历史记录。 + + SQL 语义: + SELECT DISTINCT unit FROM material_base + WHERE unit IS NOT NULL AND unit != '' + ORDER BY unit ASC + """ + try: + rows = db.session.query(MaterialBase.unit) \ + .filter(MaterialBase.unit.isnot(None), MaterialBase.unit != '') \ + .distinct() \ + .all() + sorted_units = sorted([u[0] for u in rows if u[0]]) + return sorted_units + except Exception as e: + traceback.print_exc() + print(f"查询计量单位字典失败: {e}") + return [] + @staticmethod def create_material(data): """新增基础信息""" diff --git a/inventory-web/src/api/material_base.ts b/inventory-web/src/api/material_base.ts index b74d1c7..c5c816e 100644 --- a/inventory-web/src/api/material_base.ts +++ b/inventory-web/src/api/material_base.ts @@ -86,4 +86,12 @@ export function markWarningOrdered(data: { baseId: number; isOrdered: boolean }) method: 'post', data }) +} + +// 9. 获取计量单位字典 (新增/编辑弹窗下拉历史) +export function getMaterialUnitsAPI() { + return request({ + url: '/inbound/base/units', + method: 'get' + }) } \ No newline at end of file diff --git a/inventory-web/src/views/material/list.vue b/inventory-web/src/views/material/list.vue index 82a2b2f..546d5ce 100644 --- a/inventory-web/src/views/material/list.vue +++ b/inventory-web/src/views/material/list.vue @@ -409,6 +409,20 @@ + + + + + + + +
- -
-
-
- - - - - - - - - - @@ -457,13 +451,26 @@ - + + + - - - (0低-9高) + + @@ -669,7 +676,8 @@ import { exportAssetStatistics, batchSetWarning, batchSetInspection, - markWarningOrdered + markWarningOrdered, + getMaterialUnitsAPI } from '@/api/material_base'; import { uploadFile, deleteFile } from '@/api/common/upload'; import { usePasteUpload } from '@/hooks/usePasteUpload'; @@ -1003,6 +1011,7 @@ const hasFieldPermission = (field: string) => { const companyOptions = ref([]); const categoryOptions = ref([]); const typeOptions = ref([]); +const unitOptions = ref([]); const categoryTreeOptions = ref([]); // 用于搜索栏级联选择器的数据绑定中转 @@ -1018,10 +1027,25 @@ const searchCategoryPath = computed({ // 类别级联选择器的 ref const categoryCascaderRef = ref(null); -// 选中类别后自动收起下拉面板 +// 选中类别后:1) 收起下拉面板;2) 自动提取末级 Label 末尾的英文字母填入规格型号 const onCategoryChange = () => { - if (categoryCascaderRef.value) { - categoryCascaderRef.value.togglePopperVisible(false); + if (!categoryCascaderRef.value) return; + + // 1) 收起下拉 + categoryCascaderRef.value.togglePopperVisible(false); + + // 2) 从末级节点 Label 提取英文字母后缀 (例如 "电子半成品HH" -> "HH"),写入规格型号 + // 仅在 @change 触发时赋一次值,用户可继续手动修改;未匹配到则保持原值 + try { + const nodes = categoryCascaderRef.value.getCheckedNodes?.() || []; + const node = nodes[0]; + const label: string = (node && node.label) || ''; + const match = label.match(/[a-zA-Z]+$/); + if (match) { + form.value.spec = match[0]; + } + } catch (e) { + console.error('提取类别英文后缀失败', e); } }; @@ -1127,6 +1151,17 @@ const getOptionsList = () => { }); }; +// 获取计量单位字典(新增/编辑弹窗下拉历史) +const fetchUnitList = () => { + getMaterialUnitsAPI().then((res: any) => { + if (res.code === 200) { + unitOptions.value = res.data || []; + } + }).catch(err => { + console.error("获取计量单位字典失败", err); + }); +}; + const querySearchCompany = (queryString: string, cb: any) => { const results = queryString ? companyOptions.value.filter(item => item.toLowerCase().includes(queryString.toLowerCase())) @@ -1834,6 +1869,7 @@ onMounted(() => { getList(); } getOptionsList(); + fetchUnitList(); // 2. 修复弹窗锁定逻辑 console.log('--- 准备检测外部跳转参数 ---', route.query);