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);