优化
This commit is contained in:
@@ -1,60 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { ArrowLeft } from '@lucide/vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import ContractPendingNotice from '../components/ContractPendingNotice.vue'
|
||||
import type { InventoryTransactionListItem } from '../types'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'; import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'; import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'; import ListPageLayout from '@/shared/components/ListPageLayout.vue'; import LoadErrorState from '@/shared/components/LoadErrorState.vue'; import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import { listInventoryLedger } from '../api/inventory'; import { formatOverseasDateTime } from '../lastMilePresentation'; import type { InventoryTransactionListItem } from '../types'
|
||||
|
||||
const router = useRouter()
|
||||
const rows = ref<InventoryTransactionListItem[]>([])
|
||||
const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const filters = ref<QueryModel>({ occurredDate: [], owner: '', warehouse: '', sku: '', businessType: '', businessOrderNo: '', inboundOrderNo: '', outboundOrderNo: '' })
|
||||
const fields: QueryField[] = [
|
||||
{ key: 'occurredDate', type: 'daterange', label: '发生日期', width: 260 },
|
||||
{ key: 'owner', type: 'input', label: '客户/货主', placeholder: '请输入客户或货主', width: 190 },
|
||||
{ key: 'warehouse', type: 'select', label: '海外仓', placeholder: '全部海外仓', width: 190, options: [] },
|
||||
{ key: 'sku', type: 'input', label: 'SKU编码', placeholder: '请输入SKU编码', width: 170 },
|
||||
{ key: 'businessType', type: 'select', label: '业务类型', placeholder: '全部业务类型', width: 170, options: ['采购库存', '头程入库', '尾程入库', '退货入库', '暂扣库存', '一件代发', '头程出库', '派送出库', '调拨转仓', '库存调整'].map((value) => ({ label: value, value })) },
|
||||
{ key: 'businessOrderNo', type: 'input', label: '业务订单号', placeholder: '请输入业务订单号', width: 180 },
|
||||
{ key: 'inboundOrderNo', type: 'input', label: '入库单号', placeholder: '请输入入库单号', width: 180 },
|
||||
{ key: 'outboundOrderNo', type: 'input', label: '出库单号', placeholder: '请输入出库单号', width: 180 },
|
||||
]
|
||||
const route = useRoute(); const router = useRouter(); const rows = ref<InventoryTransactionListItem[]>([]); const customers = ref<PlatformTenantResource[]>([]); const page = ref(1); const pageSize = ref(20); const total = ref(0); const loading = ref(false); const customersLoading = ref(false); const loadError = ref<ApiErrorDetails | null>(null); const customersError = ref<ApiErrorDetails | null>(null)
|
||||
const filters = ref<QueryModel>({ occurredDate: [], customerId: String(route.query.customerId || ''), warehouse: '', sku: '', businessType: '', businessOrderNo: '', inboundOrderNo: '', outboundOrderNo: '' })
|
||||
const fields = computed<QueryField[]>(() => [
|
||||
{ key: 'occurredDate', type: 'daterange', label: '发生日期', width: 260 }, { key: 'customerId', type: 'select', label: '客户名称', placeholder: '请选择客户', width: 240, props: { filterable: true, clearable: true, loading: customersLoading.value }, options: customers.value.map((item) => ({ label: item.tenantName, value: String(item.id) })) },
|
||||
{ key: 'warehouse', type: 'input', label: '目的仓代码', placeholder: '请输入目的仓代码', width: 190 }, { key: 'sku', type: 'input', label: 'SKU编码', placeholder: '流水DTO暂未提供', width: 170, props: { disabled: true } },
|
||||
{ key: 'businessType', type: 'input', label: '业务类型', placeholder: '请输入业务类型代码', width: 170 }, { key: 'businessOrderNo', type: 'input', label: '业务订单号', placeholder: '请输入业务订单号', width: 180 },
|
||||
{ key: 'inboundOrderNo', type: 'input', label: '入库单号', placeholder: '请输入入库单号', width: 180 }, { key: 'outboundOrderNo', type: 'input', label: '出库单号', placeholder: '只读关联筛选', width: 180 },
|
||||
])
|
||||
const columns: DataTableColumn[] = [
|
||||
{ key: 'occurredAt', label: '发生时间', minWidth: 160 },
|
||||
{ key: 'owner', label: '客户', minWidth: 160 },
|
||||
{ key: 'warehouse', label: '海外仓', minWidth: 180 },
|
||||
{ key: 'sku', label: 'SKU编码', minWidth: 150 },
|
||||
{ key: 'productName', label: '中文品名', minWidth: 180 },
|
||||
{ key: 'businessType', label: '业务类型', width: 120 },
|
||||
{ key: 'businessOrderNo', label: '业务订单号', minWidth: 170 },
|
||||
{ key: 'inboundOrderNo', label: '入库单号', minWidth: 160 },
|
||||
{ key: 'outboundOrderNo', label: '出库单号', minWidth: 160 },
|
||||
{ key: 'inboundQuantity', label: '入库数量', width: 110, align: 'right' },
|
||||
{ key: 'outboundQuantity', label: '出库数量', width: 110, align: 'right' },
|
||||
{ key: 'balance', label: '结存', width: 100, align: 'right' },
|
||||
{ key: 'operator', label: '操作人', minWidth: 120 },
|
||||
{ key: 'remark', label: '备注', minWidth: 180 },
|
||||
{ key: 'occurredAt', prop: 'occurredAt', label: '发生时间', minWidth: 160 }, { key: 'owner', prop: 'owner', label: '客户', minWidth: 160 }, { key: 'warehouse', prop: 'warehouse', label: '海外仓', minWidth: 180 },
|
||||
{ key: 'sku', prop: 'sku', label: 'SKU编码', minWidth: 150 }, { key: 'productName', prop: 'productName', label: '中文品名', minWidth: 180 }, { key: 'businessType', prop: 'businessType', label: '业务类型', width: 120 },
|
||||
{ key: 'businessOrderNo', prop: 'businessOrderNo', label: '业务订单号', minWidth: 170 }, { key: 'inboundOrderNo', prop: 'inboundOrderNo', label: '入库单号', minWidth: 160 }, { key: 'outboundOrderNo', prop: 'outboundOrderNo', label: '出库单号', minWidth: 160 },
|
||||
{ key: 'inboundQuantity', prop: 'inboundQuantity', label: '入库数量', width: 110, align: 'right' }, { key: 'outboundQuantity', prop: 'outboundQuantity', label: '出库数量', width: 110, align: 'right' }, { key: 'balance', prop: 'balance', label: '结存', width: 100, align: 'right' },
|
||||
{ key: 'operator', prop: 'operator', label: '操作人', minWidth: 120 }, { key: 'remark', prop: 'remark', label: '备注', minWidth: 180 },
|
||||
]
|
||||
|
||||
function back() { void router.push({ name: 'overseas-inventory' }) }
|
||||
function text(value: unknown) { return String(value ?? '').trim() || '—' }
|
||||
function customerName(id: string) { return customers.value.find((item) => String(item.id) === id)?.tenantName || '—' }
|
||||
async function loadCustomers() { customersLoading.value = true; customersError.value = null; try { const records: PlatformTenantResource[] = []; let current = 1; let pages = 1; do { const result = await listPlatformTenants({ page: current, size: 200, status: 'ACTIVE' }); records.push(...result.records); pages = Math.max(1, result.pages); current += 1 } while (current <= pages); customers.value = records; if (filters.value.customerId) void load() } catch (error) { customersError.value = getApiErrorDetails(error, '客户列表加载失败,请重试') } finally { customersLoading.value = false } }
|
||||
async function load(model: QueryModel = filters.value) { Object.assign(filters.value, model); const customerId = String(filters.value.customerId || '').trim(); if (!customerId) { rows.value = []; total.value = 0; loadError.value = null; return }; const range = Array.isArray(filters.value.occurredDate) ? filters.value.occurredDate.map(String) : []; loading.value = true; loadError.value = null; try { const result = await listInventoryLedger({ customerId, page: page.value, size: pageSize.value, destinationWarehouseCode: String(filters.value.warehouse || '').trim() || undefined, businessType: String(filters.value.businessType || '').trim() || undefined, businessOrderNo: String(filters.value.businessOrderNo || '').trim() || undefined, inboundOrderNo: String(filters.value.inboundOrderNo || '').trim() || undefined, outboundOrderNo: String(filters.value.outboundOrderNo || '').trim() || undefined, occurredFrom: range[0] ? `${range[0]}T00:00:00` : undefined, occurredTo: range[1] ? `${range[1]}T23:59:59` : undefined }); rows.value = result.records.map((item) => ({ id: String(item.id), occurredAt: formatOverseasDateTime(item.occurredAt), owner: customerName(customerId), warehouse: text(item.destinationWarehouseCode), sku: '—', productName: '—', businessType: text(item.businessType), businessOrderNo: text(item.businessOrderNo), inboundOrderNo: text(item.inboundOrderNo), outboundOrderNo: text(item.outboundOrderNo), inboundQuantity: item.deltaPackages > 0 ? item.deltaPackages : 0, outboundQuantity: item.deltaPackages < 0 ? Math.abs(item.deltaPackages) : 0, balance: Number(item.afterPackages || 0), operator: text(item.operatorId), remark: text(item.remark) })); total.value = result.total } catch (error) { rows.value = []; total.value = 0; loadError.value = getApiErrorDetails(error, '进销存记录加载失败,请重试') } finally { loading.value = false } }
|
||||
function search(model: QueryModel) { page.value = 1; void load(model) }; function reset(model: QueryModel) { page.value = 1; void load(model) }; function back() { void router.push({ name: 'overseas-inventory' }) }; onMounted(loadCustomers)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminPage><ListPageLayout aria-label="进销存记录列表">
|
||||
<template #toolbar><QueryToolbar v-model="filters" class="surface-panel" :fields="fields" ariaLabel="进销存记录筛选" preference-key="overseas-inventory-transactions-query" @search="page = 1" /></template>
|
||||
<template #state><ContractPendingNotice domain="进销存记录" /><p class="read-only-boundary">出库相关字段仅展示既有库存流水事实;本页面不提供出库单跳转、库存扣减或其他离仓操作。</p></template>
|
||||
<section class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :total="0" preference-key="overseas-inventory-transactions" row-key="id" empty-text="海外区域进销存查询契约待接入">
|
||||
<template #toolbar-actions><el-button @click="back"><ArrowLeft :size="16" />返回库存管理</el-button></template>
|
||||
<template #pagination-left>共 0 条进销存记录</template>
|
||||
</DataTable></section>
|
||||
</ListPageLayout></AdminPage>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.read-only-boundary { margin: 8px 2px 0; color: var(--cc-muted); font-size: 12px; line-height: 1.5; }
|
||||
</style>
|
||||
<template><AdminPage><ListPageLayout aria-label="进销存记录列表"><template #toolbar><QueryToolbar v-model="filters" class="surface-panel" :fields="fields" :loading="loading" ariaLabel="进销存记录筛选" preference-key="overseas-inventory-transactions-query" @search="search" @reset="reset" /></template>
|
||||
<template v-if="customersError || loadError" #state><LoadErrorState title="进销存记录加载失败" :message="(customersError || loadError)?.message" :loading="customersLoading || loading" @retry="customersError ? loadCustomers() : load()"><template #details><ApiErrorMeta :details="(customersError || loadError)!" /></template></LoadErrorState></template>
|
||||
<template v-else #state><p class="read-only-boundary">出库相关字段仅展示既有库存流水事实;本页面不提供出库单跳转、库存扣减或其他离仓操作。当前流水 DTO 未提供 SKU、产品名称与海外仓名称,对应列显示空值。</p></template>
|
||||
<section v-if="!customersError && !loadError" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="overseas-inventory-transactions" row-key="id" :empty-text="filters.customerId ? '暂无进销存记录' : '请先选择客户后查询'" @update:page="load()" @update:page-size="page = 1; load()"><template #toolbar-actions><el-button @click="back"><ArrowLeft :size="16" />返回库存管理</el-button></template><template #pagination-left>共 {{ total }} 条进销存记录</template></DataTable></section>
|
||||
</ListPageLayout></AdminPage></template>
|
||||
<style scoped>.read-only-boundary{margin:8px 2px 0;color:var(--cc-muted);font-size:12px;line-height:1.5}</style>
|
||||
|
||||
Reference in New Issue
Block a user