feat: 优化库位树UI层级颜色,并将入库页面库位输入升级为级联选择器

This commit is contained in:
DXC
2026-03-06 14:52:47 +08:00
parent 359b8a8345
commit 7201b658fb
7 changed files with 341 additions and 20 deletions

View File

@ -0,0 +1,35 @@
import request from '@/utils/request'
// 获取库位树形结构
export function getWarehouseTree() {
return request({
url: '/v1/warehouse/tree',
method: 'get'
})
}
// 创建库位
export function createWarehouse(data: any) {
return request({
url: '/v1/warehouse',
method: 'post',
data
})
}
// 更新库位
export function updateWarehouse(data: any) {
return request({
url: `/v1/warehouse/${data.id}`,
method: 'put',
data
})
}
// 删除库位
export function deleteWarehouse(id: number) {
return request({
url: `/v1/warehouse/${id}`,
method: 'delete'
})
}

View File

@ -84,13 +84,31 @@
<div class="tree-node">
<span class="node-label">{{ node.label }}</span>
<span class="node-actions">
<el-button type="primary" link size="small" @click="handleAddChild(data)" :icon="Plus">
<el-button
:type="getLevelButtonType(node.level, 'add')"
link
size="small"
@click="handleAddChild(data)"
:icon="Plus"
>
新增下级
</el-button>
<el-button type="warning" link size="small" @click="handleEdit(data)" :icon="Edit">
<el-button
:type="getLevelButtonType(node.level, 'edit')"
link
size="small"
@click="handleEdit(data)"
:icon="Edit"
>
编辑
</el-button>
<el-button type="danger" link size="small" @click="handleDelete(data)" :icon="Delete">
<el-button
:type="getLevelButtonType(node.level, 'delete')"
link
size="small"
@click="handleDelete(data)"
:icon="Delete"
>
删除
</el-button>
</span>
@ -195,6 +213,21 @@ const savePrinterConfig = async () => {
}
// ==================== 库位管理相关 ====================
// 根据层级返回按钮颜色类型
const getLevelButtonType = (level: number, action: string) => {
// 层级颜色映射
const levelColors: Record<number, Record<string, string>> = {
0: { add: 'primary', edit: 'info', delete: 'danger' }, // 顶级: 蓝/灰/红
1: { add: 'success', edit: 'warning', delete: 'danger' }, // 二级: 绿/橙/红
2: { add: 'warning', edit: 'info', delete: 'danger' }, // 三级: 橙/灰/红
}
// 4级及以上统一使用危险色
if (level >= 3) {
return 'danger'
}
return levelColors[level]?.[action] || 'primary'
}
const warehouseDialogVisible = ref(false)
const treeRef = ref()
const treeData = ref<any[]>([])

View File

