This commit is contained in:
zlwu committed 2026-06-21 12:41:39 +08:00
1 parent 299609706c
commit e46c0480d4
87 files changed
+11975 -15543

No files matched your search

@@ -1,159 +1,25 @@
<template>
<el-dialog
v-model="innerVisible"
<SystemViewDialog
v-model:visible="innerVisible"
title="查看关联数据"
:icon="Link"
:sections="sections"
:loading="loading"
width="1200px"
align-center
destroy-on-close
class="dialog-form-layout db-related-table-dialog"
modal-class="order-module-dialog-mask"
>
<div v-loading="loading" class="db-related-body">
<el-empty v-if="!hasData" description="暂无关联数据" />
<template v-else>
<section v-if="data.plan" class="db-related-table-section">
<h3 class="db-related-table-title">计划</h3>
<div class="view-subtable-wrap">
<el-table :data="planRows" class="view-subtable list-table" stripe>
<el-table-column prop="planNo" label="计划号" min-width="120" align="center" />
<el-table-column prop="businessType" label="业务类型" min-width="100" align="center">
<template #default="{ row }">
<el-tag :type="businessTypeTagType(row.businessType)" size="small">
{{ row.businessType }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="customerName"
label="往来单位"
min-width="150"
align="center"
show-overflow-tooltip
/>
<el-table-column
prop="product"
label="产品"
min-width="120"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="planDate" label="计划日期" min-width="120" align="center" />
<el-table-column prop="startDate" label="起始日期" min-width="120" align="center" />
<el-table-column prop="endDate" label="截止日期" min-width="120" align="center" />
<el-table-column prop="executionStatus" label="执行状态" min-width="110" align="center">
<template #default="{ row }">
<el-tag :type="planExecutionTagType(row.executionStatus)" size="small">
{{ row.executionStatus || '—' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="plannedQuantity" label="计划量(吨)" min-width="110" align="right" />
<el-table-column label="已执行量(吨)" min-width="110" align="right">
<template #default="{ row }">
{{ formatKgToTon(row.executedQuantity) }}
</template>
</el-table-column>
<el-table-column
prop="remarks"
label="备注"
min-width="150"
align="center"
show-overflow-tooltip
/>
</el-table>
</div>
</section>
<section v-if="data.weighing" class="db-related-table-section">
<h3 class="db-related-table-title">地磅单</h3>
<div class="view-subtable-wrap">
<el-table :data="weighingRows" class="view-subtable list-table" stripe>
<el-table-column
prop="batchNo"
label="出入库单号"
min-width="130"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="vehicleNo" label="车牌号" min-width="110" align="center" />
<el-table-column
prop="cargoName"
label="货物名称"
min-width="120"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="businessType" label="业务类型" min-width="100" align="center">
<template #default="{ row }">
<el-tag :type="businessTypeTagType(row.businessType)" size="small">
{{ row.businessType }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="supplier"
label="供货单位"
min-width="150"
align="center"
show-overflow-tooltip
/>
<el-table-column
prop="consignee"
label="收货单位"
min-width="150"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="grossWeight" label="毛重(kg)" min-width="110" align="right" />
<el-table-column
prop="grossWeightTime"
label="毛重时间"
min-width="160"
align="center"
/>
<el-table-column prop="tareWeight" label="皮重(kg)" min-width="110" align="right" />
<el-table-column
prop="tareWeightTime"
label="皮重时间"
min-width="160"
align="center"
/>
<el-table-column prop="deduction" label="扣杂(kg)" min-width="110" align="right">
<template #default="{ row }">
{{ row.deduction ?? 0 }}
</template>
</el-table-column>
<el-table-column prop="netWeight" label="净重(kg)" min-width="110" align="right" />
<el-table-column
prop="remarks"
label="备注"
min-width="150"
align="center"
show-overflow-tooltip
/>
</el-table>
</div>
</section>
</template>
</div>
<template #footer>
<el-button @click="innerVisible = false">
<el-icon><Close /></el-icon>
关闭
</el-button>
</template>
</el-dialog>
/>
</template>
<script setup lang="ts">
/**
* UI 模式 P09 · 标准查看弹窗(3 列 KV 表格)
* 参考:DbPlanRelatedViewDialog · src/views/db/plans/index.vue
*/
import { computed } from 'vue'
import { Close } from '@element-plus/icons-vue'
import { Link } from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import type { InventoryRelatedData } from '@/api/db/inventory'
import {
businessTypeTagType,
formatKgToTon,
planExecutionTagType
} from '@/components/business/db/db-related-view'
import { buildInventoryRelatedSections } from '@/components/business/db/db-related-view'
const props = defineProps<{
visible: boolean
@@ -170,9 +36,5 @@
set: (val) => emit('update:visible', val)
})
const hasData = computed(() => Boolean(props.data.plan || props.data.weighing))
const planRows = computed(() => (props.data.plan ? [props.data.plan] : []))
const weighingRows = computed(() => (props.data.weighing ? [props.data.weighing] : []))
const sections = computed(() => buildInventoryRelatedSections(props.data))
</script>
@@ -1,131 +1,25 @@
<template>
<el-dialog
v-model="innerVisible"
<SystemViewDialog
v-model:visible="innerVisible"
title="查看关联数据"
:icon="Link"
:sections="sections"
:loading="loading"
width="1200px"
align-center
destroy-on-close
class="dialog-form-layout db-related-table-dialog"
modal-class="order-module-dialog-mask"
>
<div v-loading="loading" class="db-related-body">
<el-empty v-if="!hasData" description="暂无关联数据" />
<template v-else>
<section v-if="data.inventories.length" class="db-related-table-section">
<h3 class="db-related-table-title">出入库单</h3>
<div class="view-subtable-wrap">
<el-table :data="data.inventories" class="view-subtable list-table" stripe>
<el-table-column type="index" label="序号" min-width="60" align="center" />
<el-table-column
prop="batchNo"
label="出入库单号"
min-width="130"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="date" label="日期" min-width="120" align="center" />
<el-table-column
prop="partnerCompany"
label="往来单位"
min-width="150"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="businessType" label="业务类型" min-width="100" align="center">
<template #default="{ row }">
<el-tag :type="businessTypeTagType(row.businessType)" size="small">
{{ row.businessType }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="product"
label="产品"
min-width="120"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="vehicleNo" label="车牌号" min-width="110" align="center" />
<el-table-column prop="quantity" label="数量(吨)" min-width="110" align="right" />
<el-table-column prop="status" label="状态" min-width="100" align="center">
<template #default="{ row }">
<el-tag :type="inventoryStatusTagType(row.status)" size="small">
{{ row.status || '待处理' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="remarks"
label="备注"
min-width="150"
align="center"
show-overflow-tooltip
/>
</el-table>
</div>
</section>
<section v-if="data.weighings.length" class="db-related-table-section">
<h3 class="db-related-table-title">地磅单</h3>
<div class="view-subtable-wrap">
<el-table :data="data.weighings" class="view-subtable list-table" stripe>
<el-table-column type="index" label="序号" min-width="60" align="center" />
<el-table-column
prop="batchNo"
label="出入库单号"
min-width="130"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="vehicleNo" label="车牌号" min-width="110" align="center" />
<el-table-column
prop="cargoName"
label="货物名称"
min-width="120"
align="center"
show-overflow-tooltip
/>
<el-table-column prop="businessType" label="业务类型" min-width="100" align="center">
<template #default="{ row }">
<el-tag :type="businessTypeTagType(row.businessType)" size="small">
{{ row.businessType }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="grossWeight" label="毛重(kg)" min-width="110" align="right" />
<el-table-column
prop="grossWeightTime"
label="毛重时间"
min-width="160"
align="center"
/>
<el-table-column prop="tareWeight" label="皮重(kg)" min-width="110" align="right" />
<el-table-column
prop="tareWeightTime"
label="皮重时间"
min-width="160"
align="center"
/>
<el-table-column prop="netWeight" label="净重(kg)" min-width="110" align="right" />
</el-table>
</div>
</section>
</template>
</div>
<template #footer>
<el-button @click="innerVisible = false">
<el-icon><Close /></el-icon>
关闭
</el-button>
</template>
</el-dialog>
/>
</template>
<script setup lang="ts">
/**
* UI 模式 P09 · 标准查看弹窗(3 列 KV 表格)
* 参考:DbRelatedViewDialog · src/views/db/weighing/index.vue
*/
import { computed } from 'vue'
import { Close } from '@element-plus/icons-vue'
import { Link } from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import type { PlanRelatedData } from '@/api/db/plans'
import { businessTypeTagType, inventoryStatusTagType } from '@/components/business/db/db-related-view'
import { buildPlanRelatedSections } from '@/components/business/db/db-related-view'
const props = defineProps<{
visible: boolean
@@ -142,7 +36,5 @@
set: (val) => emit('update:visible', val)
})
const hasData = computed(
() => props.data.inventories.length > 0 || props.data.weighings.length > 0
)
const sections = computed(() => buildPlanRelatedSections(props.data))
</script>
@@ -1,95 +0,0 @@
<template>
<el-select
v-model="model"
:placeholder="placeholder"
filterable
remote
:remote-method="loadOptions"
:loading="loading"
:allow-create="allowCreate"
default-first-option
clearable
style="width: 100%"
@focus="handleFocus"
>
<el-option
v-for="item in options"
:key="item.id"
:label="item.vehicleNo"
:value="item.vehicleNo"
/>
</el-select>
</template>
<script setup lang="ts">
import { vehicleApi, type Vehicle } from '@/api/db/vehicles'
defineOptions({ name: 'DbVehicleSelect' })
const model = defineModel<string>({ default: '' })
withDefaults(
defineProps<{
placeholder?: string
allowCreate?: boolean
}>(),
{
placeholder: '请选择或输入车牌号',
allowCreate: true
}
)
const loading = ref(false)
const options = ref<Vehicle[]>([])
const loadOptions = async (keyword: string) => {
loading.value = true
try {
options.value = await vehicleApi.list(keyword || undefined)
} catch (error) {
console.error('加载车牌号列表失败', error)
options.value = []
} finally {
loading.value = false
}
}
const handleFocus = () => {
if (options.value.length === 0) {
loadOptions('')
}
}
const isSameVehicleNo = (left: string, right: string) =>
left.trim().toLowerCase() === right.trim().toLowerCase()
const vehicleExists = async (vehicleNo: string) => {
const trimmed = vehicleNo.trim()
if (options.value.some((item) => isSameVehicleNo(item.vehicleNo, trimmed))) {
return true
}
const list = await vehicleApi.list(trimmed)
const matched = list.find((item) => isSameVehicleNo(item.vehicleNo, trimmed))
if (matched && !options.value.some((item) => item.id === matched.id)) {
options.value = [...options.value, matched]
}
return Boolean(matched)
}
/** 保存前确保车牌号已写入基础资料(已存在则跳过,与原地磅系统一致) */
const ensureVehicleExists = async () => {
const vehicleNo = model.value?.trim()
if (!vehicleNo) return
if (await vehicleExists(vehicleNo)) return
try {
await vehicleApi.create({ vehicleNo, remarks: null }, { showErrorMessage: false })
} catch (err: unknown) {
const status = (err as { response?: { status?: number } })?.response?.status
if (status !== 409) throw err
}
}
defineExpose({ ensureVehicleExists })
</script>
@@ -1,5 +1,5 @@
<template>
<div class="db-chart-card">
<div class="db-chart-card db-dual-bar">
<h3 class="db-chart-title">{{ title }}</h3>
<div class="db-dual-bar__body">
<el-empty v-if="!data.length" description="今日无数据" />
@@ -14,8 +14,9 @@
实际量
</span>
</div>
<div class="chart-container">
<div v-for="item in data" :key="item.label" class="chart-item">
<span class="chart-label">{{ item.label }}</span>
<span class="chart-label" :title="item.label">{{ item.label }}</span>
<div class="chart-bar-group">
<div class="chart-bar-wrapper">
<div
@@ -41,6 +42,7 @@
<span class="value actual">{{ item.actual.toFixed(2) }}</span>
</div>
</div>
</div>
</template>
</div>
</div>
@@ -30,6 +30,8 @@ function sectionTitle(base: string, index: number, total: number): string {
export function buildPlanViewSection(plan: Plan): ViewSection {
return {
title: '计划',
fieldLayout: 'table',
tableMode: 'triple',
fields: [
{ label: '计划号', value: plan.planNo },
{ label: '业务类型', value: plan.businessType, tagType: businessTypeTagType(plan.businessType) },
@@ -57,6 +59,8 @@ export function buildInventoryViewSection(
): ViewSection {
return {
title,
fieldLayout: 'table',
tableMode: 'triple',
fields: [
{ label: '出入库单号', value: record.batchNo },
{ label: '日期', value: record.date },
@@ -120,7 +124,7 @@ export function buildWeighingViewSection(
fields.push({ label: '备注', value: record.remarks, span: true })
}
return { title, fields }
return { title, fieldLayout: 'table', tableMode: 'triple', fields }
}
type MergedPlanRelatedItem = (PlanInventoryRecord | PlanWeighingRecord) & {
@@ -160,7 +164,14 @@ function mergePlanRelatedItems(data: PlanRelatedData): MergedPlanRelatedItem[] {
export function buildPlanRelatedSections(data: PlanRelatedData): ViewSection[] {
const items = mergePlanRelatedItems(data)
if (!items.length) {
return [{ title: '关联数据', fields: [{ label: '说明', value: '暂无关联数据', span: true }] }]
return [
{
title: '关联数据',
fieldLayout: 'table',
tableMode: 'triple',
fields: [{ label: '说明', value: '暂无关联数据', span: 'full' }]
}
]
}
const inventoryCount = items.filter((item) => item.type === 'inventory').length
@@ -185,7 +196,14 @@ export function buildInventoryRelatedSections(data: InventoryRelatedData): ViewS
if (data.plan) sections.push(buildPlanViewSection(data.plan))
if (data.weighing) sections.push(buildWeighingViewSection(data.weighing))
if (!sections.length) {
return [{ title: '关联数据', fields: [{ label: '说明', value: '暂无关联数据', span: true }] }]
return [
{
title: '关联数据',
fieldLayout: 'table',
tableMode: 'triple',
fields: [{ label: '说明', value: '暂无关联数据', span: 'full' }]
}
]
}
return sections
}
@@ -195,7 +213,14 @@ export function buildWeighingRelatedSections(data: WeighingRelatedData): ViewSec
if (data.plan) sections.push(buildPlanViewSection(data.plan))
if (data.inventory) sections.push(buildInventoryViewSection(data.inventory))
if (!sections.length) {
return [{ title: '关联数据', fields: [{ label: '说明', value: '暂无关联数据', span: true }] }]
return [
{
title: '关联数据',
fieldLayout: 'table',
tableMode: 'triple',
fields: [{ label: '说明', value: '暂无关联数据', span: 'full' }]
}
]
}
return sections
}