up
This commit is contained in:
@@ -38,6 +38,7 @@ const notFound = ref(false)
|
||||
|
||||
// ── 容器名缓存 ──
|
||||
const containerNames = reactive({})
|
||||
const containerBreadcrumb = ref('')
|
||||
|
||||
// ── Tab ──
|
||||
const activeTab = ref('work_orders')
|
||||
@@ -112,6 +113,7 @@ async function fetchItem() {
|
||||
commits.value = data.commits ?? []
|
||||
workOrders.value = data.work_orders ?? []
|
||||
canModifyItem.value = data.canModifyItem === true
|
||||
containerBreadcrumb.value = data.container_breadcrumb ?? ''
|
||||
loadContainerNames()
|
||||
} else {
|
||||
notFound.value = true
|
||||
@@ -375,12 +377,13 @@ onMounted(() => {
|
||||
<span>{{ t('warehouse.quantity') }}: {{ item.Quantity }}</span>
|
||||
<span>{{ t('warehouse.location') }}:
|
||||
<RouterLink
|
||||
v-if="item.ContainerID"
|
||||
v-if="containerBreadcrumb"
|
||||
:to="`/warehouse/container/${item.ContainerID}`"
|
||||
class="text-blue-500 hover:underline ml-1"
|
||||
>
|
||||
{{ containerNames[item.ContainerID] || `#${item.ContainerID}` }}
|
||||
{{ containerBreadcrumb }}
|
||||
</RouterLink>
|
||||
<span v-else-if="item.ContainerID" class="text-blue-500 ml-1">{{ `#${item.ContainerID}` }}</span>
|
||||
<span v-else class="text-orange-500 ml-1">{{ t('warehouse.unstored') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -499,9 +502,9 @@ onMounted(() => {
|
||||
<span>{{ fmtTs(commit.CreatedAt) }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5 mt-0.5 flex-wrap text-sm font-medium text-gray-700 dark:text-gray-200">
|
||||
<span>{{ getContainerName(commit.OldContainer) }}</span>
|
||||
<span>{{ commit.OldContainerBreadcrumb || t('warehouse.unstored') }}</span>
|
||||
<IconArrowRight :size="13" class="text-blue-500 flex-shrink-0" />
|
||||
<span>{{ getContainerName(commit.NewContainer) }}</span>
|
||||
<span>{{ commit.NewContainerBreadcrumb || t('warehouse.unstored') }}</span>
|
||||
</div>
|
||||
<p v-if="commit.Remark" class="text-xs text-gray-400 mt-0.5">{{ commit.Remark }}</p>
|
||||
</div>
|
||||
@@ -526,12 +529,13 @@ onMounted(() => {
|
||||
{{ t('warehouse.current_location') }}:
|
||||
<span class="font-medium text-gray-700 dark:text-gray-300">
|
||||
<RouterLink
|
||||
v-if="item?.ContainerID"
|
||||
v-if="containerBreadcrumb"
|
||||
:to="`/warehouse/container/${item.ContainerID}`"
|
||||
class="text-blue-500 hover:underline"
|
||||
>
|
||||
{{ containerNames[item.ContainerID] || `#${item.ContainerID}` }}
|
||||
{{ containerBreadcrumb }}
|
||||
</RouterLink>
|
||||
<span v-else-if="item?.ContainerID">#{{ item.ContainerID }}</span>
|
||||
<span v-else class="text-orange-500">{{ t('warehouse.unstored') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -29,67 +29,11 @@ const currentPage = ref(1)
|
||||
const search = ref('')
|
||||
const loading = ref(false)
|
||||
|
||||
// 容器名映射表
|
||||
const containerMap = ref({})
|
||||
const allContainerCount = ref(0)
|
||||
|
||||
const isEn = computed(() => locale.value === 'en')
|
||||
|
||||
// ── 统计数据 ──
|
||||
const stats = reactive({
|
||||
total: 0,
|
||||
inContainer: 0,
|
||||
unstored: 0,
|
||||
})
|
||||
|
||||
// ── 分页信息 ──
|
||||
const totalPages = computed(() => Math.ceil(totalCount.value / pageSize.value) || 1)
|
||||
|
||||
function getContainerTitle(cid) {
|
||||
if (cid == null) return `<span class="text-gray-400">${t('warehouse.unstored_items')}</span>`
|
||||
return containerMap.value[cid] || `#${cid}`
|
||||
}
|
||||
|
||||
// ── 权限判断 ──
|
||||
function canModifyItem(idx) {
|
||||
return canModifyItems.value[idx] === true
|
||||
}
|
||||
|
||||
// ── 获取容器名映射 ──
|
||||
async function fetchContainerMap() {
|
||||
try {
|
||||
const { errCode, data } = await warehouseApi.getContainers({ entries: 500, page: 1 })
|
||||
if (errCode === 0 && data) {
|
||||
allContainerCount.value = data.all_count || 0
|
||||
const map = {}
|
||||
for (const c of (data.containers || [])) {
|
||||
map[c.ID] = c.Title
|
||||
}
|
||||
for (const c of (data.containers || [])) {
|
||||
if (c.ChildCount > 0) {
|
||||
await fetchChildContainers(c.ID, map)
|
||||
}
|
||||
}
|
||||
containerMap.value = map
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchChildContainers(parentId, map) {
|
||||
try {
|
||||
const { errCode, data } = await warehouseApi.getContainers({ entries: 500, page: 1, parent_id: parentId })
|
||||
if (errCode === 0 && data) {
|
||||
for (const c of (data.containers || [])) {
|
||||
map[c.ID] = c.Title
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// ── 获取物品列表 ──
|
||||
async function fetchItems() {
|
||||
loading.value = true
|
||||
@@ -205,9 +149,7 @@ function formatDate(dateStr) {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchContainerMap().then(fetchItems)
|
||||
})
|
||||
onMounted(fetchItems)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -289,9 +231,9 @@ onMounted(() => {
|
||||
<td class="px-5 py-3 text-xs text-gray-500 dark:text-gray-400 max-w-[160px] truncate">{{ item.SerialNumber || '—' }}</td>
|
||||
<td class="px-5 py-3 text-center text-sm">{{ item.Quantity }}</td>
|
||||
<td class="px-5 py-3">
|
||||
<span v-if="item.ContainerID != null" class="inline-flex items-center gap-1 text-blue-600 text-sm">
|
||||
<span v-if="item.ContainerBreadcrumb" class="inline-flex items-center gap-1 text-blue-600 text-sm">
|
||||
<IconArrowRight :size="13" />
|
||||
<span class="truncate max-w-[140px]">{{ getContainerTitle(item.ContainerID) }}</span>
|
||||
<span class="truncate max-w-[200px]">{{ item.ContainerBreadcrumb }}</span>
|
||||
</span>
|
||||
<span v-else class="inline-flex items-center gap-1 text-xs text-orange-500">
|
||||
{{ t('warehouse.unstored_items') }}
|
||||
|
||||
@@ -45,7 +45,6 @@ const containerPage = ref(1)
|
||||
const containerPageSize = ref(10)
|
||||
const containerSearch = ref('')
|
||||
const containerLoading = ref(false)
|
||||
const containerMap = ref({}) // id -> title
|
||||
|
||||
// 新增/编辑弹窗
|
||||
const showContainerForm = ref(false)
|
||||
@@ -109,17 +108,6 @@ async function fetchContainers() {
|
||||
finally { containerLoading.value = false }
|
||||
}
|
||||
|
||||
async function fetchAllContainerMap() {
|
||||
try {
|
||||
const { errCode, data } = await warehouseApi.getContainers({ entries: 500, page: 1 })
|
||||
if (errCode === 0 && data) {
|
||||
const map = {}
|
||||
for (const c of (data.containers || [])) map[c.ID] = c.Title
|
||||
containerMap.value = map
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
function goContainerPage(page) {
|
||||
if (page < 1 || page > containerTotalPages.value) return
|
||||
containerPage.value = page
|
||||
@@ -304,10 +292,6 @@ async function doDeleteItem() {
|
||||
finally { deletingItem.value = false }
|
||||
}
|
||||
|
||||
function getContainerTitle(cid) {
|
||||
return containerMap.value[cid] || `#${cid}`
|
||||
}
|
||||
|
||||
// ── 工具函数 ──
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '—'
|
||||
@@ -349,7 +333,7 @@ function fmtTs(ts) {
|
||||
onMounted(() => {
|
||||
fetchContainerStats()
|
||||
fetchContainers()
|
||||
fetchAllContainerMap().then(() => fetchItems())
|
||||
fetchItems()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -584,9 +568,9 @@ onMounted(() => {
|
||||
<td class="px-6 py-3 max-w-[200px] truncate text-xs text-gray-500 dark:text-gray-400">{{ item.Remark || '—' }}</td>
|
||||
<td class="px-6 py-3 text-center text-sm">{{ item.Quantity }}</td>
|
||||
<td class="px-6 py-3">
|
||||
<span v-if="item.ContainerID != null" class="inline-flex items-center gap-1 text-sm text-blue-600">
|
||||
<span v-if="item.ContainerBreadcrumb" class="inline-flex items-center gap-1 text-sm text-blue-600">
|
||||
<IconArrowRight :size="13" />
|
||||
<span class="max-w-[140px] truncate">{{ getContainerTitle(item.ContainerID) }}</span>
|
||||
<span class="max-w-[200px] truncate">{{ item.ContainerBreadcrumb }}</span>
|
||||
</span>
|
||||
<span v-else class="inline-flex items-center gap-1 text-xs text-orange-500">
|
||||
{{ t('warehouse.unstored_items') }}
|
||||
|
||||
Reference in New Issue
Block a user