@ -327,16 +327,15 @@
</el-col>
<el-col :span="6">
<el-form-item label="库位" prop="warehouse_location">
<el-autocomplete
v-model="form.warehouse_location"
:fetch-suggestions="querySearchLocation"
placeholder="例如: A-01-02"
style="width: 100%"
clearable
:trigger-on-focus="true"
>
<template #default="{ item }"><div style="font-weight: 500">{{ item.value }}</div></template>
</el-autocomplete>
<el-cascader
v-model="form.warehouse_location"
:options="warehouseOptions"
:props="{ value: 'full_path', label: 'name', children: 'children', checkStrictly: true, emitPath: false }"
placeholder="请选择库位"
style="width: 100%"
clearable
filterable
/>
</el-form-item>
</el-col>
</el-row>
@ -653,6 +652,7 @@ import {
getFilterOptions
} from '@/api/inbound/buy'
import {getLabelPreview, executePrint} from '@/api/common/print'
import { getWarehouseTree } from '@/api/common/warehouse'
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue'
import { useUserStore } from '@/stores/user'
@ -782,6 +782,9 @@ const cameraRef = ref<InstanceType<typeof WebRtcCamera> | null>(null)
const currentCameraField = ref<'arrival_photo' | 'inspection_report'>('arrival_photo')
const inspection_report_url = ref('')
// 库位级联选择器数据
const warehouseOptions = ref<any[]>([])
const advancedFilterVisible = ref(false)
const advancedConditions = ref([{ field: '', operator: '', value: '' }])
const fieldOptions = computed(() => {
@ -1227,6 +1230,18 @@ const fetchOptions = async () => {
}
}
// 加载库位树数据
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.category = ''
@ -1524,6 +1539,7 @@ onMounted(() => {
initColumnPermissions()
fetchData()
fetchOptions()
loadWarehouseTree()
})
</script>

View File

@ -286,7 +286,17 @@
<div class="card-content">
<el-row :gutter="24">
<el-col :span="6"><el-form-item label="SKU" prop="sku"><el-input v-model="form.sku" placeholder="自动生成" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="库位" prop="warehouse_location"><el-input v-model="form.warehouse_location" placeholder="例如: B-01-01" clearable /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="库位" prop="warehouse_location">
<el-cascader
v-model="form.warehouse_location"
:options="warehouseOptions"
:props="{ value: 'full_path', label: 'name', children: 'children', checkStrictly: true, emitPath: false }"
placeholder="请选择库位"
style="width: 100%"
clearable
filterable
/>
</el-form-item></el-col>
<el-col :span="6"><el-form-item label="入库日期"><el-date-picker v-model="form.in_date" type="date" value-format="YYYY-MM-DD" style="width:100%" disabled /></el-form-item></el-col>
</el-row>
@ -513,6 +523,7 @@ import {
import { uploadFile, deleteFile } from '@/api/inbound/buy'
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue'
import { getLabelPreview, executePrint } from '@/api/common/print'
import { getWarehouseTree } from '@/api/common/warehouse'
import { useUserStore } from '@/stores/user'
// ------------------------------------
@ -628,6 +639,9 @@ const currentCameraField = ref<'product_photo' | 'quality_report_link' | 'inspec
const quality_url = ref('')
const inspection_url = ref('')
// 库位级联选择器数据
const warehouseOptions = ref<any[]>([])
// [核心优化] 所有列定义
const allColumns = [
{ prop: 'company_name', label: '所属公司', minWidth: '100', sortable: true }, // [新增]
@ -958,6 +972,18 @@ const fetchOptions = async () => {
}
}
// 加载库位树数据
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.category = ''
@ -1178,6 +1204,7 @@ onMounted(() => {
initColumnPermissions()
fetchData()
fetchOptions()
loadWarehouseTree()
})
// 成本计算监听

View File

@ -345,7 +345,17 @@
<el-row :gutter="24">
<el-col :span="6"><el-form-item label="编码/SKU" prop="sku"><el-input v-model="form.sku" placeholder="系统自动生成" disabled/></el-form-item></el-col>
<el-col :span="6"><el-form-item label="入库日期" prop="in_date"><el-date-picker v-model="form.in_date" type="date" value-format="YYYY-MM-DD" style="width:100%" disabled/></el-form-item></el-col>
<el-col :span="6"><el-form-item label="库位" prop="warehouse_location"><el-input v-model="form.warehouse_location" placeholder="例如: B-01-01" clearable/></el-form-item></el-col>
<el-col :span="6"><el-form-item label="库位" prop="warehouse_location">
<el-cascader
v-model="form.warehouse_location"
:options="warehouseOptions"
:props="{ value: 'full_path', label: 'name', children: 'children', checkStrictly: true, emitPath: false }"
placeholder="请选择库位"
style="width: 100%"
clearable
filterable
/>
</el-form-item></el-col>
</el-row>
<div class="identity-panel">
@ -577,6 +587,7 @@ import {
import { uploadFile, deleteFile } from '@/api/inbound/buy'
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue'
import {getLabelPreview, executePrint} from '@/api/common/print'
import { getWarehouseTree } from '@/api/common/warehouse'
import { useUserStore } from '@/stores/user'
// ------------------------------------
@ -691,6 +702,9 @@ const cameraRef = ref<InstanceType<typeof WebRtcCamera> | null>(null)
const currentCameraField = ref<'arrival_photo' | 'quality_report_link'>('arrival_photo')
const quality_report_url = ref('')
// 库位级联选择器数据
const warehouseOptions = ref<any[]>([])
const entryMode = ref('batch')
const modeLocked = ref(false)
@ -1092,6 +1106,18 @@ const fetchOptions = async () => {
}
}
// 加载库位树数据
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.category = ''
@ -1306,6 +1332,7 @@ onMounted(() => {
initColumnPermissions()
fetchData()
fetchOptions()
loadWarehouseTree()
})
</script>