提交
This commit is contained in:
1 parent
ffc89d9b57
commit
c2cba3e668
53 files changed
+11794
-6264
No files matched your search
@@ -3,11 +3,11 @@
|
||||
<div class="cert-form-header">
|
||||
<span class="cert-form-title">{{ title }}</span>
|
||||
<el-button type="primary" size="small" @click="handleAddCert">
|
||||
<el-icon><Plus /></el-icon>添加证书
|
||||
<el-icon><Plus /></el-icon>{{ addButtonLabel }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="!certList.length" class="cert-empty">暂无证书,点击「添加证书」</div>
|
||||
<div v-if="!certList.length" class="cert-empty">{{ emptyHint }}</div>
|
||||
|
||||
<el-table v-else-if="layout === 'table'" :data="certList" stripe class="list-table cert-form-table">
|
||||
<el-table-column type="index" label="序号" min-width="68" align="center" header-align="center" />
|
||||
@@ -20,7 +20,7 @@
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-if="hasTrailerPlateOption"
|
||||
v-if="hasTrailerPlateOption && !isRowRequired(row)"
|
||||
:model-value="normalizeVehicleCertPart(row.vehiclePart)"
|
||||
placeholder="请选择车牌号"
|
||||
style="width: 100%"
|
||||
@@ -33,12 +33,17 @@
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>{{ headPlateLabel }}</span>
|
||||
<span v-else>{{ resolvePlateLabel(row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="证书名称" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<span v-if="isRowRequired(row)" class="cert-name-locked">
|
||||
{{ row.certName }}
|
||||
<el-tag type="info" size="small">必备</el-tag>
|
||||
</span>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="row.certName"
|
||||
placeholder="请选择或输入"
|
||||
filterable
|
||||
@@ -87,8 +92,8 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="60" align="center" header-align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-button link type="danger" @click="handleRemoveCert($index)">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button v-if="!isRowRequired(row)" link type="danger" @click="handleRemoveCert($index)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -98,15 +103,19 @@
|
||||
<div v-else class="cert-card-list">
|
||||
<div v-for="(cert, index) in certList" :key="cert._key" class="cert-card">
|
||||
<div class="cert-card-head">
|
||||
<span class="cert-card-index">证书 {{ index + 1 }}</span>
|
||||
<el-button link type="danger" @click="handleRemoveCert(index)">
|
||||
<span class="cert-card-index">
|
||||
{{ isRowRequired(cert) ? `必备 · ${cert.certName}` : `证书 ${index + 1}` }}
|
||||
</span>
|
||||
<el-button v-if="!isRowRequired(cert)" link type="danger" @click="handleRemoveCert(index)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="form-grid-4 cert-card-grid">
|
||||
<el-form-item label="证书名称" required>
|
||||
<span v-if="isRowRequired(cert)" class="cert-name-locked">{{ cert.certName }}</span>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="cert.certName"
|
||||
placeholder="请选择或输入证书名称"
|
||||
filterable
|
||||
@@ -155,12 +164,23 @@ import { Delete, Plus } from '@element-plus/icons-vue'
|
||||
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
|
||||
import type { CertRow } from '@/api/pl'
|
||||
import {
|
||||
ensureCarrierVehicleCertSlots,
|
||||
ensureSelfVehicleCertSlots,
|
||||
mergeCertListWithRequiredSlots,
|
||||
type CertRowWithMeta
|
||||
} from '@/utils/pl-cert-slots'
|
||||
import { matchRequiredCertName } from '@/utils/pl-personnel-cert'
|
||||
import {
|
||||
PL_CARRIER_VEHICLE_HEAD_REQUIRED_CERT_NAMES,
|
||||
PL_CARRIER_VEHICLE_TRAILER_REQUIRED_CERT_NAMES,
|
||||
PL_SELF_VEHICLE_HEAD_REQUIRED_CERT_NAMES,
|
||||
PL_SELF_VEHICLE_TRAILER_REQUIRED_CERT_NAMES,
|
||||
PL_VEHICLE_CERT_PART_HEAD,
|
||||
PL_VEHICLE_CERT_PART_TRAILER,
|
||||
normalizeVehicleCertPart
|
||||
} from '@/utils/pl-vehicle-cert'
|
||||
|
||||
type CertRowWithKey = CertRow & { _key: string }
|
||||
type CertRowWithKey = CertRowWithMeta & { _key: string }
|
||||
type CertUploadRef = InstanceType<typeof AttachmentUploadField>
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -169,10 +189,16 @@ const props = withDefaults(
|
||||
uploadFolder: string
|
||||
certNameOptions?: string[]
|
||||
layout?: 'card' | 'table'
|
||||
/** 列表模式:展示车牌号列,可从主车/挂车车牌中选择 */
|
||||
showVehiclePartColumn?: boolean
|
||||
licensePlate?: string
|
||||
trailerNo?: string
|
||||
/** 人员/单段车辆:固定必备证书名称 */
|
||||
requiredCertNames?: readonly string[]
|
||||
requiredVehiclePart?: string
|
||||
/** 山峡自有车统一表格:按主车/挂车自动注入必备槽位 */
|
||||
enforceSelfVehicleRequired?: boolean
|
||||
/** 承运商车辆:按主车/挂车注入必备槽位(行驶证、营运证) */
|
||||
enforceCarrierVehicleRequired?: boolean
|
||||
}>(),
|
||||
{
|
||||
title: '证书',
|
||||
@@ -180,10 +206,27 @@ const props = withDefaults(
|
||||
layout: 'card',
|
||||
showVehiclePartColumn: false,
|
||||
licensePlate: '',
|
||||
trailerNo: ''
|
||||
trailerNo: '',
|
||||
requiredCertNames: () => [],
|
||||
requiredVehiclePart: PL_VEHICLE_CERT_PART_HEAD,
|
||||
enforceSelfVehicleRequired: false,
|
||||
enforceCarrierVehicleRequired: false
|
||||
}
|
||||
)
|
||||
|
||||
const hasRequiredMode = computed(
|
||||
() =>
|
||||
props.enforceSelfVehicleRequired ||
|
||||
props.enforceCarrierVehicleRequired ||
|
||||
(props.requiredCertNames?.length ?? 0) > 0
|
||||
)
|
||||
|
||||
const addButtonLabel = computed(() => (hasRequiredMode.value ? '添加其他证书' : '添加证书'))
|
||||
|
||||
const emptyHint = computed(() =>
|
||||
hasRequiredMode.value ? '暂无证书' : '暂无证书,点击「添加证书」'
|
||||
)
|
||||
|
||||
const headPlateLabel = computed(() => props.licensePlate?.trim() || '—')
|
||||
const hasTrailerPlateOption = computed(() => Boolean(props.trailerNo?.trim()))
|
||||
|
||||
@@ -203,23 +246,88 @@ const vehiclePlateOptions = computed(() => {
|
||||
return options
|
||||
})
|
||||
|
||||
function resolvePlateLabel(row: CertRowWithKey) {
|
||||
const part = normalizeVehicleCertPart(row.vehiclePart)
|
||||
if (part === PL_VEHICLE_CERT_PART_TRAILER) {
|
||||
return props.trailerNo?.trim() || '挂车'
|
||||
}
|
||||
return headPlateLabel.value
|
||||
}
|
||||
|
||||
function requiredNamesForRow(row: CertRowWithKey): readonly string[] {
|
||||
if (props.requiredCertNames?.length) {
|
||||
return props.requiredCertNames
|
||||
}
|
||||
if (!props.enforceSelfVehicleRequired && !props.enforceCarrierVehicleRequired) return []
|
||||
const part = normalizeVehicleCertPart(row.vehiclePart)
|
||||
if (props.enforceCarrierVehicleRequired) {
|
||||
return part === PL_VEHICLE_CERT_PART_TRAILER
|
||||
? PL_CARRIER_VEHICLE_TRAILER_REQUIRED_CERT_NAMES
|
||||
: PL_CARRIER_VEHICLE_HEAD_REQUIRED_CERT_NAMES
|
||||
}
|
||||
return part === PL_VEHICLE_CERT_PART_TRAILER
|
||||
? PL_SELF_VEHICLE_TRAILER_REQUIRED_CERT_NAMES
|
||||
: PL_SELF_VEHICLE_HEAD_REQUIRED_CERT_NAMES
|
||||
}
|
||||
|
||||
function isRowRequired(row: CertRowWithKey) {
|
||||
if (row._required) return true
|
||||
const requiredNames = requiredNamesForRow(row)
|
||||
if (!requiredNames.length) return false
|
||||
return requiredNames.some(name => matchRequiredCertName(row.certName, name))
|
||||
}
|
||||
|
||||
function syncRequiredSlots() {
|
||||
if (props.enforceSelfVehicleRequired) {
|
||||
certList.value = ensureSelfVehicleCertSlots(certList.value, props.trailerNo)
|
||||
return
|
||||
}
|
||||
if (props.enforceCarrierVehicleRequired) {
|
||||
certList.value = ensureCarrierVehicleCertSlots(certList.value, props.trailerNo)
|
||||
return
|
||||
}
|
||||
if (props.requiredCertNames?.length) {
|
||||
certList.value = mergeCertListWithRequiredSlots(certList.value, props.requiredCertNames, {
|
||||
vehiclePart: props.requiredVehiclePart
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function handleVehiclePartChange(row: CertRowWithKey, value: string) {
|
||||
if (isRowRequired(row)) return
|
||||
row.vehiclePart = normalizeVehicleCertPart(value)
|
||||
}
|
||||
|
||||
const certList = defineModel<CertRowWithKey[]>('modelValue', { default: () => [] })
|
||||
|
||||
watch(
|
||||
() =>
|
||||
[
|
||||
props.enforceSelfVehicleRequired,
|
||||
props.enforceCarrierVehicleRequired,
|
||||
props.requiredCertNames,
|
||||
props.trailerNo
|
||||
] as const,
|
||||
() => {
|
||||
if (hasRequiredMode.value) {
|
||||
syncRequiredSlots()
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const certUploadRefs = ref<Record<number, CertUploadRef | null>>({})
|
||||
|
||||
function createEmptyCert(): CertRowWithKey {
|
||||
return {
|
||||
_key: `cert-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
||||
vehiclePart: PL_VEHICLE_CERT_PART_HEAD,
|
||||
vehiclePart: props.requiredVehiclePart || PL_VEHICLE_CERT_PART_HEAD,
|
||||
certName: '',
|
||||
certNo: '',
|
||||
expireDate: '',
|
||||
remindDays: 30,
|
||||
attachmentUrls: ''
|
||||
attachmentUrls: '',
|
||||
_required: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +336,8 @@ function handleAddCert() {
|
||||
}
|
||||
|
||||
function handleRemoveCert(index: number) {
|
||||
const row = certList.value[index]
|
||||
if (row && isRowRequired(row)) return
|
||||
const next = [...certList.value]
|
||||
next.splice(index, 1)
|
||||
certList.value = next
|
||||
@@ -250,7 +360,11 @@ function clearUploadRefs() {
|
||||
certUploadRefs.value = {}
|
||||
}
|
||||
|
||||
defineExpose({ hasUploading, clearUploadRefs })
|
||||
function refreshRequiredSlots() {
|
||||
syncRequiredSlots()
|
||||
}
|
||||
|
||||
defineExpose({ hasUploading, clearUploadRefs, refreshRequiredSlots })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -282,6 +396,14 @@ defineExpose({ hasUploading, clearUploadRefs })
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.cert-name-locked {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-weight: 500;
|
||||
color: var(--text, #1e293b);
|
||||
}
|
||||
|
||||
.cert-form-table {
|
||||
border-top: 1px solid var(--mint-border, #d9e8e2);
|
||||
|
||||
|
||||
@@ -26,61 +26,67 @@
|
||||
</section>
|
||||
|
||||
<section class="pl-plan-form-section pl-plan-freight-section">
|
||||
<h4 class="pl-plan-subtitle">运费信息</h4>
|
||||
<div class="pl-plan-freight-section-head">
|
||||
<h4 class="pl-plan-subtitle">运费信息</h4>
|
||||
<label class="pl-plan-freight-switch">
|
||||
<span class="pl-plan-freight-switch-label">是否有运输费用</span>
|
||||
<el-switch v-model="formData.hasFreight" :active-value="1" :inactive-value="0" />
|
||||
</label>
|
||||
</div>
|
||||
<el-form
|
||||
v-if="formData.hasFreight === 1"
|
||||
:model="formData"
|
||||
label-width="140px"
|
||||
label-position="right"
|
||||
class="pl-plan-freight-form"
|
||||
>
|
||||
<div class="form-grid-4">
|
||||
<el-form-item label="是否有运输费用">
|
||||
<el-switch v-model="formData.hasFreight" :active-value="1" :inactive-value="0" />
|
||||
<div class="form-grid-4 pl-plan-archive-freight-grid">
|
||||
<el-form-item label="运费计算方式">
|
||||
<el-select v-model="formData.freightType">
|
||||
<el-option label="按重量" value="by_weight" />
|
||||
<el-option label="按趟" value="by_trip" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="运输公里数">
|
||||
<el-input-number
|
||||
v-model="formData.distanceKm"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.freightType === 'by_weight'"
|
||||
:label="`运输量(${freightUnitLabel})`"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="freightCalc.transportQty.value"
|
||||
:min="0"
|
||||
:precision="3"
|
||||
@change="freightCalc.markTransportQtyTouched()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-else class="pl-plan-archive-freight-grid-cell" aria-hidden="true" />
|
||||
|
||||
<div class="pl-plan-archive-freight-grid-cell" aria-hidden="true" />
|
||||
<el-form-item
|
||||
v-if="formData.freightType === 'by_weight'"
|
||||
:label="`运输单价(元/${freightUnitLabel})`"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="freightCalc.freightPrice.value"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-else class="pl-plan-archive-freight-grid-cell" aria-hidden="true" />
|
||||
<el-form-item label="运费金额(元)">
|
||||
<el-input-number
|
||||
v-model="freightCalc.freightAmount.value"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
@change="freightCalc.markFreightAmountTouched()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template v-if="formData.hasFreight === 1">
|
||||
<el-form-item label="运输公里数">
|
||||
<el-input-number
|
||||
v-model="formData.distanceKm"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="运费计算方式">
|
||||
<el-select v-model="formData.freightType">
|
||||
<el-option label="按重量" value="by_weight" />
|
||||
<el-option label="按趟" value="by_trip" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.freightType === 'by_weight'"
|
||||
:label="`运输量(${freightUnitLabel})`"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="freightCalc.transportQty.value"
|
||||
:min="0"
|
||||
:precision="3"
|
||||
@change="freightCalc.markTransportQtyTouched()"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.freightType === 'by_weight'"
|
||||
:label="`运输单价(元/${freightUnitLabel})`"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="freightCalc.freightPrice.value"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="运费金额(元)">
|
||||
<el-input-number
|
||||
v-model="freightCalc.freightAmount.value"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
@change="freightCalc.markFreightAmountTouched()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
</el-form>
|
||||
</section>
|
||||
@@ -119,7 +125,10 @@ import {
|
||||
import PlPlanFormProductTable from '@/components/business/pl-plan-form-dialog/PlPlanFormProductTable.vue'
|
||||
import PlPlanViewTabs from '@/components/business/pl-plan-view-tabs/index.vue'
|
||||
import type { PlanFormProductRow } from '@/composables/usePlContractToPlan'
|
||||
import { enrichPlanProductsHazardFromCrm } from '@/composables/usePlToxicProductCertCheck'
|
||||
import {
|
||||
buildMissingHazardCertReadyMessage,
|
||||
enrichPlanProductsHazardFromCrm
|
||||
} from '@/composables/usePlToxicProductCertCheck'
|
||||
import { usePlFreightCalc, resolveFreightUnitLabel } from '@/composables/usePlFreightCalc'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { pickBxData } from '@/utils/http/bx'
|
||||
@@ -302,6 +311,16 @@ async function handleSubmit() {
|
||||
return
|
||||
}
|
||||
|
||||
if (!isAdjustMode.value) {
|
||||
const certMessage = buildMissingHazardCertReadyMessage(plan.value, productRows.value)
|
||||
if (certMessage) {
|
||||
await ElMessageBox.alert(`${certMessage},请至【危化品证上传】页面操作。`, '无法归档', {
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const body: PlanArchiveBody = {
|
||||
@@ -392,6 +411,7 @@ async function handleSubmit() {
|
||||
.pl-plan-freight-section {
|
||||
.pl-plan-subtitle {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
@@ -400,6 +420,28 @@ async function handleSubmit() {
|
||||
}
|
||||
}
|
||||
|
||||
.pl-plan-freight-section-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.pl-plan-freight-switch {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pl-plan-freight-switch-label {
|
||||
font-size: 13px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pl-plan-freight-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
@@ -418,8 +460,13 @@ async function handleSubmit() {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.form-grid-4 {
|
||||
.pl-plan-archive-freight-grid {
|
||||
align-items: center;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
.pl-plan-archive-freight-grid-cell {
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
:deep(.el-select),
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
show-vehicle-part-column
|
||||
:license-plate="licensePlate"
|
||||
:trailer-no="trailerNo"
|
||||
:enforce-self-vehicle-required="enforceSelfVehicleRequired"
|
||||
:enforce-carrier-vehicle-required="enforceCarrierVehicleRequired"
|
||||
/>
|
||||
|
||||
<el-tabs
|
||||
@@ -73,13 +75,19 @@ const props = withDefaults(
|
||||
certNameOptions?: string[]
|
||||
title?: string
|
||||
layout?: 'card' | 'table'
|
||||
/** 山峡自有车:注入必备证书槽位并校验 */
|
||||
enforceSelfVehicleRequired?: boolean
|
||||
/** 承运商车辆:注入必备证书槽位并校验 */
|
||||
enforceCarrierVehicleRequired?: boolean
|
||||
}>(),
|
||||
{
|
||||
licensePlate: '',
|
||||
trailerNo: '',
|
||||
certNameOptions: () => [],
|
||||
title: '车辆证书',
|
||||
layout: 'card'
|
||||
layout: 'card',
|
||||
enforceSelfVehicleRequired: false,
|
||||
enforceCarrierVehicleRequired: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -149,9 +157,16 @@ function clearUploadRefs() {
|
||||
trailerCertFormRef.value?.clearUploadRefs()
|
||||
}
|
||||
|
||||
function refreshRequiredSlots() {
|
||||
unifiedCertFormRef.value?.refreshRequiredSlots?.()
|
||||
headCertFormRef.value?.refreshRequiredSlots?.()
|
||||
trailerCertFormRef.value?.refreshRequiredSlots?.()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
hasUploading,
|
||||
clearUploadRefs
|
||||
clearUploadRefs,
|
||||
refreshRequiredSlots
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -46,7 +46,8 @@ import type { ViewTableMode } from '@/components/business/system-view-dialog/typ
|
||||
import {
|
||||
PL_VEHICLE_CERT_PART_HEAD,
|
||||
PL_VEHICLE_CERT_PART_TRAILER,
|
||||
getSelfVehiclePartCertMissingSuffix,
|
||||
getVehiclePartCertMissingSuffix,
|
||||
type PlVehicleCertCheckType,
|
||||
splitVehicleCertsByPart
|
||||
} from '@/utils/pl-vehicle-cert'
|
||||
|
||||
@@ -56,6 +57,8 @@ const props = withDefaults(
|
||||
licensePlate?: string
|
||||
trailerNo?: string
|
||||
vehicleId?: string
|
||||
vehicleCertCheckType?: PlVehicleCertCheckType
|
||||
/** @deprecated 使用 vehicleCertCheckType */
|
||||
checkSelfVehicleCerts?: boolean
|
||||
tableMode?: ViewTableMode
|
||||
certLayout?: 'card' | 'table'
|
||||
@@ -65,6 +68,7 @@ const props = withDefaults(
|
||||
licensePlate: '',
|
||||
trailerNo: '',
|
||||
vehicleId: '',
|
||||
vehicleCertCheckType: undefined,
|
||||
checkSelfVehicleCerts: false,
|
||||
tableMode: 'triple',
|
||||
certLayout: 'card'
|
||||
@@ -98,16 +102,26 @@ const scopedCertList = computed(() => {
|
||||
const headCertList = computed(() => splitVehicleCertsByPart(scopedCertList.value).headCerts)
|
||||
const trailerCertList = computed(() => splitVehicleCertsByPart(scopedCertList.value).trailerCerts)
|
||||
|
||||
const resolvedVehicleCertCheckType = computed<PlVehicleCertCheckType | undefined>(() => {
|
||||
if (props.vehicleCertCheckType) return props.vehicleCertCheckType
|
||||
return props.checkSelfVehicleCerts ? 'self' : undefined
|
||||
})
|
||||
|
||||
const headTabLabelWithHint = computed(() => {
|
||||
if (!props.checkSelfVehicleCerts) return headTabLabel.value
|
||||
return headTabLabel.value + getSelfVehiclePartCertMissingSuffix(headCertList.value, PL_VEHICLE_CERT_PART_HEAD)
|
||||
const checkType = resolvedVehicleCertCheckType.value
|
||||
if (!checkType) return headTabLabel.value
|
||||
return (
|
||||
headTabLabel.value +
|
||||
getVehiclePartCertMissingSuffix(headCertList.value, PL_VEHICLE_CERT_PART_HEAD, checkType)
|
||||
)
|
||||
})
|
||||
|
||||
const trailerTabLabelWithHint = computed(() => {
|
||||
if (!props.checkSelfVehicleCerts) return trailerTabLabel.value
|
||||
const checkType = resolvedVehicleCertCheckType.value
|
||||
if (!checkType) return trailerTabLabel.value
|
||||
return (
|
||||
trailerTabLabel.value +
|
||||
getSelfVehiclePartCertMissingSuffix(trailerCertList.value, PL_VEHICLE_CERT_PART_TRAILER)
|
||||
getVehiclePartCertMissingSuffix(trailerCertList.value, PL_VEHICLE_CERT_PART_TRAILER, checkType)
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
:license-plate="licensePlate"
|
||||
:trailer-no="trailerNo"
|
||||
:vehicle-id="vehicleId"
|
||||
:check-self-vehicle-certs="checkSelfVehicleCerts"
|
||||
:vehicle-cert-check-type="vehicleCertCheckType"
|
||||
:table-mode="tableMode"
|
||||
:cert-layout="certLayout"
|
||||
/>
|
||||
@@ -20,7 +20,7 @@
|
||||
>
|
||||
<PersonnelViewPanel
|
||||
:person="person"
|
||||
:check-self-vehicle-certs="checkSelfVehicleCerts"
|
||||
:check-linked-personnel-certs="showLinkedPersonnelCertCheck"
|
||||
:table-mode="tableMode"
|
||||
:cert-layout="certLayout"
|
||||
/>
|
||||
@@ -34,7 +34,7 @@ import PersonnelViewPanel from '@/components/business/pl-vehicle-personnel-view-
|
||||
import type { CertRead } from '@/api/pl'
|
||||
import type { VehiclePersonnelViewRow } from '@/components/business/pl-vehicle-personnel-view-list/index.vue'
|
||||
import type { ViewTableMode } from '@/components/business/system-view-dialog/types'
|
||||
import { getSelfVehicleCertMissingSuffix } from '@/utils/pl-vehicle-cert'
|
||||
import { getVehicleCertMissingSuffix, type PlVehicleCertCheckType } from '@/utils/pl-vehicle-cert'
|
||||
import { getPersonnelCertMissingSuffix } from '@/utils/pl-personnel-cert'
|
||||
import { formatPlPersonnelNameWithRole } from '@/utils/pl-display'
|
||||
|
||||
@@ -45,6 +45,10 @@ const props = withDefaults(
|
||||
trailerNo?: string
|
||||
vehicleId?: string
|
||||
personnelList?: VehiclePersonnelViewRow[]
|
||||
vehicleCertCheckType?: PlVehicleCertCheckType
|
||||
/** 山峡自有车:关联人员证书缺失提示 */
|
||||
checkLinkedPersonnelCerts?: boolean
|
||||
/** @deprecated 使用 vehicleCertCheckType + checkLinkedPersonnelCerts */
|
||||
checkSelfVehicleCerts?: boolean
|
||||
tableMode?: ViewTableMode
|
||||
certLayout?: 'card' | 'table'
|
||||
@@ -55,6 +59,8 @@ const props = withDefaults(
|
||||
trailerNo: '',
|
||||
vehicleId: '',
|
||||
personnelList: () => [],
|
||||
vehicleCertCheckType: undefined,
|
||||
checkLinkedPersonnelCerts: false,
|
||||
checkSelfVehicleCerts: false,
|
||||
tableMode: 'triple',
|
||||
certLayout: 'card'
|
||||
@@ -73,23 +79,29 @@ const tabsInstanceKey = computed(
|
||||
|
||||
const vehicleCertTabLabel = computed(() => {
|
||||
const label = '车辆证书'
|
||||
if (!props.checkSelfVehicleCerts) return label
|
||||
const checkType = props.vehicleCertCheckType
|
||||
if (!checkType) return label
|
||||
return (
|
||||
label +
|
||||
getSelfVehicleCertMissingSuffix({
|
||||
getVehicleCertMissingSuffix({
|
||||
vehicleType: checkType,
|
||||
certList: props.certList,
|
||||
trailerNo: props.trailerNo
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
const showLinkedPersonnelCertCheck = computed(
|
||||
() => props.checkLinkedPersonnelCerts || props.checkSelfVehicleCerts
|
||||
)
|
||||
|
||||
function getPersonKey(person: VehiclePersonnelViewRow, index: number) {
|
||||
return `person-${props.vehicleId || props.licensePlate || 'vehicle'}-${person.personnelId || `${person.personnelName}-${index}`}`
|
||||
}
|
||||
|
||||
function getPersonTabLabel(person: VehiclePersonnelViewRow) {
|
||||
const suffix =
|
||||
props.checkSelfVehicleCerts && person.role
|
||||
showLinkedPersonnelCertCheck.value && person.role
|
||||
? getPersonnelCertMissingSuffix(person.certList || [], person.role as 'driver' | 'escort')
|
||||
: ''
|
||||
return `${formatPlPersonnelNameWithRole(person.personnelName, person.role)}${suffix}`
|
||||
|
||||
+8
-1
@@ -38,19 +38,26 @@ const props = withDefaults(
|
||||
person: VehiclePersonnelViewRow
|
||||
showTitle?: boolean
|
||||
checkSelfVehicleCerts?: boolean
|
||||
/** @deprecated 使用 checkLinkedPersonnelCerts */
|
||||
checkLinkedPersonnelCerts?: boolean
|
||||
tableMode?: ViewTableMode
|
||||
certLayout?: 'card' | 'table'
|
||||
}>(),
|
||||
{
|
||||
showTitle: false,
|
||||
checkSelfVehicleCerts: false,
|
||||
checkLinkedPersonnelCerts: false,
|
||||
tableMode: 'triple',
|
||||
certLayout: 'card'
|
||||
}
|
||||
)
|
||||
|
||||
const showPersonnelCertCheck = computed(
|
||||
() => props.checkLinkedPersonnelCerts || props.checkSelfVehicleCerts
|
||||
)
|
||||
|
||||
const personnelCertMissingSuffix = computed(() => {
|
||||
if (!props.checkSelfVehicleCerts || !props.person.role) return ''
|
||||
if (!showPersonnelCertCheck.value || !props.person.role) return ''
|
||||
return getPersonnelCertMissingSuffix(
|
||||
props.person.certList || [],
|
||||
props.person.role as 'driver' | 'escort'
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
:trailer-no="detail?.trailerNo"
|
||||
:vehicle-id="detail?.id"
|
||||
:personnel-list="personnelList"
|
||||
:check-self-vehicle-certs="detail?.vehicleType === 'self'"
|
||||
:vehicle-cert-check-type="detail?.vehicleType === 'self' || detail?.vehicleType === 'carrier' ? detail.vehicleType : undefined"
|
||||
:check-linked-personnel-certs="detail?.vehicleType === 'self'"
|
||||
cert-layout="table"
|
||||
/>
|
||||
</template>
|
||||
|
||||
Reference in new issue
Block a user