提交
This commit is contained in:
1 parent
c00f19f8bd
commit
272c68af4b
134 files changed
+930389
-38617
No files matched your search
@@ -7,13 +7,16 @@
|
||||
'white': #ffffff,
|
||||
'black': #000000,
|
||||
'success': (
|
||||
'base': #168f45
|
||||
'base': #059669
|
||||
),
|
||||
'warning': (
|
||||
'base': #ffae1f
|
||||
'base': #d97706
|
||||
),
|
||||
'danger': (
|
||||
'base': #ff4d4f
|
||||
'base': #dc2626
|
||||
),
|
||||
'info': (
|
||||
'base': #1e293b
|
||||
),
|
||||
'error': (
|
||||
'base': #fa896b
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
--el-color-primary-light-8: #c8ecd4 !important;
|
||||
--el-color-primary-light-9: var(--mint-primary-bg) !important;
|
||||
--el-color-primary-dark-2: var(--mint-primary-dark) !important;
|
||||
// 语义色:供 el-tag effect=dark 使用实心底(避免 Element 默认 info #909399)
|
||||
--el-color-success: #059669 !important;
|
||||
--el-color-warning: #d97706 !important;
|
||||
--el-color-danger: #dc2626 !important;
|
||||
--el-color-info: #1e293b !important;
|
||||
--el-border-color: var(--mint-border) !important;
|
||||
--el-border-color-light: #dfece6 !important;
|
||||
--el-fill-color-light: var(--mint-table-head) !important;
|
||||
@@ -302,20 +307,67 @@ html.dark .el-card {
|
||||
}
|
||||
}
|
||||
|
||||
// 修改el-tag样式
|
||||
.el-tag {
|
||||
font-weight: 500;
|
||||
// 语义 Tag:深色底 + 白字(配合全局 ElTag 默认 effect=dark;覆盖 light 残留)
|
||||
html body .el-tag {
|
||||
border: none !important;
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
transition: all 0s !important;
|
||||
--el-tag-text-color: #ffffff;
|
||||
color: #ffffff !important;
|
||||
|
||||
&.el-tag--default {
|
||||
height: 26px !important;
|
||||
}
|
||||
|
||||
.el-tag__close {
|
||||
color: rgba(255, 255, 255, 0.85) !important;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2) !important;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
&,
|
||||
&.el-tag--primary,
|
||||
&.el-tag--success {
|
||||
--el-tag-bg-color: #059669;
|
||||
--el-tag-border-color: #059669;
|
||||
--el-tag-hover-color: #047857;
|
||||
background: #059669 !important;
|
||||
background-color: #059669 !important;
|
||||
border-color: #059669 !important;
|
||||
}
|
||||
|
||||
&.el-tag--warning {
|
||||
--el-tag-bg-color: #d97706;
|
||||
--el-tag-border-color: #d97706;
|
||||
--el-tag-hover-color: #b45309;
|
||||
background: #d97706 !important;
|
||||
background-color: #d97706 !important;
|
||||
border-color: #d97706 !important;
|
||||
}
|
||||
|
||||
&.el-tag--danger {
|
||||
--el-tag-bg-color: #dc2626;
|
||||
--el-tag-border-color: #dc2626;
|
||||
--el-tag-hover-color: #b91c1c;
|
||||
background: #dc2626 !important;
|
||||
background-color: #dc2626 !important;
|
||||
border-color: #dc2626 !important;
|
||||
}
|
||||
|
||||
// 中性 info:无背景,正文标准色(与彩色语义 Tag 区分)
|
||||
&.el-tag--info {
|
||||
--el-tag-bg-color: transparent;
|
||||
--el-tag-border-color: transparent;
|
||||
--el-tag-text-color: var(--mint-text);
|
||||
--el-tag-hover-color: var(--mint-text);
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
border-color: transparent !important;
|
||||
color: var(--mint-text) !important;
|
||||
}
|
||||
@@ -858,47 +910,6 @@ body .el-table thead {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Fresh Mint:状态标签(映射 design spec 的浅底 + 语义色字)
|
||||
.page-container .el-tag,
|
||||
.console-container .el-tag {
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.page-container .el-tag--success,
|
||||
.console-container .el-tag--success {
|
||||
background: #d4f0de !important;
|
||||
color: #147a3c !important;
|
||||
}
|
||||
|
||||
.page-container .el-tag--warning,
|
||||
.console-container .el-tag--warning {
|
||||
background: #fffbeb !important;
|
||||
color: #d97706 !important;
|
||||
}
|
||||
|
||||
.page-container .el-tag--danger,
|
||||
.console-container .el-tag--danger {
|
||||
background: #fef2f2 !important;
|
||||
color: #dc2626 !important;
|
||||
}
|
||||
|
||||
.page-container .el-tag--info,
|
||||
.console-container .el-tag--info {
|
||||
background: transparent !important;
|
||||
border-color: transparent !important;
|
||||
color: var(--mint-text) !important;
|
||||
}
|
||||
|
||||
.page-container .el-tag--primary,
|
||||
.console-container .el-tag--primary {
|
||||
background: #e6f8ed !important;
|
||||
color: #168f45 !important;
|
||||
}
|
||||
|
||||
.page-container .el-button--primary,
|
||||
.console-container .el-button--primary {
|
||||
--el-button-bg-color: var(--mint-primary);
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
--warning-bg: #fffbeb;
|
||||
--danger: #dc2626;
|
||||
--danger-bg: #fef2f2;
|
||||
--info: #64748b;
|
||||
--info-bg: #f8fafc;
|
||||
--info: #1e293b;
|
||||
--info-bg: #f1f5f9;
|
||||
|
||||
/* 弹窗相对视口上下留白(各 20px,总 40px) */
|
||||
--dialog-viewport-inset: 20px;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-dialog
|
||||
v-model="innerVisible"
|
||||
:title="dialogTitle"
|
||||
width="820px"
|
||||
width="1100px"
|
||||
align-center
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
@@ -13,83 +13,84 @@
|
||||
style="backdrop-filter: none"
|
||||
@closed="handleClosed"
|
||||
>
|
||||
<el-form label-position="top" class="form-grid-2">
|
||||
<el-form-item label="客户原文" class="form-col-span-2">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="客户原文">
|
||||
<el-input
|
||||
v-model="rawText"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="粘贴客户提供的车辆与驾押信息后点击识别"
|
||||
:rows="10"
|
||||
placeholder="请按示例格式填写或粘贴客户原文后点击识别"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-col-span-2">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleParse">
|
||||
<el-icon><MagicStick /></el-icon>识别
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="parsed">
|
||||
<el-form-item v-if="showVehicleFields" label="承运商" class="form-col-span-2" required>
|
||||
<el-select
|
||||
v-model="carrierId"
|
||||
placeholder="请选择承运商"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="c in carrierOptions"
|
||||
:key="c.id"
|
||||
:label="c.carrierName"
|
||||
:value="c.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="mode === 'personnel-first' && hasPlate"
|
||||
label="建车选项"
|
||||
class="form-col-span-2"
|
||||
>
|
||||
<el-form-item v-if="mode === 'personnel-first' && hasPlate" label="建车选项">
|
||||
<el-checkbox v-model="createVehicle">一并创建三方车辆并关联</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="showVehicleFields" label="主车号">
|
||||
<el-input v-model="vehicleForm.licensePlate" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showVehicleFields" label="挂车号">
|
||||
<el-input v-model="vehicleForm.trailerNo" maxlength="20" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showVehicleFields" label="核载(吨)">
|
||||
<el-input-number
|
||||
v-model="vehicleForm.loadCapacity"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-if="showVehicleFields" class="form-grid-4">
|
||||
<el-form-item label="承运商" required>
|
||||
<el-select
|
||||
v-model="carrierId"
|
||||
placeholder="请选择承运商"
|
||||
filterable
|
||||
clearable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="c in carrierOptions"
|
||||
:key="c.id"
|
||||
:label="c.carrierName"
|
||||
:value="c.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="主车号">
|
||||
<el-input v-model="vehicleForm.licensePlate" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="挂车号">
|
||||
<el-input v-model="vehicleForm.trailerNo" maxlength="20" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="核载(吨)">
|
||||
<el-input-number
|
||||
v-model="vehicleForm.loadCapacity"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item label="驾驶员">
|
||||
<el-input v-model="driverForm.personnelName" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="驾驶员手机">
|
||||
<el-input v-model="driverForm.phoneNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="驾驶员身份证" class="form-col-span-2">
|
||||
<el-input v-model="driverForm.idCardNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<div class="form-grid-3">
|
||||
<el-form-item label="驾驶员">
|
||||
<el-input v-model="driverForm.personnelName" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="驾驶员手机">
|
||||
<el-input v-model="driverForm.phoneNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="驾驶员身份证">
|
||||
<el-input v-model="driverForm.idCardNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item label="押运员">
|
||||
<el-input v-model="escortForm.personnelName" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="押运员电话">
|
||||
<el-input v-model="escortForm.phoneNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="押运员身份证" class="form-col-span-2">
|
||||
<el-input v-model="escortForm.idCardNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<div class="form-grid-3">
|
||||
<el-form-item label="押运员">
|
||||
<el-input v-model="escortForm.personnelName" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="押运员电话">
|
||||
<el-input v-model="escortForm.phoneNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="押运员身份证">
|
||||
<el-input v-model="escortForm.idCardNo" maxlength="32" clearable />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="conflictRows.length" class="form-col-span-2 paste-conflict-block">
|
||||
<div v-if="conflictRows.length" class="paste-conflict-block">
|
||||
<h4 class="paste-conflict-title">冲突处理</h4>
|
||||
<div v-for="row in conflictRows" :key="row.key" class="paste-conflict-row">
|
||||
<div class="paste-conflict-label">
|
||||
@@ -105,7 +106,6 @@
|
||||
|
||||
<el-alert
|
||||
v-if="parsed.warnings.length"
|
||||
class="form-col-span-2"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
:title="`有 ${parsed.warnings.length} 行未识别`"
|
||||
@@ -140,6 +140,7 @@
|
||||
} from '@/api/pl'
|
||||
import { pickBxPageResult } from '@/utils/http/bx'
|
||||
import {
|
||||
PL_PASTE_SAMPLE_TEXT,
|
||||
parsePlCustomerVehicleText,
|
||||
type PlPasteRecognizeResult
|
||||
} from '@/utils/pl-paste-recognize'
|
||||
@@ -169,7 +170,7 @@
|
||||
props.mode === 'vehicle-bundle' ? '粘贴识别(整车套装)' : '粘贴识别(以人为主)'
|
||||
)
|
||||
|
||||
const rawText = ref('')
|
||||
const rawText = ref(PL_PASTE_SAMPLE_TEXT)
|
||||
const parsed = ref<PlPasteRecognizeResult | null>(null)
|
||||
const carrierId = ref('')
|
||||
const createVehicle = ref(true)
|
||||
@@ -376,7 +377,7 @@
|
||||
}
|
||||
|
||||
function handleClosed() {
|
||||
rawText.value = ''
|
||||
rawText.value = PL_PASTE_SAMPLE_TEXT
|
||||
parsed.value = null
|
||||
carrierId.value = ''
|
||||
createVehicle.value = true
|
||||
@@ -395,12 +396,20 @@
|
||||
watch(
|
||||
() => props.visible,
|
||||
async v => {
|
||||
if (v) await ensureCarriers()
|
||||
if (v) {
|
||||
rawText.value = PL_PASTE_SAMPLE_TEXT
|
||||
await ensureCarriers()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.paste-conflict-block,
|
||||
:deep(.el-alert) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.paste-conflict-block {
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 8px;
|
||||
|
||||
@@ -5,33 +5,72 @@
|
||||
:key="product.id || `${product.productNo}-${index}`"
|
||||
class="pl-plan-list-product-cell__row"
|
||||
>
|
||||
<span class="pl-plan-list-product-cell__line">
|
||||
<span class="pl-plan-list-product-cell__text">{{ formatProductLine(product) }}</span>
|
||||
<el-tag v-if="getHazardFlags(product).isToxic" type="warning" size="small" class="pl-plan-list-product-cell__mark">
|
||||
毒
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="getHazardFlags(product).isExplosive"
|
||||
type="danger"
|
||||
size="small"
|
||||
class="pl-plan-list-product-cell__mark"
|
||||
>
|
||||
爆
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="showCertStatus && isHazardProduct(product)"
|
||||
class="pl-plan-list-product-cell__certs"
|
||||
>
|
||||
<span
|
||||
v-for="slot in getRequiredCertSlots(product)"
|
||||
:key="slot.key"
|
||||
class="pl-plan-list-product-cell__cert-text"
|
||||
<span
|
||||
class="pl-plan-list-product-cell__line"
|
||||
:class="{
|
||||
'pl-plan-list-product-cell__line--qty': field === 'qty',
|
||||
'pl-plan-list-product-cell__line--center': field === 'spec' || field === 'unit'
|
||||
}"
|
||||
>
|
||||
<template v-if="!field">
|
||||
<span class="pl-plan-list-product-cell__text">{{ formatProductLine(product) }}</span>
|
||||
<el-tag
|
||||
v-if="getHazardFlags(product).isToxic"
|
||||
type="warning"
|
||||
size="small"
|
||||
class="pl-plan-list-product-cell__mark"
|
||||
>
|
||||
{{ slot.label }}(<span
|
||||
:class="{ 'pl-plan-list-product-cell__cert-status--missing': !isProductCertSlotFilled(product, slot.key) }"
|
||||
>{{ isProductCertSlotFilled(product, slot.key) ? '有' : '无' }}</span>)
|
||||
毒
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="getHazardFlags(product).isExplosive"
|
||||
type="danger"
|
||||
size="small"
|
||||
class="pl-plan-list-product-cell__mark"
|
||||
>
|
||||
爆
|
||||
</el-tag>
|
||||
<span
|
||||
v-if="showCertStatus && isHazardProduct(product)"
|
||||
class="pl-plan-list-product-cell__certs"
|
||||
>
|
||||
<span
|
||||
v-for="slot in getRequiredCertSlots(product)"
|
||||
:key="slot.key"
|
||||
class="pl-plan-list-product-cell__cert-text"
|
||||
>
|
||||
{{ slot.label }}(<span
|
||||
:class="{
|
||||
'pl-plan-list-product-cell__cert-status--missing': !isProductCertSlotFilled(
|
||||
product,
|
||||
slot.key
|
||||
)
|
||||
}"
|
||||
>{{ isProductCertSlotFilled(product, slot.key) ? '有' : '无' }}</span
|
||||
>)
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="field === 'name'">
|
||||
<span class="pl-plan-list-product-cell__text">{{ product.productName || '—' }}</span>
|
||||
<el-tag
|
||||
v-if="getHazardFlags(product).isToxic"
|
||||
type="warning"
|
||||
size="small"
|
||||
class="pl-plan-list-product-cell__mark"
|
||||
>
|
||||
毒
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-if="getHazardFlags(product).isExplosive"
|
||||
type="danger"
|
||||
size="small"
|
||||
class="pl-plan-list-product-cell__mark"
|
||||
>
|
||||
爆
|
||||
</el-tag>
|
||||
</template>
|
||||
<span v-else class="pl-plan-list-product-cell__text">{{ formatFieldValue(product) }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,12 +86,20 @@ import {
|
||||
resolveProductHazardFlags
|
||||
} from '@/composables/usePlToxicProductCertCheck'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { formatPlanProductListText } from '@/utils/pl-display'
|
||||
import {
|
||||
formatPlanProductListText,
|
||||
getPlanProductQuantity,
|
||||
getPlanProductSpec
|
||||
} from '@/utils/pl-display'
|
||||
|
||||
withDefaults(
|
||||
export type PlPlanListProductCellField = 'name' | 'spec' | 'qty' | 'unit'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
products?: PlanProduct[]
|
||||
/** 危化品行下方展示证书有无(按产品类型) */
|
||||
/** 按字段拆列展示;未传时保持整行拼接 */
|
||||
field?: PlPlanListProductCellField
|
||||
/** 危化品行下方展示证书有无(按产品类型;仅整行模式) */
|
||||
showCertStatus?: boolean
|
||||
}>(),
|
||||
{
|
||||
@@ -71,6 +118,21 @@ function formatProductLine(product: PlanProduct) {
|
||||
return formatPlanProductListText(product, getUnitLabel)
|
||||
}
|
||||
|
||||
function formatFieldValue(product: PlanProduct) {
|
||||
if (props.field === 'spec') {
|
||||
return getPlanProductSpec(product)
|
||||
}
|
||||
if (props.field === 'qty') {
|
||||
return getPlanProductQuantity(product)
|
||||
}
|
||||
if (props.field === 'unit') {
|
||||
const unitRaw = product.unit || ''
|
||||
if (!unitRaw) return '—'
|
||||
return getUnitLabel(unitRaw) || unitRaw
|
||||
}
|
||||
return '—'
|
||||
}
|
||||
|
||||
function getHazardFlags(product: PlanProduct) {
|
||||
return resolveProductHazardFlags(product)
|
||||
}
|
||||
@@ -105,6 +167,18 @@ function getHazardFlags(product: PlanProduct) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pl-plan-list-product-cell__line--qty {
|
||||
justify-content: flex-end;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pl-plan-list-product-cell__line--center {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pl-plan-list-product-cell__text {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -1224,7 +1224,17 @@
|
||||
mapContractProducts(contractSnapshot.value?.products)
|
||||
)
|
||||
|
||||
const hazardProducts = computed(() => products.value.filter((item) => isHazardProduct(item)))
|
||||
/** 危化证区域展示 CRM 标准名(productRows 已回填 standardProductName;库内 productName 可能是别名) */
|
||||
const hazardProducts = computed(() =>
|
||||
products.value
|
||||
.filter((item) => isHazardProduct(item))
|
||||
.map((item) => {
|
||||
const formRow = item.id ? planProductFormById.value.get(String(item.id)) : undefined
|
||||
const standardName = String(formRow?.standardProductName || '').trim()
|
||||
if (!standardName || standardName === item.productName) return item
|
||||
return { ...item, productName: standardName }
|
||||
})
|
||||
)
|
||||
|
||||
async function handleViewContract() {
|
||||
const contractId = contractSnapshot.value?.id || plan.value?.contractId
|
||||
|
||||
@@ -125,8 +125,10 @@ function syncCertList(headCerts: CertRowWithKey[], trailerCerts: CertRowWithKey[
|
||||
certList.value = mergeVehicleCertsByPart(headCerts, trailerCerts, hasTrailer.value)
|
||||
}
|
||||
|
||||
watch(hasTrailer, value => {
|
||||
if (!value) {
|
||||
watch(hasTrailer, (value, oldValue) => {
|
||||
// 仅在「有挂车 → 无挂车」时剥离挂车证书,避免编辑回填时
|
||||
// trailerNo 与 certList 同 tick 赋值触发误清空。
|
||||
if (!value && oldValue) {
|
||||
activePart.value = PL_VEHICLE_CERT_PART_HEAD
|
||||
certList.value = mergeVehicleCertsByPart(
|
||||
splitVehicleCertsByPart(certList.value).headCerts,
|
||||
@@ -137,6 +139,10 @@ watch(hasTrailer, value => {
|
||||
trailerCertFormRef.value?.clearUploadRefs()
|
||||
return
|
||||
}
|
||||
if (!value) {
|
||||
activePart.value = PL_VEHICLE_CERT_PART_HEAD
|
||||
return
|
||||
}
|
||||
if (activePart.value !== PL_VEHICLE_CERT_PART_TRAILER) {
|
||||
activePart.value = PL_VEHICLE_CERT_PART_HEAD
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
/**
|
||||
* 全局包装 ElTag:默认插槽无有效内容时不渲染,避免空值时出现带背景色的空 tag。
|
||||
* 通过 vite Components 自定义 resolver 替换自动导入的 ElTag。
|
||||
* 全局包装 ElTag:
|
||||
* 1) 默认插槽无有效内容时不渲染,避免空值时出现带背景色的空 tag
|
||||
* 2) 默认 effect="dark"(深色底 + 白字),覆盖 Element Plus 默认 light(浅底彩字 / info=#909399)
|
||||
* 通过 vite Components 自定义 resolver + main.ts 全局注册替换 ElTag。
|
||||
*/
|
||||
import { ElTag } from 'element-plus'
|
||||
// 走 SCSS 源码,使 el-light.scss 中的语义色生效(info Tag 另由 el-ui 设为无背景+正文色)
|
||||
import 'element-plus/es/components/tag/style/index'
|
||||
import { Comment, Text, defineComponent, h, type VNode, type VNodeArrayChildren } from 'vue'
|
||||
|
||||
function hasVisibleDefaultContent(vnodes: VNode[] | undefined): boolean {
|
||||
@@ -39,7 +43,9 @@ const EmptyAwareElTag = defineComponent({
|
||||
if (!hasVisibleDefaultContent(slots.default?.())) {
|
||||
return null
|
||||
}
|
||||
return h(ElTag, { ...props, ...attrs }, slots)
|
||||
// ElTag 自身 default effect 为 light(浅底彩字);此处一律强制 dark(深色底白字)
|
||||
// 注意:不能读 props.effect 再 ?? 'dark',因默认值已是 'light',永远不会落到 dark
|
||||
return h(ElTag, { ...props, ...attrs, effect: 'dark' }, slots)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -22,7 +22,7 @@ export function isRequiredCertSlotComplete(
|
||||
if (!cert) return false
|
||||
if (!matchRequiredCertName(cert.certName, requiredName)) return false
|
||||
if (!cert.expireDate) return false
|
||||
if (!cert.attachmentUrls?.trim()) return false
|
||||
// 证书附件非必填
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ export function getMissingRequiredCertFieldLabels(
|
||||
requiredName: string
|
||||
): string[] {
|
||||
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
|
||||
return ['有效期', '附件']
|
||||
return ['有效期']
|
||||
}
|
||||
const missing: string[] = []
|
||||
if (!cert.expireDate) missing.push('有效期')
|
||||
if (!cert.attachmentUrls?.trim()) missing.push('附件')
|
||||
// 证书附件非必填
|
||||
return missing
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
/**
|
||||
* 三方车辆/人员客户文本粘贴解析
|
||||
* 示例:
|
||||
* 皖LB1405 皖LP359
|
||||
* 核载:34 吨
|
||||
* 驾驶员:徐孝军
|
||||
* 手机号:18956652137
|
||||
* 身份证:342921198602020031
|
||||
* 押运员:汪海明
|
||||
* 电话:13955522828
|
||||
* 身份证:342829197009084019
|
||||
* 标准格式见 `PL_PASTE_SAMPLE_TEXT`。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 粘贴识别输入框预填示例(格式与解析规则一致,敏感字段已脱敏,供用户对照改写)
|
||||
* 姓名保留姓、手机保留前 3 后 4、身份证保留前 6 后 4、车牌保留省份简称后打码
|
||||
*/
|
||||
export const PL_PASTE_SAMPLE_TEXT = [
|
||||
'皖****** 皖******',
|
||||
'核载:34 吨',
|
||||
'驾驶员:张**',
|
||||
'手机号:138****0000',
|
||||
'身份证:340000********0000',
|
||||
'押运员:李**',
|
||||
'电话:139****0000',
|
||||
'身份证:340000********0000'
|
||||
].join('\n')
|
||||
|
||||
export interface PlPastePersonnelDraft {
|
||||
personnelName: string
|
||||
phoneNo?: string
|
||||
|
||||
@@ -119,7 +119,7 @@ export function isPersonnelCertStrictComplete(
|
||||
if (!cert?.certName?.trim()) return false
|
||||
if (!matchRequiredCertName(cert.certName, requiredName)) return false
|
||||
if (!cert.expireDate) return false
|
||||
if (!cert.attachmentUrls?.trim()) return false
|
||||
// 证书附件非必填
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -136,11 +136,7 @@ export function matchRequiredCertName(
|
||||
}
|
||||
|
||||
export function isPersonnelCertUploaded(cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'>) {
|
||||
return Boolean(
|
||||
cert?.certName?.trim() &&
|
||||
cert?.expireDate &&
|
||||
cert?.attachmentUrls?.trim()
|
||||
)
|
||||
return Boolean(cert?.certName?.trim() && cert?.expireDate)
|
||||
}
|
||||
|
||||
export function getRequiredPersonnelCertNames(role: PersonnelCertRole): readonly string[] {
|
||||
@@ -215,11 +211,11 @@ function getPersonnelCertMissingFieldLabels(
|
||||
requiredName: string
|
||||
): string[] {
|
||||
if (!cert || !matchRequiredCertName(cert.certName, requiredName)) {
|
||||
return ['有效期', '附件']
|
||||
return ['有效期']
|
||||
}
|
||||
const missing: string[] = []
|
||||
if (!cert.expireDate) missing.push('有效期')
|
||||
if (!cert.attachmentUrls?.trim()) missing.push('附件')
|
||||
// 证书附件非必填
|
||||
return missing
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,7 @@ export function mergeVehicleCertsByPart<T extends CertRow>(
|
||||
}
|
||||
|
||||
export function isVehicleCertUploaded(cert?: Pick<CertRow, 'certName' | 'certNo' | 'expireDate' | 'attachmentUrls'>) {
|
||||
return Boolean(
|
||||
cert?.certName?.trim() &&
|
||||
cert?.expireDate &&
|
||||
cert?.attachmentUrls?.trim()
|
||||
)
|
||||
return Boolean(cert?.certName?.trim() && cert?.expireDate)
|
||||
}
|
||||
|
||||
export function getVehicleHeadRequiredCertNames(
|
||||
@@ -263,11 +259,11 @@ function getVehicleCertMissingFieldLabels(
|
||||
requiredName: string
|
||||
): string[] {
|
||||
if (!cert || !matchVehicleRequiredCertName(cert.certName, requiredName)) {
|
||||
return ['有效期', '附件']
|
||||
return ['有效期']
|
||||
}
|
||||
const missing: string[] = []
|
||||
if (!cert.expireDate) missing.push('有效期')
|
||||
if (!cert.attachmentUrls?.trim()) missing.push('附件')
|
||||
// 证书附件非必填
|
||||
return missing
|
||||
}
|
||||
|
||||
|
||||
@@ -189,9 +189,49 @@
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column v-if="isColumnVisible('products')" label="产品信息" min-width="240">
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productName')"
|
||||
label="产品名称"
|
||||
min-width="200"
|
||||
align="left"
|
||||
header-align="left"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" />
|
||||
<PlPlanListProductCell :products="row.products" field="name" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productSpec')"
|
||||
label="型号/规格"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="spec" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productQty')"
|
||||
label="数量"
|
||||
min-width="90"
|
||||
align="right"
|
||||
header-align="right"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="qty" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productUnit')"
|
||||
label="单位"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="unit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isColumnVisible('planAttachments')" label="计划附件" min-width="200">
|
||||
@@ -328,7 +368,10 @@ const listColumnDefs = [
|
||||
{ prop: 'followStatus', label: '跟进状态' },
|
||||
{ prop: 'planType', label: '单据类型' },
|
||||
{ prop: 'customerName', label: '客户名称' },
|
||||
{ prop: 'products', label: '产品信息' },
|
||||
{ prop: 'productName', label: '产品名称' },
|
||||
{ prop: 'productSpec', label: '型号/规格' },
|
||||
{ prop: 'productQty', label: '数量' },
|
||||
{ prop: 'productUnit', label: '单位' },
|
||||
{ prop: 'planAttachments', label: '计划附件' },
|
||||
{ prop: 'licensePlate', label: '车牌号' },
|
||||
{ prop: 'personnelSummary', label: '人员' },
|
||||
|
||||
@@ -179,9 +179,49 @@
|
||||
min-width="120"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column v-if="isColumnVisible('products')" label="产品信息" min-width="240">
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productName')"
|
||||
label="产品名称"
|
||||
min-width="200"
|
||||
align="left"
|
||||
header-align="left"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" />
|
||||
<PlPlanListProductCell :products="row.products" field="name" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productSpec')"
|
||||
label="型号/规格"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="spec" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productQty')"
|
||||
label="数量"
|
||||
min-width="90"
|
||||
align="right"
|
||||
header-align="right"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="qty" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productUnit')"
|
||||
label="单位"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="unit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isColumnVisible('planAttachments')" label="计划附件" min-width="280">
|
||||
@@ -382,7 +422,10 @@ const planList = ref<Plan[]>([])
|
||||
|
||||
const listColumnDefs = [
|
||||
{ prop: 'planDate', label: '计划日期' },
|
||||
{ prop: 'products', label: '产品信息' },
|
||||
{ prop: 'productName', label: '产品名称' },
|
||||
{ prop: 'productSpec', label: '型号/规格' },
|
||||
{ prop: 'productQty', label: '数量' },
|
||||
{ prop: 'productUnit', label: '单位' },
|
||||
{ prop: 'planAttachments', label: '计划附件' },
|
||||
{ prop: 'customerName', label: '客户名称' },
|
||||
{ prop: 'planType', label: '单据类型' },
|
||||
|
||||
@@ -246,14 +246,48 @@
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('products')"
|
||||
label="产品信息"
|
||||
min-width="240"
|
||||
v-if="isColumnVisible('productName')"
|
||||
label="产品名称"
|
||||
min-width="200"
|
||||
align="left"
|
||||
header-align="left"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" />
|
||||
<PlPlanListProductCell :products="row.products" field="name" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productSpec')"
|
||||
label="型号/规格"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="spec" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productQty')"
|
||||
label="数量"
|
||||
min-width="90"
|
||||
align="right"
|
||||
header-align="right"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="qty" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('productUnit')"
|
||||
label="单位"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<PlPlanListProductCell :products="row.products" field="unit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -490,7 +524,10 @@ const listColumnDefs = [
|
||||
{ prop: 'planDate', label: '计划日期' },
|
||||
{ prop: 'planType', label: '单据类型' },
|
||||
{ prop: 'customerName', label: '客户名称' },
|
||||
{ prop: 'products', label: '产品信息' },
|
||||
{ prop: 'productName', label: '产品名称' },
|
||||
{ prop: 'productSpec', label: '型号/规格' },
|
||||
{ prop: 'productQty', label: '数量' },
|
||||
{ prop: 'productUnit', label: '单位' },
|
||||
{ prop: 'planAttachments', label: '计划附件' },
|
||||
{ prop: 'licensePlate', label: '车牌号' },
|
||||
{ prop: 'personnelSummary', label: '人员' },
|
||||
|
||||
@@ -441,6 +441,7 @@ import {
|
||||
type VehicleDetail,
|
||||
type VehiclePersonnelRow,
|
||||
type CertRow,
|
||||
type CertRead,
|
||||
type Personnel,
|
||||
type Carrier
|
||||
} from '@/api/pl'
|
||||
@@ -454,7 +455,7 @@ import SystemViewDialog, {
|
||||
} from '@/components/business/system-view-dialog/index.vue'
|
||||
import { loadPersonnelWithCerts } from '@/composables/usePlVehicleViewDetail'
|
||||
import { useDbInstantSearch } from '@/composables/useDbInstantSearch'
|
||||
import { pickBxList, pickBxPageResult } from '@/utils/http/bx'
|
||||
import { pickBxData, pickBxList, pickBxPageResult } from '@/utils/http/bx'
|
||||
import { DEFAULT_LIST_PAGE_SIZE } from '@/utils/table/tableConfig'
|
||||
import { formatDateTime } from '@/utils/format'
|
||||
import {
|
||||
@@ -488,6 +489,7 @@ type CertFormListRef = InstanceType<typeof PlVehicleCertPartTabs>
|
||||
const loading = ref(false)
|
||||
const quickSearchKeyword = ref('')
|
||||
const submitLoading = ref(false)
|
||||
const dialogLoading = ref(false)
|
||||
const vehicleList = ref<Vehicle[]>([])
|
||||
const carrierList = ref<Carrier[]>([])
|
||||
|
||||
@@ -554,7 +556,6 @@ const formData = reactive({
|
||||
|
||||
const formRules = {
|
||||
licensePlate: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
|
||||
trailerNo: [{ required: true, message: '请输入挂车号', trigger: 'blur' }],
|
||||
vehicleStatus: [{ required: true, message: '请选择车辆状态', trigger: 'change' }],
|
||||
carrierId: [{ required: true, message: '请选择承运商', trigger: 'change' }]
|
||||
}
|
||||
@@ -923,14 +924,28 @@ async function handleView(row: Vehicle) {
|
||||
}
|
||||
}
|
||||
|
||||
function mapCertRowsForForm(certs: CertRead[] | undefined | null) {
|
||||
return (certs || []).map(c => ({
|
||||
_key: c.id || c.certId || `cert-${Math.random().toString(36).slice(2, 10)}`,
|
||||
certId: c.id || c.certId,
|
||||
vehiclePart: c.vehiclePart,
|
||||
certName: c.certName,
|
||||
certNo: c.certNo,
|
||||
expireDate: c.expireDate ? String(c.expireDate).slice(0, 10) : '',
|
||||
remindDays: c.remindDays ?? 30,
|
||||
attachmentUrls: c.attachmentUrls || ''
|
||||
}))
|
||||
}
|
||||
|
||||
async function handleEdit(row: Vehicle) {
|
||||
dialogTitle.value = '编辑自有车辆'
|
||||
isEdit.value = true
|
||||
dialogLoading.value = true
|
||||
dialogVisible.value = true
|
||||
try {
|
||||
await loadPersonnelOptions()
|
||||
const res = await vehicleApi.get(row.id)
|
||||
const detail = ((res.data ?? res) || {}) as VehicleDetail
|
||||
const detail = pickBxData<VehicleDetail>(res) || ({} as VehicleDetail)
|
||||
if (detail.vehicleType !== VEHICLE_TYPE_SELF) {
|
||||
ElMessage.warning('仅可编辑自有车辆')
|
||||
dialogVisible.value = false
|
||||
@@ -953,23 +968,21 @@ async function handleEdit(row: Vehicle) {
|
||||
age: p.age ?? null
|
||||
}))
|
||||
)
|
||||
// 等 trailerNo 相关 watch 先消化,再回填证书,避免被 hasTrailer 逻辑误清空
|
||||
await nextTick()
|
||||
const sourceCerts =
|
||||
detail.certList?.length ? detail.certList : row.certList?.length ? row.certList : []
|
||||
certList.value = ensureSelfVehicleCertSlots(
|
||||
(detail.certList || []).map(c => ({
|
||||
_key: c.id || c.certId || `cert-${Math.random().toString(36).slice(2, 10)}`,
|
||||
certId: c.id || c.certId,
|
||||
vehiclePart: c.vehiclePart,
|
||||
certName: c.certName,
|
||||
certNo: c.certNo,
|
||||
expireDate: c.expireDate,
|
||||
remindDays: c.remindDays ?? 30,
|
||||
attachmentUrls: c.attachmentUrls || ''
|
||||
})),
|
||||
mapCertRowsForForm(sourceCerts),
|
||||
formData.trailerNo
|
||||
)
|
||||
await nextTick()
|
||||
certFormListRef.value?.refreshRequiredSlots?.()
|
||||
} catch {
|
||||
dialogVisible.value = false
|
||||
ElMessage.error('加载车辆详情失败')
|
||||
} finally {
|
||||
dialogLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -459,6 +459,7 @@ import {
|
||||
type VehicleDetail,
|
||||
type VehiclePersonnelRow,
|
||||
type CertRow,
|
||||
type CertRead,
|
||||
type Carrier,
|
||||
type Personnel
|
||||
} from '@/api/pl'
|
||||
@@ -472,7 +473,7 @@ import SystemViewDialog, {
|
||||
type ViewSection
|
||||
} from '@/components/business/system-view-dialog/index.vue'
|
||||
import { useDbInstantSearch } from '@/composables/useDbInstantSearch'
|
||||
import { pickBxList, pickBxPageResult } from '@/utils/http/bx'
|
||||
import { pickBxData, pickBxList, pickBxPageResult } from '@/utils/http/bx'
|
||||
import { DEFAULT_LIST_PAGE_SIZE } from '@/utils/table/tableConfig'
|
||||
import { formatDateTime } from '@/utils/format'
|
||||
import { formatPlVehiclePlateDisplay, normalizePlPersonnelSummaryDisplay } from '@/utils/pl-display'
|
||||
@@ -498,6 +499,8 @@ const loading = ref(false)
|
||||
const quickSearchKeyword = ref('')
|
||||
const submitLoading = ref(false)
|
||||
const dialogLoading = ref(false)
|
||||
/** 编辑回填中:跳过 vehicleType watch,避免证书被 ensure 覆盖清空 */
|
||||
const hydratingEdit = ref(false)
|
||||
const vehicleList = ref<Vehicle[]>([])
|
||||
const carrierList = ref<Carrier[]>([])
|
||||
|
||||
@@ -567,7 +570,6 @@ const formData = reactive({
|
||||
|
||||
const formRules = {
|
||||
licensePlate: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
|
||||
trailerNo: [{ required: true, message: '请输入挂车号', trigger: 'blur' }],
|
||||
carrierId: [{ required: true, message: '请选择承运商', trigger: 'change' }]
|
||||
}
|
||||
|
||||
@@ -974,15 +976,29 @@ async function handleView(row: Vehicle) {
|
||||
}
|
||||
}
|
||||
|
||||
function mapCertRowsForForm(certs: CertRead[] | undefined | null) {
|
||||
return (certs || []).map(c => ({
|
||||
_key: c.id || c.certId || `cert-${Math.random().toString(36).slice(2, 10)}`,
|
||||
certId: c.id || c.certId,
|
||||
vehiclePart: c.vehiclePart,
|
||||
certName: c.certName,
|
||||
certNo: c.certNo,
|
||||
expireDate: c.expireDate ? String(c.expireDate).slice(0, 10) : '',
|
||||
remindDays: c.remindDays ?? 30,
|
||||
attachmentUrls: c.attachmentUrls || ''
|
||||
}))
|
||||
}
|
||||
|
||||
async function handleEdit(row: Vehicle) {
|
||||
dialogTitle.value = '编辑车辆'
|
||||
isEdit.value = true
|
||||
dialogLoading.value = true
|
||||
hydratingEdit.value = true
|
||||
dialogVisible.value = true
|
||||
try {
|
||||
await loadPersonnelOptions()
|
||||
const res = await vehicleApi.get(row.id)
|
||||
const detail = ((res.data ?? res) || {}) as VehicleDetail
|
||||
const detail = pickBxData<VehicleDetail>(res) || ({} as VehicleDetail)
|
||||
Object.assign(formData, {
|
||||
id: detail.id,
|
||||
licensePlate: detail.licensePlate,
|
||||
@@ -1001,19 +1017,19 @@ async function handleEdit(row: Vehicle) {
|
||||
age: p.age ?? null
|
||||
}))
|
||||
)
|
||||
const mappedCerts = (detail.certList || []).map(c => ({
|
||||
_key: c.id || c.certId || `cert-${Math.random().toString(36).slice(2, 10)}`,
|
||||
certId: c.id || c.certId,
|
||||
vehiclePart: c.vehiclePart,
|
||||
certName: c.certName,
|
||||
certNo: c.certNo,
|
||||
expireDate: c.expireDate,
|
||||
remindDays: c.remindDays ?? 30,
|
||||
attachmentUrls: c.attachmentUrls || ''
|
||||
}))
|
||||
certList.value = ensureVehicleCertSlots(mappedCerts, formData.trailerNo, VEHICLE_TYPE_LOCK)
|
||||
// 等 trailerNo 相关 watch 先消化,再回填证书,避免被 hasTrailer 逻辑误清空
|
||||
await nextTick()
|
||||
const sourceCerts =
|
||||
detail.certList?.length ? detail.certList : row.certList?.length ? row.certList : []
|
||||
certList.value = ensureVehicleCertSlots(
|
||||
mapCertRowsForForm(sourceCerts),
|
||||
formData.trailerNo,
|
||||
VEHICLE_TYPE_LOCK
|
||||
)
|
||||
await nextTick()
|
||||
certFormListRef.value?.refreshRequiredSlots?.()
|
||||
} finally {
|
||||
hydratingEdit.value = false
|
||||
dialogLoading.value = false
|
||||
}
|
||||
}
|
||||
@@ -1105,7 +1121,7 @@ async function handleDelete(row: Vehicle) {
|
||||
watch(
|
||||
() => formData.vehicleType,
|
||||
async type => {
|
||||
if (!dialogVisible.value) return
|
||||
if (!dialogVisible.value || hydratingEdit.value) return
|
||||
await loadPersonnelOptions()
|
||||
if (type === 'self' || type === 'carrier') {
|
||||
certList.value = ensureVehicleCertSlots(
|
||||
|
||||
Reference in new issue
Block a user