提交
This commit is contained in:
1 parent
c2cba3e668
commit
2142b33cfa
24 files changed
+4834
-3684
No files matched your search
@@ -99,6 +99,7 @@ export interface Vehicle {
|
||||
loadCapacity?: number
|
||||
vehicleStatus: string
|
||||
remark?: string
|
||||
certList?: CertRead[]
|
||||
createTime: string
|
||||
}
|
||||
|
||||
@@ -152,6 +153,7 @@ export interface Personnel {
|
||||
status: string
|
||||
remark?: string
|
||||
nearestExpireDate?: string
|
||||
certList?: CertRead[]
|
||||
createTime: string
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,13 @@
|
||||
|
||||
<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
|
||||
v-else-if="layout === 'table'"
|
||||
:data="certList"
|
||||
stripe
|
||||
class="list-table cert-form-table"
|
||||
:row-class-name="showVehiclePartColumn ? getCertRowClassName : undefined"
|
||||
>
|
||||
<el-table-column type="index" label="序号" min-width="68" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
v-if="showVehiclePartColumn"
|
||||
@@ -298,6 +304,13 @@ function handleVehiclePartChange(row: CertRowWithKey, value: string) {
|
||||
row.vehiclePart = normalizeVehicleCertPart(value)
|
||||
}
|
||||
|
||||
function getCertRowClassName({ row }: { row: CertRowWithKey }) {
|
||||
if (!props.showVehiclePartColumn) return ''
|
||||
return normalizeVehicleCertPart(row.vehiclePart) === PL_VEHICLE_CERT_PART_TRAILER
|
||||
? 'cert-row-trailer'
|
||||
: 'cert-row-head'
|
||||
}
|
||||
|
||||
const certList = defineModel<CertRowWithKey[]>('modelValue', { default: () => [] })
|
||||
|
||||
watch(
|
||||
@@ -407,6 +420,14 @@ defineExpose({ hasUploading, clearUploadRefs, refreshRequiredSlots })
|
||||
.cert-form-table {
|
||||
border-top: 1px solid var(--mint-border, #d9e8e2);
|
||||
|
||||
:deep(.cert-row-head td.el-table__cell) {
|
||||
background-color: #ecfdf5 !important;
|
||||
}
|
||||
|
||||
:deep(.cert-row-trailer td.el-table__cell) {
|
||||
background-color: #fffbeb !important;
|
||||
}
|
||||
|
||||
:deep(.el-select),
|
||||
:deep(.el-input),
|
||||
:deep(.el-date-editor) {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div v-if="badges.length" class="pl-personnel-cert-badges">
|
||||
<el-tooltip
|
||||
v-for="badge in badges"
|
||||
:key="badge.requiredName"
|
||||
:content="badge.title"
|
||||
placement="top"
|
||||
>
|
||||
<span
|
||||
class="pl-personnel-cert-badges__item"
|
||||
:class="`pl-personnel-cert-badges__item--${badge.status}`"
|
||||
>
|
||||
{{ badge.shortLabel }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { CertRead } from '@/api/pl'
|
||||
import { getPersonnelRequiredCertBadges } from '@/utils/pl-personnel-cert'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
personnelType?: string | null
|
||||
certList?: CertRead[]
|
||||
}>(),
|
||||
{
|
||||
personnelType: '',
|
||||
certList: () => []
|
||||
}
|
||||
)
|
||||
|
||||
const badges = computed(() =>
|
||||
getPersonnelRequiredCertBadges(props.personnelType, props.certList || [])
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pl-personnel-cert-badges {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.pl-personnel-cert-badges__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pl-personnel-cert-badges__item--missing {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.pl-personnel-cert-badges__item--valid {
|
||||
background: #ecfdf5;
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.pl-personnel-cert-badges__item--expiring {
|
||||
background: #fffbeb;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.pl-personnel-cert-badges__item--expired {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<span v-if="badgeGroups.length" class="pl-vehicle-cert-badges">
|
||||
<span class="pl-vehicle-cert-badges__paren">(</span>
|
||||
<template v-for="(group, groupIndex) in badgeGroups" :key="group.key">
|
||||
<span v-if="groupIndex > 0" class="pl-vehicle-cert-badges__divider">|</span>
|
||||
<span class="pl-vehicle-cert-badges__group">
|
||||
<el-tooltip
|
||||
v-for="badge in group.badges"
|
||||
:key="`${group.key}-${badge.requiredName}`"
|
||||
:content="badge.title"
|
||||
placement="top"
|
||||
>
|
||||
<span
|
||||
class="pl-vehicle-cert-badges__item"
|
||||
:class="`pl-vehicle-cert-badges__item--${badge.status}`"
|
||||
>
|
||||
{{ badge.shortLabel }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<span class="pl-vehicle-cert-badges__paren">)</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { CertRead } from '@/api/pl'
|
||||
import {
|
||||
PL_VEHICLE_CERT_PART_HEAD,
|
||||
PL_VEHICLE_CERT_PART_TRAILER,
|
||||
getVehiclePartRequiredCertBadges,
|
||||
type PlVehicleCertCheckType
|
||||
} from '@/utils/pl-vehicle-cert'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
vehicleType?: PlVehicleCertCheckType
|
||||
certList?: CertRead[]
|
||||
trailerNo?: string | null
|
||||
}>(),
|
||||
{
|
||||
vehicleType: 'self',
|
||||
certList: () => [],
|
||||
trailerNo: ''
|
||||
}
|
||||
)
|
||||
|
||||
const hasTrailer = computed(() => Boolean(props.trailerNo?.trim()))
|
||||
|
||||
const badgeGroups = computed(() => {
|
||||
const groups = [
|
||||
{
|
||||
key: PL_VEHICLE_CERT_PART_HEAD,
|
||||
badges: getVehiclePartRequiredCertBadges({
|
||||
vehicleType: props.vehicleType,
|
||||
certList: props.certList || [],
|
||||
part: PL_VEHICLE_CERT_PART_HEAD,
|
||||
partLabel: hasTrailer.value ? '主车' : ''
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
if (hasTrailer.value) {
|
||||
groups.push({
|
||||
key: PL_VEHICLE_CERT_PART_TRAILER,
|
||||
badges: getVehiclePartRequiredCertBadges({
|
||||
vehicleType: props.vehicleType,
|
||||
certList: props.certList || [],
|
||||
part: PL_VEHICLE_CERT_PART_TRAILER,
|
||||
partLabel: '挂车'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return groups
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pl-vehicle-cert-badges {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__paren,
|
||||
.pl-vehicle-cert-badges__divider {
|
||||
font-size: 12px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__group {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__item--missing {
|
||||
background: #f1f5f9;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__item--valid {
|
||||
background: #ecfdf5;
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__item--expiring {
|
||||
background: #fffbeb;
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.pl-vehicle-cert-badges__item--expired {
|
||||
background: #fef2f2;
|
||||
color: #dc2626;
|
||||
}
|
||||
</style>
|
||||
@@ -72,6 +72,16 @@ export function getRequiredPersonnelCertNamesByType(
|
||||
return PL_PERSONNEL_DRIVER_REQUIRED_CERT_NAMES
|
||||
}
|
||||
|
||||
/** 车辆关联人员:从人员主数据类型映射为关联角色(司机/押运员) */
|
||||
export function mapPersonnelTypeToVehicleRole(
|
||||
personnelType?: string | null
|
||||
): 'driver' | 'escort' | undefined {
|
||||
if (personnelType === 'driver') return 'driver'
|
||||
if (personnelType === 'escort') return 'escort'
|
||||
if (personnelType === 'both') return 'driver'
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function validatePersonnelTypeRoleCompat(
|
||||
personnelType: string | undefined,
|
||||
role: string | undefined,
|
||||
@@ -176,3 +186,102 @@ export function getPersonnelCertMissingSuffix(
|
||||
}
|
||||
return hasPersonnelMasterCertMissing(certList) ? PL_PERSONNEL_CERT_MISSING_SUFFIX : ''
|
||||
}
|
||||
|
||||
export const PL_PERSONNEL_CERT_SHORT_LABELS: Record<string, string> = {
|
||||
身份证: '身',
|
||||
驾驶证: '驾',
|
||||
从业资格证: '业'
|
||||
}
|
||||
|
||||
export type PersonnelCertBadgeStatus = 'missing' | 'valid' | 'expiring' | 'expired'
|
||||
|
||||
export interface PersonnelCertBadgeItem {
|
||||
requiredName: string
|
||||
shortLabel: string
|
||||
status: PersonnelCertBadgeStatus
|
||||
title: string
|
||||
}
|
||||
|
||||
function getPersonnelCertMissingFieldLabels(
|
||||
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'> | undefined,
|
||||
requiredName: string
|
||||
): string[] {
|
||||
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
|
||||
return ['证号', '有效期', '附件']
|
||||
}
|
||||
const missing: string[] = []
|
||||
if (!cert.certNo?.trim()) missing.push('证号')
|
||||
if (!cert.expireDate) missing.push('有效期')
|
||||
if (!cert.attachmentUrls?.trim()) missing.push('附件')
|
||||
return missing
|
||||
}
|
||||
|
||||
function formatPersonnelCertBadgeTooltip(
|
||||
requiredName: string,
|
||||
status: PersonnelCertBadgeStatus,
|
||||
cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'>
|
||||
): string {
|
||||
if (status === 'missing') {
|
||||
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
|
||||
return `${requiredName}:缺失(未登记该证书)`
|
||||
}
|
||||
const missing = getPersonnelCertMissingFieldLabels(cert, requiredName)
|
||||
return `${requiredName}:缺失(缺少${missing.join('、')})`
|
||||
}
|
||||
|
||||
const expireDate = cert?.expireDate || '—'
|
||||
const expDate = new Date(expireDate)
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
expDate.setHours(0, 0, 0, 0)
|
||||
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
|
||||
const certNo = cert?.certNo?.trim()
|
||||
const certNoText = certNo ? `,证号 ${certNo}` : ''
|
||||
|
||||
if (status === 'expired') {
|
||||
return `${requiredName}:已过期,有效期 ${expireDate},已过期 ${Math.abs(diffDays)} 天${certNoText}`
|
||||
}
|
||||
if (status === 'expiring') {
|
||||
return `${requiredName}:临期,有效期 ${expireDate},剩余 ${diffDays} 天${certNoText}`
|
||||
}
|
||||
return `${requiredName}:正常,有效期 ${expireDate}${certNoText}`
|
||||
}
|
||||
|
||||
export function getPersonnelCertBadgeStatus(
|
||||
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'> | undefined,
|
||||
requiredName: string
|
||||
): PersonnelCertBadgeStatus {
|
||||
if (!isPersonnelCertStrictComplete(cert, requiredName)) {
|
||||
return 'missing'
|
||||
}
|
||||
const expireDate = cert?.expireDate
|
||||
if (!expireDate) return 'missing'
|
||||
|
||||
const remindDays = cert?.remindDays ?? 30
|
||||
const expDate = new Date(expireDate)
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
expDate.setHours(0, 0, 0, 0)
|
||||
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (diffDays <= 0) return 'expired'
|
||||
if (diffDays <= remindDays) return 'expiring'
|
||||
return 'valid'
|
||||
}
|
||||
|
||||
export function getPersonnelRequiredCertBadges(
|
||||
personnelType: string | null | undefined,
|
||||
certList: CertRow[] = []
|
||||
): PersonnelCertBadgeItem[] {
|
||||
return getRequiredPersonnelCertNamesByType(personnelType).map(requiredName => {
|
||||
const matched = certList.find(cert => matchRequiredCertName(cert.certName, requiredName))
|
||||
const status = getPersonnelCertBadgeStatus(matched, requiredName)
|
||||
const shortLabel = PL_PERSONNEL_CERT_SHORT_LABELS[requiredName] || requiredName.slice(0, 1)
|
||||
return {
|
||||
requiredName,
|
||||
shortLabel,
|
||||
status,
|
||||
title: formatPersonnelCertBadgeTooltip(requiredName, status, matched)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -235,3 +235,124 @@ export function validateVehicleCertNamesNotEmpty(
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export const PL_VEHICLE_CERT_SHORT_LABELS: Record<string, string> = {
|
||||
行驶证: '行',
|
||||
营运证: '营',
|
||||
保险单: '保',
|
||||
罐检报告: '罐'
|
||||
}
|
||||
|
||||
export type VehicleCertBadgeStatus = 'missing' | 'valid' | 'expiring' | 'expired'
|
||||
|
||||
export interface VehicleCertBadgeItem {
|
||||
requiredName: string
|
||||
shortLabel: string
|
||||
status: VehicleCertBadgeStatus
|
||||
title: string
|
||||
}
|
||||
|
||||
function matchVehicleRequiredCertName(
|
||||
actualName: string | undefined,
|
||||
requiredName: string
|
||||
): boolean {
|
||||
return (actualName?.trim() || '') === requiredName
|
||||
}
|
||||
|
||||
function getVehicleCertMissingFieldLabels(
|
||||
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'> | undefined,
|
||||
requiredName: string
|
||||
): string[] {
|
||||
if (!cert || !matchVehicleRequiredCertName(cert.certName, requiredName)) {
|
||||
return ['证号', '有效期', '附件']
|
||||
}
|
||||
const missing: string[] = []
|
||||
if (!cert.certNo?.trim()) missing.push('证号')
|
||||
if (!cert.expireDate) missing.push('有效期')
|
||||
if (!cert.attachmentUrls?.trim()) missing.push('附件')
|
||||
return missing
|
||||
}
|
||||
|
||||
function formatVehicleCertBadgeTooltip(
|
||||
partLabel: string,
|
||||
requiredName: string,
|
||||
status: VehicleCertBadgeStatus,
|
||||
cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'>
|
||||
): string {
|
||||
const prefix = partLabel ? `${partLabel} · ` : ''
|
||||
if (status === 'missing') {
|
||||
if (!cert || !matchVehicleRequiredCertName(cert.certName, requiredName)) {
|
||||
return `${prefix}${requiredName}:缺失(未登记该证书)`
|
||||
}
|
||||
const missing = getVehicleCertMissingFieldLabels(cert, requiredName)
|
||||
return `${prefix}${requiredName}:缺失(缺少${missing.join('、')})`
|
||||
}
|
||||
|
||||
const expireDate = cert?.expireDate || '—'
|
||||
const expDate = new Date(expireDate)
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
expDate.setHours(0, 0, 0, 0)
|
||||
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
|
||||
const certNo = cert?.certNo?.trim()
|
||||
const certNoText = certNo ? `,证号 ${certNo}` : ''
|
||||
|
||||
if (status === 'expired') {
|
||||
return `${prefix}${requiredName}:已过期,有效期 ${expireDate},已过期 ${Math.abs(diffDays)} 天${certNoText}`
|
||||
}
|
||||
if (status === 'expiring') {
|
||||
return `${prefix}${requiredName}:临期,有效期 ${expireDate},剩余 ${diffDays} 天${certNoText}`
|
||||
}
|
||||
return `${prefix}${requiredName}:正常,有效期 ${expireDate}${certNoText}`
|
||||
}
|
||||
|
||||
export function getVehicleCertBadgeStatus(
|
||||
cert: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls' | 'remindDays'> | undefined,
|
||||
requiredName: string
|
||||
): VehicleCertBadgeStatus {
|
||||
if (!isVehicleCertUploaded(cert) || !matchVehicleRequiredCertName(cert?.certName, requiredName)) {
|
||||
return 'missing'
|
||||
}
|
||||
const expireDate = cert?.expireDate
|
||||
if (!expireDate) return 'missing'
|
||||
|
||||
const remindDays = cert?.remindDays ?? 30
|
||||
const expDate = new Date(expireDate)
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
expDate.setHours(0, 0, 0, 0)
|
||||
const diffDays = Math.ceil((expDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
|
||||
|
||||
if (diffDays <= 0) return 'expired'
|
||||
if (diffDays <= remindDays) return 'expiring'
|
||||
return 'valid'
|
||||
}
|
||||
|
||||
export function getVehiclePartRequiredCertBadges(options: {
|
||||
vehicleType: PlVehicleCertCheckType
|
||||
certList?: CertRow[]
|
||||
part: VehicleCertPart
|
||||
partLabel?: string
|
||||
}): VehicleCertBadgeItem[] {
|
||||
const { vehicleType, certList = [], part, partLabel = '' } = options
|
||||
const partCerts =
|
||||
part === PL_VEHICLE_CERT_PART_TRAILER
|
||||
? splitVehicleCertsByPart(certList).trailerCerts
|
||||
: splitVehicleCertsByPart(certList).headCerts
|
||||
const requiredNames =
|
||||
part === PL_VEHICLE_CERT_PART_TRAILER
|
||||
? getVehicleTrailerRequiredCertNames(vehicleType)
|
||||
: getVehicleHeadRequiredCertNames(vehicleType)
|
||||
|
||||
return requiredNames.map(requiredName => {
|
||||
const matched = partCerts.find(cert => matchVehicleRequiredCertName(cert.certName, requiredName))
|
||||
const status = getVehicleCertBadgeStatus(matched, requiredName)
|
||||
const shortLabel = PL_VEHICLE_CERT_SHORT_LABELS[requiredName] || requiredName.slice(0, 1)
|
||||
return {
|
||||
requiredName,
|
||||
shortLabel,
|
||||
status,
|
||||
title: formatVehicleCertBadgeTooltip(partLabel, requiredName, status, matched)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -182,7 +182,7 @@
|
||||
<el-tag v-else-if="row.qualificationComplete === false" type="warning" size="small">
|
||||
资质不全
|
||||
</el-tag>
|
||||
<span v-else>—</span>
|
||||
<el-tag v-else type="success" size="small">资质齐全</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
|
||||
@@ -114,12 +114,18 @@
|
||||
<el-table-column
|
||||
prop="personnelName"
|
||||
label="姓名"
|
||||
min-width="100"
|
||||
min-width="160"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="handleView(row)">{{ row.personnelName }}</el-link>
|
||||
<div class="personnel-name-cell">
|
||||
<el-link type="primary" @click="handleView(row)">{{ row.personnelName }}</el-link>
|
||||
<PlPersonnelCertBadges
|
||||
:personnel-type="row.personnelType"
|
||||
:cert-list="row.certList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -357,6 +363,7 @@ import { Check, Close, Delete, Edit, Plus, RefreshLeft, Search, User } from '@el
|
||||
import { personnelApi, type Personnel, type PersonnelDetail, type CertRow } from '@/api/pl'
|
||||
import PlCertFormList from '@/components/business/pl-cert-form-list/index.vue'
|
||||
import PlCertViewList from '@/components/business/pl-cert-view-list/index.vue'
|
||||
import PlPersonnelCertBadges from '@/components/business/pl-personnel-cert-badges/index.vue'
|
||||
import SystemViewDialog, {
|
||||
type ViewSection
|
||||
} from '@/components/business/system-view-dialog/index.vue'
|
||||
@@ -824,4 +831,12 @@ onMounted(() => {
|
||||
.sub-table {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.personnel-name-cell {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -113,14 +113,21 @@
|
||||
<el-table-column
|
||||
prop="licensePlate"
|
||||
label="车牌号"
|
||||
min-width="120"
|
||||
min-width="340"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="handleView(row)">
|
||||
{{ formatPlVehiclePlateDisplay(row.licensePlate, row.trailerNo) }}
|
||||
</el-link>
|
||||
<div class="vehicle-plate-cell">
|
||||
<el-link type="primary" @click="handleView(row)">
|
||||
{{ formatPlVehiclePlateDisplay(row.licensePlate, row.trailerNo) }}
|
||||
</el-link>
|
||||
<PlVehicleCertBadges
|
||||
vehicle-type="self"
|
||||
:cert-list="row.certList"
|
||||
:trailer-no="row.trailerNo"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="车辆类型" min-width="90" align="center" header-align="center" v-if="isColumnVisible('vehicleType')">
|
||||
@@ -216,7 +223,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="承运商" prop="carrierId">
|
||||
<el-select v-model="formData.carrierId" placeholder="请选择承运商(选填)" clearable filterable>
|
||||
<el-select v-model="formData.carrierId" placeholder="请选择承运商" filterable>
|
||||
<el-option
|
||||
v-for="c in carrierList"
|
||||
:key="c.id"
|
||||
@@ -390,6 +397,7 @@ import {
|
||||
} from '@/api/pl'
|
||||
import PlVehicleCertPartTabs from '@/components/business/pl-vehicle-cert-part-tabs/index.vue'
|
||||
import PlVehicleCertPersonnelTabs from '@/components/business/pl-vehicle-cert-personnel-tabs/index.vue'
|
||||
import PlVehicleCertBadges from '@/components/business/pl-vehicle-cert-badges/index.vue'
|
||||
import type { VehiclePersonnelViewRow } from '@/components/business/pl-vehicle-personnel-view-list/index.vue'
|
||||
import SystemViewDialog, {
|
||||
type ViewSection
|
||||
@@ -414,7 +422,11 @@ import {
|
||||
PL_VEHICLE_CERT_NAME_OPTIONS,
|
||||
getSelfVehicleCertMissingSuffix
|
||||
} from '@/utils/pl-vehicle-cert'
|
||||
import { validatePersonnelTypeRoleCompat, validatePersonnelAffiliationVehicleCompat } from '@/utils/pl-personnel-cert'
|
||||
import {
|
||||
mapPersonnelTypeToVehicleRole,
|
||||
validatePersonnelTypeRoleCompat,
|
||||
validatePersonnelAffiliationVehicleCompat
|
||||
} from '@/utils/pl-personnel-cert'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
|
||||
const VEHICLE_TYPE_SELF = 'self'
|
||||
@@ -487,7 +499,8 @@ const formData = reactive({
|
||||
|
||||
const formRules = {
|
||||
licensePlate: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
|
||||
vehicleStatus: [{ required: true, message: '请选择车辆状态', trigger: 'change' }]
|
||||
vehicleStatus: [{ required: true, message: '请选择车辆状态', trigger: 'change' }],
|
||||
carrierId: [{ required: true, message: '请选择承运商', trigger: 'change' }]
|
||||
}
|
||||
|
||||
function getStatusTagType(status: string) {
|
||||
@@ -605,6 +618,7 @@ function handlePersonnelSelect(row: VehiclePersonnelRow, personnelId?: string) {
|
||||
row.personnelName = ''
|
||||
row.phoneNo = ''
|
||||
row.age = null
|
||||
row.role = ''
|
||||
return
|
||||
}
|
||||
const person = personnelOptions.value.find(p => p.id === personnelId)
|
||||
@@ -613,6 +627,11 @@ function handlePersonnelSelect(row: VehiclePersonnelRow, personnelId?: string) {
|
||||
row.personnelName = person.personnelName
|
||||
row.phoneNo = person.phoneNo || ''
|
||||
row.age = person.age ?? null
|
||||
const mappedRole = mapPersonnelTypeToVehicleRole(person.personnelType)
|
||||
if (mappedRole) {
|
||||
row.role = mappedRole
|
||||
handleRoleChange(row, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePersonnelRows(rows: VehiclePersonnelRow[]) {
|
||||
@@ -1002,4 +1021,13 @@ onMounted(() => {
|
||||
.sub-table {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.vehicle-plate-cell {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -121,14 +121,21 @@
|
||||
<el-table-column
|
||||
prop="licensePlate"
|
||||
label="车牌号"
|
||||
min-width="120"
|
||||
min-width="340"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="handleView(row)">
|
||||
{{ formatPlVehiclePlateDisplay(row.licensePlate, row.trailerNo) }}
|
||||
</el-link>
|
||||
<div class="vehicle-plate-cell">
|
||||
<el-link type="primary" @click="handleView(row)">
|
||||
{{ formatPlVehiclePlateDisplay(row.licensePlate, row.trailerNo) }}
|
||||
</el-link>
|
||||
<PlVehicleCertBadges
|
||||
:vehicle-type="row.vehicleType === 'carrier' ? 'carrier' : 'self'"
|
||||
:cert-list="row.certList"
|
||||
:trailer-no="row.trailerNo"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="车辆类型" min-width="100" align="center" header-align="center" v-if="isColumnVisible('vehicleType')">
|
||||
@@ -233,7 +240,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="承运商" prop="carrierId">
|
||||
<el-select v-model="formData.carrierId" placeholder="请选择承运商" clearable filterable>
|
||||
<el-select v-model="formData.carrierId" placeholder="请选择承运商" filterable>
|
||||
<el-option
|
||||
v-for="c in carrierList"
|
||||
:key="c.id"
|
||||
@@ -412,6 +419,7 @@ import {
|
||||
} from '@/api/pl'
|
||||
import PlVehicleCertPartTabs from '@/components/business/pl-vehicle-cert-part-tabs/index.vue'
|
||||
import PlVehicleCertPersonnelTabs from '@/components/business/pl-vehicle-cert-personnel-tabs/index.vue'
|
||||
import PlVehicleCertBadges from '@/components/business/pl-vehicle-cert-badges/index.vue'
|
||||
import type { VehiclePersonnelViewRow } from '@/components/business/pl-vehicle-personnel-view-list/index.vue'
|
||||
import SystemViewDialog, {
|
||||
type ViewSection
|
||||
@@ -432,7 +440,11 @@ import {
|
||||
getVehicleCertMissingSuffix,
|
||||
type PlVehicleCertCheckType
|
||||
} from '@/utils/pl-vehicle-cert'
|
||||
import { validatePersonnelTypeRoleCompat, validatePersonnelAffiliationVehicleCompat } from '@/utils/pl-personnel-cert'
|
||||
import {
|
||||
mapPersonnelTypeToVehicleRole,
|
||||
validatePersonnelTypeRoleCompat,
|
||||
validatePersonnelAffiliationVehicleCompat
|
||||
} from '@/utils/pl-personnel-cert'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
|
||||
type CertListItem = CertRow & { _key?: string }
|
||||
@@ -506,7 +518,8 @@ const formData = reactive({
|
||||
|
||||
const formRules = {
|
||||
licensePlate: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
|
||||
vehicleType: [{ required: true, message: '请选择车辆类型', trigger: 'change' }]
|
||||
vehicleType: [{ required: true, message: '请选择车辆类型', trigger: 'change' }],
|
||||
carrierId: [{ required: true, message: '请选择承运商', trigger: 'change' }]
|
||||
}
|
||||
|
||||
function getStatusTagType(status: string) {
|
||||
@@ -671,6 +684,7 @@ function handlePersonnelSelect(row: VehiclePersonnelRow, personnelId?: string) {
|
||||
row.personnelName = ''
|
||||
row.phoneNo = ''
|
||||
row.age = null
|
||||
row.role = ''
|
||||
return
|
||||
}
|
||||
const person = personnelOptions.value.find(p => p.id === personnelId)
|
||||
@@ -679,6 +693,11 @@ function handlePersonnelSelect(row: VehiclePersonnelRow, personnelId?: string) {
|
||||
row.personnelName = person.personnelName
|
||||
row.phoneNo = person.phoneNo || ''
|
||||
row.age = person.age ?? null
|
||||
const mappedRole = mapPersonnelTypeToVehicleRole(person.personnelType)
|
||||
if (mappedRole) {
|
||||
row.role = mappedRole
|
||||
handleRoleChange(row, 0)
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePersonnelRows(rows: VehiclePersonnelRow[]) {
|
||||
@@ -1107,4 +1126,13 @@ onMounted(() => {
|
||||
.sub-table {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.vehicle-plate-cell {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 6px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user