feat(pl): show available contract qty before plan qty in stop products
Add contract-product-arrange-qty API and form UI with green available qty, red plan qty over-hint, and click-through dialog for usage and plan list. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
3011cb9dae
commit
81b1cb9b1d
10 files changed
+1227
-11
No files matched your search
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="modelValue"
|
||||
class="dialog-form-layout pl-contract-product-arrange-qty-dialog"
|
||||
:title="dialogTitle"
|
||||
width="640px"
|
||||
align-center
|
||||
destroy-on-close
|
||||
append-to-body
|
||||
modal-class="order-module-dialog-mask"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
>
|
||||
<div v-loading="loading" class="arrange-qty-body">
|
||||
<p v-if="subtitle" class="arrange-qty-sub">{{ subtitle }}</p>
|
||||
<div class="arrange-qty-stats">
|
||||
<div class="arrange-qty-stat">
|
||||
<div class="k">合同数量</div>
|
||||
<div class="v">{{ contractQtyText }}</div>
|
||||
</div>
|
||||
<div class="arrange-qty-stat">
|
||||
<div class="k">已安排</div>
|
||||
<div class="v">{{ formatQty(detail?.arrangedQty) }}</div>
|
||||
</div>
|
||||
<div class="arrange-qty-stat">
|
||||
<div class="k">可安排</div>
|
||||
<div class="v is-avail">{{ availableQtyText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arrange-qty-list-title">已安排本产品的运输计划</div>
|
||||
<el-table
|
||||
v-if="(detail?.plans || []).length"
|
||||
:data="detail?.plans || []"
|
||||
class="list-table"
|
||||
stripe
|
||||
size="small"
|
||||
max-height="280"
|
||||
>
|
||||
<el-table-column prop="planNo" label="计划编号" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="planDate" label="计划日期" min-width="110" />
|
||||
<el-table-column label="计划数量" min-width="100" align="right">
|
||||
<template #default="{ row }">{{ formatQty(row.planQty) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template #default="{ row }">{{ statusLabel(row) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<p v-else class="arrange-qty-empty">暂无已安排计划</p>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="emit('update:modelValue', false)">
|
||||
<el-icon><Check /></el-icon>知道了
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Check } from '@element-plus/icons-vue'
|
||||
import { planApi, type ContractProductArrangeQtyDetail } from '@/api/pl'
|
||||
import { pickBxData } from '@/utils/http/bx'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
contractId?: string
|
||||
productId?: string
|
||||
productName?: string
|
||||
excludePlanId?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{ 'update:modelValue': [boolean] }>()
|
||||
|
||||
const loading = ref(false)
|
||||
const detail = ref<ContractProductArrangeQtyDetail | null>(null)
|
||||
|
||||
const dialogTitle = computed(
|
||||
() => `合同用量 · ${props.productName || detail.value?.productName || '产品'}`
|
||||
)
|
||||
const subtitle = computed(() => {
|
||||
const d = detail.value
|
||||
if (!d) return ''
|
||||
const parts = [d.customerName, d.contractNo].filter(Boolean)
|
||||
return parts.join(' - ')
|
||||
})
|
||||
const contractQtyText = computed(() => {
|
||||
if (!detail.value) return '—'
|
||||
if (!detail.value.hasFixedQty) return '按客户需求'
|
||||
return formatQty(detail.value.contractQty)
|
||||
})
|
||||
const availableQtyText = computed(() => {
|
||||
if (!detail.value) return '—'
|
||||
if (!detail.value.hasFixedQty) return '不限额'
|
||||
return formatQty(detail.value.availableQty)
|
||||
})
|
||||
|
||||
function formatQty(n: number | null | undefined) {
|
||||
if (n == null || Number.isNaN(Number(n))) return '—'
|
||||
return Number(n).toFixed(3)
|
||||
}
|
||||
|
||||
function statusLabel(row: { archiveStatus?: string; followStatus?: string; transportStatus?: string }) {
|
||||
const archive = (row.archiveStatus || '').trim()
|
||||
if (archive === 'archived') return '已归档'
|
||||
const follow = (row.followStatus || '').trim()
|
||||
if (follow === 'completed') return '已完成'
|
||||
if (follow === 'arranged' || row.transportStatus === 'arranged') return '已安排'
|
||||
return follow || row.transportStatus || '—'
|
||||
}
|
||||
|
||||
async function loadDetail() {
|
||||
const contractId = String(props.contractId || '').trim()
|
||||
const productId = String(props.productId || '').trim()
|
||||
if (!contractId || !productId) {
|
||||
detail.value = null
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await planApi.getContractProductArrangeQty({
|
||||
contractId,
|
||||
productId,
|
||||
excludePlanId: props.excludePlanId || undefined
|
||||
})
|
||||
detail.value = pickBxData<ContractProductArrangeQtyDetail>(res) || null
|
||||
} catch {
|
||||
detail.value = null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.modelValue, props.contractId, props.productId, props.excludePlanId] as const,
|
||||
([visible]) => {
|
||||
if (visible) void loadDetail()
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.arrange-qty-body {
|
||||
min-height: 120px;
|
||||
}
|
||||
.arrange-qty-sub {
|
||||
margin: 0 0 12px;
|
||||
font-size: 13px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
}
|
||||
.arrange-qty-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.arrange-qty-stat {
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--el-border-color-lighter, #e2e8f0);
|
||||
background: #f8fafc;
|
||||
.k {
|
||||
font-size: 11px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
}
|
||||
.v {
|
||||
margin-top: 2px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
&.is-avail {
|
||||
color: #059669;
|
||||
}
|
||||
}
|
||||
}
|
||||
.arrange-qty-list-title {
|
||||
margin: 0 0 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.arrange-qty-empty {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
}
|
||||
</style>
|
||||
@@ -201,6 +201,8 @@
|
||||
:compact="compactProducts"
|
||||
:allow-remove="!readonly"
|
||||
:shared-readonly="true"
|
||||
:contract-id="deliveryContractId(delivery)"
|
||||
:exclude-plan-id="excludePlanId"
|
||||
@remove="(productIndex) => removeStopProduct(index, productIndex)"
|
||||
/>
|
||||
</article>
|
||||
@@ -234,13 +236,15 @@
|
||||
qtyUnitLabel?: string
|
||||
/** 多送货段时提示拆分数量 */
|
||||
showSplitHint?: boolean
|
||||
excludePlanId?: string
|
||||
}>(),
|
||||
{
|
||||
tabMode: true,
|
||||
readonly: false,
|
||||
compactProducts: true,
|
||||
qtyUnitLabel: '',
|
||||
showSplitHint: false
|
||||
showSplitHint: false,
|
||||
excludePlanId: ''
|
||||
}
|
||||
)
|
||||
|
||||
@@ -259,6 +263,10 @@
|
||||
}
|
||||
|
||||
const activeIndex = ref(0)
|
||||
|
||||
function deliveryContractId(delivery: PlanDeliveryForm) {
|
||||
return String(delivery.contracts?.[0]?.contractId || '').trim()
|
||||
}
|
||||
const customerOptionsByIndex = ref<Record<number, CustomerOptionRow[]>>({})
|
||||
const customerOptionsLoading = ref<Record<number, boolean>>({})
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
ref="loadSectionRef"
|
||||
v-model="loadForm"
|
||||
compact-products
|
||||
:exclude-plan-id="planId || ''"
|
||||
@open-customer-picker="openCustomerSelector('load')"
|
||||
@add-products="productSelectorVisible = true"
|
||||
/>
|
||||
@@ -230,6 +231,7 @@
|
||||
compact-products
|
||||
:qty-unit-label="planQtyUnitLabel"
|
||||
:show-split-hint="showDeliverySplitHint"
|
||||
:exclude-plan-id="planId || ''"
|
||||
@active-index-change="deliveryActiveIndex = $event"
|
||||
@open-customer-picker="openCustomerSelector('delivery', $event)"
|
||||
@sync-products="syncDeliveryProductsFromLoadManual"
|
||||
|
||||
@@ -145,6 +145,8 @@
|
||||
:products="modelValue.products"
|
||||
:editable="!readonly"
|
||||
:compact="compactProducts"
|
||||
:contract-id="stopContractId"
|
||||
:exclude-plan-id="excludePlanId"
|
||||
@remove="removeStopProduct"
|
||||
/>
|
||||
</div>
|
||||
@@ -168,10 +170,13 @@
|
||||
modelValue: PlanLoadForm
|
||||
readonly?: boolean
|
||||
compactProducts?: boolean
|
||||
/** 编辑计划时排除本计划占用 */
|
||||
excludePlanId?: string
|
||||
}>(),
|
||||
{
|
||||
readonly: false,
|
||||
compactProducts: true
|
||||
compactProducts: true,
|
||||
excludePlanId: ''
|
||||
}
|
||||
)
|
||||
|
||||
@@ -193,6 +198,11 @@
|
||||
|
||||
const isInternal = computed(() => isPlInternalCustomerName(props.modelValue.customerName))
|
||||
|
||||
const stopContractId = computed(() => {
|
||||
const id = String(props.modelValue.contracts?.[0]?.contractId || '').trim()
|
||||
return id
|
||||
})
|
||||
|
||||
/** 非内部客户须先选装货合同才能添加产品;内部客户不限制 */
|
||||
const addProductsDisabled = computed(() => {
|
||||
if (isInternal.value) return false
|
||||
|
||||
@@ -111,6 +111,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="pl-stop-product-dual-item__row2">
|
||||
<div class="pl-stop-product-dual-item__field">
|
||||
<span class="pl-stop-product-dual-item__label">可安排数量</span>
|
||||
<div class="pl-stop-avail-wrap">
|
||||
<span class="pl-stop-avail-num">{{ formatAvailableDisplay(row) }}</span>
|
||||
<el-button
|
||||
class="pl-stop-avail-help"
|
||||
:disabled="!canOpenArrangeQty(row)"
|
||||
circle
|
||||
size="small"
|
||||
@click="openArrangeQtyDialog(row)"
|
||||
>
|
||||
?
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pl-stop-product-dual-item__field">
|
||||
<span class="pl-stop-product-dual-item__label">计划数量</span>
|
||||
<el-input-number
|
||||
@@ -120,13 +135,17 @@
|
||||
:precision="3"
|
||||
:controls="false"
|
||||
class="pl-plan-product-cell-control pl-stop-product-dual-qty"
|
||||
:class="{ 'is-over-available': isPlanQtyOverAvailable(row) }"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
class="pl-stop-product-dual-item__readonly pl-stop-product-dual-item__qty-text"
|
||||
class="pl-stop-product-dual-item__readonly pl-stop-product-dual-item__qty-text pl-stop-plan-qty"
|
||||
>
|
||||
{{ row.planQty ?? '—' }}
|
||||
</span>
|
||||
<p v-if="editable && isPlanQtyOverAvailable(row)" class="pl-stop-over-tip">
|
||||
已超过可安排数量,安排时将被拦截
|
||||
</p>
|
||||
</div>
|
||||
<div class="pl-stop-product-dual-item__field">
|
||||
<span class="pl-stop-product-dual-item__label">包装规格</span>
|
||||
@@ -246,6 +265,22 @@
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="可安排数量" min-width="120" align="right">
|
||||
<template #default="{ row }">
|
||||
<div class="pl-stop-avail-wrap pl-stop-avail-wrap--table">
|
||||
<span class="pl-stop-avail-num">{{ formatAvailableDisplay(row) }}</span>
|
||||
<el-button
|
||||
class="pl-stop-avail-help"
|
||||
:disabled="!canOpenArrangeQty(row)"
|
||||
circle
|
||||
size="small"
|
||||
@click="openArrangeQtyDialog(row)"
|
||||
>
|
||||
?
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划数量" min-width="110" align="right">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
@@ -255,8 +290,12 @@
|
||||
:precision="3"
|
||||
:controls="false"
|
||||
style="width: 100%"
|
||||
:class="{ 'is-over-available': isPlanQtyOverAvailable(row) }"
|
||||
/>
|
||||
<span v-else>{{ row.planQty ?? '—' }}</span>
|
||||
<span v-else class="pl-stop-plan-qty">{{ row.planQty ?? '—' }}</span>
|
||||
<p v-if="editable && isPlanQtyOverAvailable(row)" class="pl-stop-over-tip">
|
||||
已超过可安排数量
|
||||
</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -358,11 +397,20 @@
|
||||
:mode="aliasBrandManageMode"
|
||||
@saved="handleAliasBrandManaged"
|
||||
/>
|
||||
|
||||
<PlContractProductArrangeQtyDialog
|
||||
v-model="arrangeQtyDialogVisible"
|
||||
:contract-id="arrangeQtyContractId"
|
||||
:product-id="arrangeQtyProductId"
|
||||
:product-name="arrangeQtyProductName"
|
||||
:exclude-plan-id="excludePlanId"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Delete, Plus } from '@element-plus/icons-vue'
|
||||
import { planApi, type ContractProductArrangeQtyDetail } from '@/api/pl'
|
||||
import type { PlanStopProductFormRow } from '@/utils/pl-plan-stop-form'
|
||||
import {
|
||||
formatStopArchiveAmount,
|
||||
@@ -378,9 +426,11 @@
|
||||
} from '@/utils/crm-product-brand'
|
||||
import PlProductNameHazardCell from '@/components/business/pl-product-name-hazard-cell/index.vue'
|
||||
import ProductAliasBrandDialog from '@/components/business/product-alias-brand-dialog/index.vue'
|
||||
import PlContractProductArrangeQtyDialog from '@/components/business/pl-contract-product-arrange-qty-dialog/index.vue'
|
||||
import DictTag from '@/components/DictTag/index.vue'
|
||||
import DictSelect from '@/components/DictSelect/index.vue'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { pickBxData } from '@/utils/http/bx'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -398,6 +448,10 @@
|
||||
showStopArchivePrice?: boolean
|
||||
/** 与 showStopActualQty / showStopArchivePrice 配合 */
|
||||
stopArchiveMode?: 'load' | 'delivery'
|
||||
/** 本段合同 id(无则展示 —) */
|
||||
contractId?: string
|
||||
/** 当前编辑计划 id,计算可安排时排除 */
|
||||
excludePlanId?: string
|
||||
}>(),
|
||||
{
|
||||
compact: false,
|
||||
@@ -405,7 +459,9 @@
|
||||
sharedReadonly: false,
|
||||
showStopActualQty: false,
|
||||
showStopArchivePrice: false,
|
||||
stopArchiveMode: 'load'
|
||||
stopArchiveMode: 'load',
|
||||
contractId: '',
|
||||
excludePlanId: ''
|
||||
}
|
||||
)
|
||||
|
||||
@@ -425,6 +481,94 @@
|
||||
const aliasBrandManageProductName = ref('')
|
||||
const aliasBrandManageMode = ref<'alias' | 'brand'>('alias')
|
||||
|
||||
const arrangeQtyCache = ref<Record<string, ContractProductArrangeQtyDetail | null>>({})
|
||||
const arrangeQtyDialogVisible = ref(false)
|
||||
const arrangeQtyContractId = ref('')
|
||||
const arrangeQtyProductId = ref('')
|
||||
const arrangeQtyProductName = ref('')
|
||||
|
||||
function cacheKey(productId: string) {
|
||||
return `${props.contractId || ''}::${productId}::${props.excludePlanId || ''}`
|
||||
}
|
||||
|
||||
async function ensureArrangeQty(productId: string) {
|
||||
const cid = String(props.contractId || '').trim()
|
||||
const pid = String(productId || '').trim()
|
||||
if (!cid || !pid) return null
|
||||
const key = cacheKey(pid)
|
||||
if (key in arrangeQtyCache.value) return arrangeQtyCache.value[key]
|
||||
try {
|
||||
const res = await planApi.getContractProductArrangeQty({
|
||||
contractId: cid,
|
||||
productId: pid,
|
||||
excludePlanId: props.excludePlanId || undefined
|
||||
})
|
||||
const data = pickBxData<ContractProductArrangeQtyDetail>(res) || null
|
||||
arrangeQtyCache.value = { ...arrangeQtyCache.value, [key]: data }
|
||||
return data
|
||||
} catch {
|
||||
arrangeQtyCache.value = { ...arrangeQtyCache.value, [key]: null }
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function formatAvailableDisplay(row: PlanStopProductFormRow) {
|
||||
const cid = String(props.contractId || '').trim()
|
||||
if (!cid) return '—'
|
||||
const pid = String(row.productId || '').trim()
|
||||
if (!pid) return '—'
|
||||
const data = arrangeQtyCache.value[cacheKey(pid)]
|
||||
if (!data) return '…'
|
||||
if (!data.hasFixedQty) return '—'
|
||||
if (data.availableQty == null) return '—'
|
||||
return Number(data.availableQty).toFixed(3)
|
||||
}
|
||||
|
||||
function isPlanQtyOverAvailable(row: PlanStopProductFormRow) {
|
||||
const cid = String(props.contractId || '').trim()
|
||||
const pid = String(row.productId || '').trim()
|
||||
if (!cid || !pid) return false
|
||||
const data = arrangeQtyCache.value[cacheKey(pid)]
|
||||
if (!data?.hasFixedQty || data.availableQty == null) return false
|
||||
const planQty = Number(row.planQty)
|
||||
if (!Number.isFinite(planQty)) return false
|
||||
return planQty > Number(data.availableQty) + 1e-9
|
||||
}
|
||||
|
||||
function canOpenArrangeQty(row: PlanStopProductFormRow) {
|
||||
return Boolean(String(props.contractId || '').trim() && String(row.productId || '').trim())
|
||||
}
|
||||
|
||||
function openArrangeQtyDialog(row: PlanStopProductFormRow) {
|
||||
if (!String(props.contractId || '').trim()) {
|
||||
ElMessage.warning('请先选择合同')
|
||||
return
|
||||
}
|
||||
if (!row.productId) return
|
||||
arrangeQtyContractId.value = String(props.contractId)
|
||||
arrangeQtyProductId.value = String(row.productId)
|
||||
arrangeQtyProductName.value = String(row.productName || row.standardProductName || '')
|
||||
arrangeQtyDialogVisible.value = true
|
||||
}
|
||||
|
||||
watch(
|
||||
() =>
|
||||
[
|
||||
props.contractId,
|
||||
props.excludePlanId,
|
||||
(props.products || []).map((p) => p.productId).join(',')
|
||||
] as const,
|
||||
() => {
|
||||
const cid = String(props.contractId || '').trim()
|
||||
if (!cid) return
|
||||
for (const row of props.products || []) {
|
||||
const pid = String(row.productId || '').trim()
|
||||
if (pid) void ensureArrangeQty(pid)
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
function handleRemove(index: number) {
|
||||
emit('remove', index)
|
||||
}
|
||||
@@ -497,8 +641,63 @@
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.pl-plan-product-cell-control {
|
||||
width: 100%;
|
||||
.pl-stop-avail-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
.pl-stop-avail-wrap--table {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.pl-stop-avail-num {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #059669;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.pl-stop-avail-help {
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
min-height: 22px !important;
|
||||
padding: 0 !important;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #059669;
|
||||
border-color: #a7f3d0;
|
||||
background: #ecfdf5;
|
||||
}
|
||||
|
||||
.pl-stop-plan-qty {
|
||||
color: #dc2626;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pl-stop-over-tip {
|
||||
margin: 4px 0 0;
|
||||
font-size: 11px;
|
||||
line-height: 1.3;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
:deep(.pl-stop-product-dual-qty.is-over-available),
|
||||
:deep(.el-input-number.is-over-available) {
|
||||
.el-input__wrapper {
|
||||
box-shadow: 0 0 0 1px #dc2626 inset;
|
||||
background: #fff5f5;
|
||||
}
|
||||
.el-input__inner {
|
||||
color: #dc2626;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.pl-stop-product-dual-qty .el-input__inner) {
|
||||
color: #dc2626;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pl-stop-product-dual-list {
|
||||
@@ -571,12 +770,13 @@
|
||||
.pl-stop-product-dual-item__label {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
color: #000;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.pl-stop-product-dual-item__readonly {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
word-break: break-all;
|
||||
line-height: 1.4;
|
||||
@@ -610,7 +810,7 @@
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,6 +822,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 产品区可编辑控件:字段值加粗(覆盖 dialog-form-layout 默认 400) */
|
||||
.pl-stop-product-dual-item__field {
|
||||
:deep(.el-input__inner),
|
||||
:deep(.el-textarea__inner),
|
||||
:deep(.el-select__selected-item),
|
||||
:deep(.el-select__placeholder:not(.is-transparent)),
|
||||
:deep(.el-select__wrapper) {
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
:deep(.pl-product-name-hazard__name) {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.line-meta-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user