feat(pl): 装送货段增加同市标记,并同步额度证件与计划表单。
同市易制毒段只校验购买证;同步 Web/H5 表单、额度统计展示与相关回归测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
d58f6ea5bd
commit
522b4be705
40 files changed
+576
-107
No files matched your search
@@ -16,8 +16,8 @@
|
||||
<div class="mp-wv-card__no">{{ row.certNo }}</div>
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="row.certType === 'transport' ? 'status-tag--warning' : 'status-tag--primary'"
|
||||
>{{ row.certType === 'transport' ? '运输证' : '购买证' }}</span
|
||||
:class="`status-tag--${certKindMobileTone(row.certType)}`"
|
||||
>{{ certKindLabel(row.certType) }}</span
|
||||
>
|
||||
</div>
|
||||
<span class="status-tag" :class="`status-tag--${statusTag(row.status)}`">{{
|
||||
@@ -109,7 +109,14 @@
|
||||
import CertConfirmSheet from './CertConfirmSheet.vue'
|
||||
import { formatDateTime } from '@/utils/format'
|
||||
import { formatCertQty } from '@/views/pl/quota-cert/model'
|
||||
import { buyPartyName, expiryWarning, salePartyName } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import {
|
||||
buyPartyName,
|
||||
certKindLabel,
|
||||
certKindMobileTone,
|
||||
compareCertUploadTime,
|
||||
expiryWarning,
|
||||
salePartyName
|
||||
} from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
import { certStatusLabels } from './face-model'
|
||||
@@ -209,9 +216,11 @@
|
||||
const kinds: CertType[] = props.kind ? [props.kind as CertType] : ['purchase', 'transport']
|
||||
const lists = await Promise.all(kinds.map((item) => quotaCertApi.list(item, params)))
|
||||
if (current !== epoch) return
|
||||
rows.value = kinds.flatMap((item, index) =>
|
||||
lists[index].map((row) => ({ ...row, certType: row.certType || item }))
|
||||
)
|
||||
rows.value = kinds
|
||||
.flatMap((item, index) =>
|
||||
lists[index].map((row) => ({ ...row, certType: row.certType || item }))
|
||||
)
|
||||
.sort(compareCertUploadTime)
|
||||
} catch {
|
||||
if (current === epoch) error.value = '证件加载失败,请重试'
|
||||
} finally {
|
||||
|
||||
@@ -41,7 +41,14 @@
|
||||
计划数量 {{ qtyText(group.source.quantity) }} {{ unitText(group.source.unit) }}
|
||||
</p>
|
||||
<div v-for="row in group.rows" :key="conversionKey(row)" class="mp-cert-factor">
|
||||
<strong>{{ row.cert.certType === 'purchase' ? '购买证' : '运输证' }} {{ row.cert.certNo }}</strong>
|
||||
<strong class="mp-cert-kind-heading">
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(row.cert.certType)}`"
|
||||
>{{ certKindLabel(row.cert.certType) }}</span
|
||||
>
|
||||
<span>{{ row.cert.certNo }}</span>
|
||||
</strong>
|
||||
<van-field
|
||||
v-model="coefficients[conversionKey(row)]"
|
||||
label="换算系数"
|
||||
@@ -91,7 +98,14 @@
|
||||
<section v-if="isPerStop && faceCards.length" class="mp-wv-section">
|
||||
<h3>关联证件证面</h3>
|
||||
<article v-for="face in faceCards" :id="faceDomId(face.key)" :key="face.key" class="mp-cert-face-card">
|
||||
<h4>{{ face.label }}</h4>
|
||||
<h4 class="mp-cert-kind-heading">
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(face.kind)}`"
|
||||
>{{ certKindLabel(face.kind) }}</span
|
||||
>
|
||||
<span>{{ face.certNo }}</span>
|
||||
</h4>
|
||||
<p v-if="!face.cert" class="plan-empty-hint">没有读到这张证的证面档案。</p>
|
||||
<template v-else>
|
||||
<div v-for="(group, groupIndex) in groupsOf(face.cert, face.kind)" :key="groupIndex">
|
||||
@@ -158,6 +172,7 @@
|
||||
sourceLabel,
|
||||
unitConversions
|
||||
} from '@/components/business/pl-plan-quota-dialog/stop-model'
|
||||
import { certKindLabel, certKindMobileTone } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { formatCertQty } from '@/views/pl/quota-cert/model'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
@@ -190,7 +205,13 @@
|
||||
const sourceOptions = computed(() => plan.value?.sourceOptions || [])
|
||||
const faceCards = computed(() => {
|
||||
const seen = new Set<string>()
|
||||
const tabs: { key: string; label: string; kind: CertType; cert: QuotaCert | null }[] = []
|
||||
const tabs: {
|
||||
key: string
|
||||
label: string
|
||||
kind: CertType
|
||||
certNo: string
|
||||
cert: QuotaCert | null
|
||||
}[] = []
|
||||
const push = (kind: string, id: string, certNo: string) => {
|
||||
if ((kind !== 'purchase' && kind !== 'transport') || !id || seen.has(`${kind}:${id}`)) return
|
||||
seen.add(`${kind}:${id}`)
|
||||
@@ -200,7 +221,8 @@
|
||||
key: `${kind}:${id}`,
|
||||
kind,
|
||||
cert,
|
||||
label: `${kind === 'purchase' ? '购买证' : '运输证'} ${number}`
|
||||
certNo: number,
|
||||
label: `${certKindLabel(kind)} ${number}`
|
||||
})
|
||||
}
|
||||
for (const row of plan.value?.stopProducts || []) {
|
||||
|
||||
@@ -60,7 +60,14 @@
|
||||
</button>
|
||||
</template>
|
||||
</template>
|
||||
<p v-else class="mp-cert-link-note">{{ currentLabel }}</p>
|
||||
<p v-else class="mp-cert-kind-heading">
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(certType)}`"
|
||||
>{{ certKindLabel(certType) }}</span
|
||||
>
|
||||
<span v-if="certNo">{{ certNo }}</span>
|
||||
</p>
|
||||
|
||||
<template v-if="certId">
|
||||
<h3>适用产品</h3>
|
||||
@@ -139,6 +146,7 @@
|
||||
type QuotaCert,
|
||||
type ScopeProduct
|
||||
} from '@/api/pl/quota-cert'
|
||||
import { certKindLabel, certKindMobileTone } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { bindingPayload, replaceCertProducts } from '@/views/pl/quota-cert/model'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
@@ -178,9 +186,6 @@
|
||||
let epoch = 0
|
||||
let searchTimer = 0
|
||||
|
||||
const currentLabel = computed(() =>
|
||||
[certType.value === 'purchase' ? '购买证' : '运输证', certNo.value].filter(Boolean).join(' ')
|
||||
)
|
||||
const pickerRows = computed(() => {
|
||||
const used = new Set(draft.value.map((product) => product.contractProductId))
|
||||
return lines.value.filter((row) => row.id && !used.has(row.id))
|
||||
|
||||
@@ -15,9 +15,13 @@
|
||||
@click="open(row)"
|
||||
>
|
||||
<div class="mp-wv-card__head">
|
||||
<div>
|
||||
<div class="mp-cert-card__main">
|
||||
<div class="mp-wv-card__no">{{ row.certNo }}</div>
|
||||
<div class="mp-wv-card__sub">{{ row.certType === 'transport' ? '运输证' : '购买证' }}</div>
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(row.certType)}`"
|
||||
>{{ certKindLabel(row.certType) }}</span
|
||||
>
|
||||
</div>
|
||||
<span class="status-tag" :class="`status-tag--${row.status === 'active' ? 'success' : 'info'}`">
|
||||
{{ certListStatus(row.status) }}
|
||||
@@ -61,7 +65,11 @@
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
import { certListStatus } from './usage-model'
|
||||
import { expiryWarning } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import {
|
||||
certKindLabel,
|
||||
certKindMobileTone,
|
||||
expiryWarning
|
||||
} from '@/views/pl/quota-cert/cert-list-face'
|
||||
|
||||
const props = defineProps<{ keyword: string; kind: string }>()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -37,6 +37,24 @@
|
||||
min-height: calc(100dvh - 132px);
|
||||
}
|
||||
|
||||
.mp-cert-kind-tag {
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
align-self: flex-start;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.mp-cert-kind-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.mp-plan-cert-list .mp-wv-flat-card {
|
||||
.mp-cert-card__main {
|
||||
display: flex;
|
||||
@@ -46,10 +64,7 @@
|
||||
}
|
||||
|
||||
.mp-cert-kind-tag {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
margin-top: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mp-wv-card__no {
|
||||
|
||||
@@ -48,7 +48,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="mp-cert-tags">
|
||||
<span class="status-tag status-tag--info">{{ cert.certType === 'purchase' ? '购买证' : '运输证' }}</span>
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(cert.certType)}`"
|
||||
>{{ certKindLabel(cert.certType) }}</span
|
||||
>
|
||||
<span class="status-tag" :class="`status-tag--${cert.linkStatus === 'active' ? 'success' : 'info'}`">
|
||||
{{ linkLabel(cert.linkStatus) }}
|
||||
</span>
|
||||
@@ -145,7 +149,14 @@
|
||||
<div class="mp-wv-card__kv">
|
||||
<div class="mp-wv-card__kv-row"><span>规格</span><span>{{ row.model }}</span></div>
|
||||
<div class="mp-wv-card__kv-row"><span>产品单位</span><span>{{ unit(row.unit) || '—' }}</span></div>
|
||||
<div class="mp-wv-card__kv-row"><span>证件类型</span><span>{{ row.certKind }}</span></div>
|
||||
<div class="mp-wv-card__kv-row">
|
||||
<span>证件类型</span>
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(row.certType)}`"
|
||||
>{{ row.certKind }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="mp-wv-card__kv-row"><span>证件编号</span><span>{{ row.certNo }}</span></div>
|
||||
<div class="mp-wv-card__kv-row"><span>证面单位</span><span>{{ unit(row.certUnit) || '—' }}</span></div>
|
||||
<div class="mp-wv-card__kv-row"><span>产品预占</span><span>{{ qty(row.reservedQty) }}</span></div>
|
||||
@@ -188,7 +199,11 @@
|
||||
type StatisticsProduct
|
||||
} from '@/api/pl/quota-cert'
|
||||
import { bindingPayload, formatCertQty } from '@/views/pl/quota-cert/model'
|
||||
import { certFaceFields } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import {
|
||||
certFaceFields,
|
||||
certKindLabel,
|
||||
certKindMobileTone
|
||||
} from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { contractTypeLabel } from '@/views/pl/quota-statistics/labels'
|
||||
import { showCrmConfirmDialog } from '@/utils/mp-crm-confirm'
|
||||
import CertLinkSheet from './CertLinkSheet.vue'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ContractStatistics } from '@/api/pl/quota-cert'
|
||||
import { certFaceFields, expiryWarning } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { certFaceFields, certKindLabel, expiryWarning } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { statusLabel } from '@/views/pl/quota-statistics/labels'
|
||||
|
||||
export function certDetailStatus(status?: string | null) {
|
||||
@@ -19,7 +19,8 @@ export function contractProductRows(detail: ContractStatistics) {
|
||||
productName: product.productName || '—',
|
||||
model: product.model || '—',
|
||||
unit: product.unit,
|
||||
certKind: cert.certType === 'purchase' ? '购买证' : '运输证',
|
||||
certType: cert.certType,
|
||||
certKind: certKindLabel(cert.certType),
|
||||
certNo: cert.certNo || '—',
|
||||
certUnit: cert.quantityUnit,
|
||||
reservedQty: product.reservedQty,
|
||||
|
||||
@@ -9,7 +9,14 @@
|
||||
<div v-else-if="loading" class="mp-cert-page-loading"><van-loading /></div>
|
||||
<template v-else-if="detail">
|
||||
<section class="mp-wv-section">
|
||||
<h3>{{ detail.certType === 'transport' ? '运输证' : '购买证' }} {{ detail.certNo }}</h3>
|
||||
<h3 class="mp-cert-kind-heading">
|
||||
<span
|
||||
class="status-tag mp-cert-kind-tag"
|
||||
:class="`status-tag--${certKindMobileTone(detail.certType)}`"
|
||||
>{{ certKindLabel(detail.certType) }}</span
|
||||
>
|
||||
<span>{{ detail.certNo }}</span>
|
||||
</h3>
|
||||
<div class="detail-field-grid">
|
||||
<div class="mp-wv-kv"><span>证面品名</span><span>{{ detail.productNameOnCert || '—' }}</span></div>
|
||||
<div class="mp-wv-kv">
|
||||
@@ -101,6 +108,7 @@
|
||||
import MpWebviewShell from '@/layouts/MpWebviewShell.vue'
|
||||
import MpBusinessHeader from '@/components/mp/MpBusinessHeader.vue'
|
||||
import { quotaStatisticsApi, type CertificateStatistics, type CertType } from '@/api/pl/quota-cert'
|
||||
import { certKindLabel, certKindMobileTone } from '@/views/pl/quota-cert/cert-list-face'
|
||||
import { formatCertQty } from '@/views/pl/quota-cert/model'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
|
||||
@@ -116,6 +116,13 @@
|
||||
:readonly="c.props.readonly"
|
||||
@update:model-value="c.patchDelivery(index, { notes: $event })"
|
||||
/>
|
||||
<van-cell class="mp-stop-toggle" title="是否同市" label="同市只需购买证"
|
||||
><template #right-icon
|
||||
><van-switch
|
||||
:model-value="delivery.sameCity === 1"
|
||||
:disabled="c.props.readonly"
|
||||
@update:model-value="c.patchDelivery(index, { sameCity: $event ? 1 : 0 })" /></template
|
||||
></van-cell>
|
||||
<van-cell
|
||||
class="mp-stop-toggle"
|
||||
title="生成地磅单"
|
||||
|
||||
@@ -61,6 +61,13 @@
|
||||
:readonly="c.props.readonly"
|
||||
@update:model-value="c.patch({ notes: $event })"
|
||||
/>
|
||||
<van-cell class="mp-stop-toggle" title="是否同市" label="同市只需购买证"
|
||||
><template #right-icon
|
||||
><van-switch
|
||||
:model-value="c.props.modelValue.sameCity === 1"
|
||||
:disabled="c.props.readonly"
|
||||
@update:model-value="c.patch({ sameCity: $event ? 1 : 0 })" /></template
|
||||
></van-cell>
|
||||
<van-cell class="mp-stop-toggle" title="生成地磅单" :label="c.dibangDirectionLabel"
|
||||
><template #right-icon
|
||||
><van-switch
|
||||
|
||||
@@ -34,6 +34,28 @@ export function certFaceFields(row: CertListFace) {
|
||||
]
|
||||
}
|
||||
|
||||
export function certKindLabel(certType?: string | null) {
|
||||
return certType === 'transport' ? '运输证' : '购买证'
|
||||
}
|
||||
|
||||
export function certKindTagType(certType?: string | null) {
|
||||
return certType === 'transport' ? 'warning' : 'success'
|
||||
}
|
||||
|
||||
export function certKindMobileTone(certType?: string | null) {
|
||||
return certType === 'transport' ? 'warning' : 'primary'
|
||||
}
|
||||
|
||||
export function compareCertUploadTime<T extends { createTime?: string | null; id?: string | null }>(
|
||||
a: T,
|
||||
b: T
|
||||
) {
|
||||
return (
|
||||
String(b.createTime || '').localeCompare(String(a.createTime || '')) ||
|
||||
String(b.id || '').localeCompare(String(a.id || ''))
|
||||
)
|
||||
}
|
||||
|
||||
export function expiryWarning(validTo?: string | null, today = new Date()) {
|
||||
const target = calendarDate(validTo)
|
||||
if (!target) return null
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
><el-tag
|
||||
v-else-if="column.prop === 'certType'"
|
||||
size="small"
|
||||
:type="row.certType === 'transport' ? 'warning' : 'success'"
|
||||
>{{ row.certType === 'transport' ? '运输证' : '购买证' }}</el-tag
|
||||
:type="certKindTagType(row.certType)"
|
||||
>{{ certKindLabel(row.certType) }}</el-tag
|
||||
><el-tag
|
||||
v-else-if="column.prop === 'status'"
|
||||
size="small"
|
||||
@@ -629,7 +629,14 @@
|
||||
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
|
||||
import CertContractBinder from './CertContractBinder.vue'
|
||||
import { bindingsFromPurchaseCerts, matchPurchaseCert } from './contract-binder-rules'
|
||||
import { buyPartyName, expiryWarning, salePartyName } from './cert-list-face'
|
||||
import {
|
||||
buyPartyName,
|
||||
certKindLabel,
|
||||
certKindTagType,
|
||||
compareCertUploadTime,
|
||||
expiryWarning,
|
||||
salePartyName
|
||||
} from './cert-list-face'
|
||||
import ContractScopeDialog from './ContractScopeDialog.vue'
|
||||
import SystemViewDialog, {
|
||||
type ViewField,
|
||||
@@ -1089,11 +1096,7 @@
|
||||
rows.value = [
|
||||
...purchases.map((row) => presentCert(row, 'purchase')),
|
||||
...transports.map((row) => presentCert(row, 'transport'))
|
||||
].sort(
|
||||
(a, b) =>
|
||||
String(b.createTime || '').localeCompare(String(a.createTime || '')) ||
|
||||
String(b.id).localeCompare(String(a.id))
|
||||
)
|
||||
].sort(compareCertUploadTime)
|
||||
} finally {
|
||||
if (current === listEpoch && !disposed) loading.value = false
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p v-else class="quota-contract-cert-dialog__current">{{ currentCertLabel }}</p>
|
||||
<p v-else class="quota-contract-cert-dialog__current">
|
||||
<el-tag size="small" :type="certKindTagType(certType)">{{ certKindLabel(certType) }}</el-tag>
|
||||
<span v-if="certNo">{{ certNo }}</span>
|
||||
</p>
|
||||
<CertContractBinder
|
||||
v-if="ready && certId && contractId"
|
||||
:key="binderKey"
|
||||
@@ -68,6 +71,7 @@
|
||||
type ScopeProduct
|
||||
} from '@/api/pl/quota-cert'
|
||||
import CertContractBinder from '../quota-cert/CertContractBinder.vue'
|
||||
import { certKindLabel, certKindTagType } from '../quota-cert/cert-list-face'
|
||||
import { bindingPayload, replaceCertProducts } from '../quota-cert/model'
|
||||
|
||||
const emit = defineEmits<{ saved: [] }>()
|
||||
@@ -91,10 +95,6 @@
|
||||
() =>
|
||||
`${mode.value}|${certType.value}|${certId.value}|${savedProducts.value.map((row) => row.contractProductId).join(',')}`
|
||||
)
|
||||
const currentCertLabel = computed(() =>
|
||||
[certType.value === 'purchase' ? '购买证' : '运输证', certNo.value].filter(Boolean).join(' ')
|
||||
)
|
||||
|
||||
function certOptionLabel(item: QuotaCert) {
|
||||
const name = [item.certNo, item.productNameOnCert].filter(Boolean).join(' · ')
|
||||
if (item.status === 'void') return `${name}(已作废)`
|
||||
@@ -209,6 +209,10 @@
|
||||
|
||||
<style scoped>
|
||||
.quota-contract-cert-dialog__current {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
margin: 0 0 12px;
|
||||
color: #1e293b;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -6,8 +6,15 @@
|
||||
v-for="cert in contract?.certificates || []"
|
||||
:key="certKey(cert)"
|
||||
:name="certKey(cert)"
|
||||
:label="certTabLabel(cert)"
|
||||
>
|
||||
<template #label>
|
||||
<span class="quota-cert-tab-label">
|
||||
<el-tag size="small" :type="certKindTagType(cert.certType)">{{
|
||||
certKindLabel(cert.certType)
|
||||
}}</el-tag>
|
||||
<span>{{ cert.certNo }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<section class="quota-cert-summary">
|
||||
<header class="quota-cert-summary__head">
|
||||
<strong>{{ cert.certNo }}</strong>
|
||||
@@ -16,8 +23,8 @@
|
||||
有效期:{{ cert.validFrom || '—' }} 至 {{ cert.validTo || '—' }}
|
||||
</span>
|
||||
<div class="quota-cert-summary__tags">
|
||||
<el-tag size="small">{{
|
||||
cert.certType === 'purchase' ? '购买证' : '运输证'
|
||||
<el-tag size="small" :type="certKindTagType(cert.certType)">{{
|
||||
certKindLabel(cert.certType)
|
||||
}}</el-tag>
|
||||
<el-tag size="small" :type="cert.linkStatus === 'active' ? 'success' : 'info'">{{
|
||||
linkLabel(cert.linkStatus)
|
||||
@@ -90,7 +97,13 @@
|
||||
<el-table-column prop="productName" label="产品" min-width="160" />
|
||||
<el-table-column prop="model" label="规格" min-width="120" />
|
||||
<el-table-column prop="unit" label="产品单位" min-width="100" />
|
||||
<el-table-column prop="certKind" label="证件类型" min-width="100" />
|
||||
<el-table-column label="证件类型" min-width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" :type="certKindTagType(row.certType)">{{
|
||||
row.certKind
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="certNo" label="证件编号" min-width="160" />
|
||||
<el-table-column prop="certUnit" label="证面单位" min-width="100" />
|
||||
<el-table-column label="产品预占" min-width="120"
|
||||
@@ -230,7 +243,12 @@
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { getProductUnitLabel } from '@/utils/crm-product-display'
|
||||
import { formatCertQty } from '../quota-cert/model'
|
||||
import { certFaceFields, expiryWarning } from '../quota-cert/cert-list-face'
|
||||
import {
|
||||
certFaceFields,
|
||||
certKindLabel,
|
||||
certKindTagType,
|
||||
expiryWarning
|
||||
} from '../quota-cert/cert-list-face'
|
||||
import StatisticsProducts from './StatisticsProducts.vue'
|
||||
import { statusLabel } from './labels'
|
||||
const props = withDefaults(
|
||||
@@ -252,10 +270,6 @@
|
||||
function certKey(cert: { certType: string; certId: string }) {
|
||||
return `${cert.certType}:${cert.certId}`
|
||||
}
|
||||
function certTabLabel(cert: ContractStatistics['certificates'][number]) {
|
||||
const kind = cert.certType === 'purchase' ? '购买证' : '运输证'
|
||||
return `${kind} ${cert.certNo || ''}`.trim()
|
||||
}
|
||||
watch(
|
||||
() =>
|
||||
props.mode === 'contract'
|
||||
@@ -282,7 +296,8 @@
|
||||
productName: product.productName || '—',
|
||||
model: product.model || '—',
|
||||
unit: unitLabel(product.unit) || '—',
|
||||
certKind: cert.certType === 'purchase' ? '购买证' : '运输证',
|
||||
certType: cert.certType,
|
||||
certKind: certKindLabel(cert.certType),
|
||||
certNo: cert.certNo || '—',
|
||||
certUnit: unitLabel(cert.quantityUnit) || '—',
|
||||
reservedQty: product.reservedQty,
|
||||
@@ -475,4 +490,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.quota-cert-tab-label {
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -144,9 +144,11 @@
|
||||
/> </div
|
||||
></template>
|
||||
<template #default="{ row }"
|
||||
><span v-if="column.prop === 'certType'">{{
|
||||
row.certType === 'transport' ? '运输证' : '购买证'
|
||||
}}</span
|
||||
><el-tag
|
||||
v-if="column.prop === 'certType'"
|
||||
size="small"
|
||||
:type="certKindTagType(row.certType)"
|
||||
>{{ certKindLabel(row.certType) }}</el-tag
|
||||
><el-tag
|
||||
v-else-if="column.prop === 'status'"
|
||||
size="small"
|
||||
@@ -205,7 +207,7 @@
|
||||
import StatisticsDetail from './StatisticsDetail.vue'
|
||||
import { createStatisticsLoader } from './loader'
|
||||
import { statusLabel, contractTypeLabel } from './labels'
|
||||
import { expiryWarning } from '../quota-cert/cert-list-face'
|
||||
import { certKindLabel, certKindTagType, expiryWarning } from '../quota-cert/cert-list-face'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
mode: 'contract' | 'certificate'
|
||||
|
||||
Reference in new issue
Block a user