|
|
@@ -32,33 +32,17 @@
|
|
|
<span class="pl-archive-brand-qty-title">{{ row.productName }} · 按品牌填量</span>
|
|
|
<el-tag v-if="row.brandMode === 'required'" size="small" type="warning">指定品牌</el-tag>
|
|
|
<el-tag v-else size="small" type="info">不限品牌</el-tag>
|
|
|
- <span
|
|
|
- v-if="!isBrandQtySumMatch(row)"
|
|
|
- class="pl-archive-brand-qty-warn"
|
|
|
- >
|
|
|
- 各品牌合计须等于实际数量({{ Number(row.actualQty ?? 0) }})
|
|
|
- </span>
|
|
|
</div>
|
|
|
- <el-table :data="row.brandQtyRows || []" stripe size="small" class="list-table">
|
|
|
- <el-table-column label="品牌" min-width="140" show-overflow-tooltip>
|
|
|
- <template #default="{ row: brandRow }">
|
|
|
- {{ brandRow.brandName || '—' }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column label="数量" min-width="140" align="right">
|
|
|
- <template #default="{ row: brandRow }">
|
|
|
- <el-input-number
|
|
|
- v-model="brandRow.qty"
|
|
|
- :min="0"
|
|
|
- :precision="3"
|
|
|
- :controls="false"
|
|
|
- :disabled="row.brandMode === 'required'"
|
|
|
- style="width: 100%"
|
|
|
- @change="() => onBrandQtyChange(row)"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
+ <BrandQtyChipsField
|
|
|
+ v-model="row.brandQtyRows"
|
|
|
+ :brand-mode="archiveBrandMode(row)"
|
|
|
+ :required-brand-id="row.brandId"
|
|
|
+ :brand-options="row.brandOptions || []"
|
|
|
+ :unit="row.unit || '吨'"
|
|
|
+ variant="admin"
|
|
|
+ :actual-qty="Number(row.actualQty ?? 0)"
|
|
|
+ @update:actual-qty="(val) => onArchiveBrandActualQty(row, val)"
|
|
|
+ />
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
@@ -163,6 +147,7 @@ import {
|
|
|
type PlIoOrder,
|
|
|
type Transport
|
|
|
} from '@/api/pl'
|
|
|
+import BrandQtyChipsField from '@/components/business/brand-qty-chips-field/index.vue'
|
|
|
import PlPlanFormProductTable from '@/components/business/pl-plan-form-dialog/PlPlanFormProductTable.vue'
|
|
|
import PlPlanViewTabs from '@/components/business/pl-plan-view-tabs/index.vue'
|
|
|
import type { PlanFormProductRow } from '@/composables/usePlContractToPlan'
|
|
|
@@ -235,6 +220,11 @@ const brandedProductRows = computed(() =>
|
|
|
productRows.value.filter(row => row.brandMode === 'required' || row.brandMode === 'any')
|
|
|
)
|
|
|
|
|
|
+function archiveBrandMode(row: PlanFormProductRow): 'any' | 'required' | null {
|
|
|
+ if (row.brandMode === 'any' || row.brandMode === 'required') return row.brandMode
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
function brandQtySum(row: PlanFormProductRow): number {
|
|
|
return (row.brandQtyRows || []).reduce((sum, item) => sum + Number(item.qty || 0), 0)
|
|
|
}
|
|
|
@@ -244,9 +234,10 @@ function isBrandQtySumMatch(row: PlanFormProductRow): boolean {
|
|
|
return Math.abs(brandQtySum(row) - Number(row.actualQty ?? 0)) < 0.0005
|
|
|
}
|
|
|
|
|
|
-function onBrandQtyChange(row: PlanFormProductRow) {
|
|
|
+function onArchiveBrandActualQty(row: PlanFormProductRow, val: number) {
|
|
|
+ // any:合计回写实际数量;required:实际数量可在产品表改,芯片数量跟合计联动
|
|
|
if (row.brandMode === 'any') {
|
|
|
- row.actualQty = Number(brandQtySum(row).toFixed(3))
|
|
|
+ row.actualQty = Number(val)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -274,6 +265,7 @@ function mapPlanProducts(products: PlanProduct[]): PlanFormProductRow[] {
|
|
|
brandMode: item.brandMode,
|
|
|
brandId: item.brandId,
|
|
|
brandName: item.brandName,
|
|
|
+ brandOptions: [],
|
|
|
brandQtyRows: [],
|
|
|
model: item.model,
|
|
|
categoryName: item.categoryName,
|
|
|
@@ -315,26 +307,36 @@ async function initBrandQtyRows(rows: PlanFormProductRow[]) {
|
|
|
rows.forEach(row => {
|
|
|
const actual = Number(row.actualQty ?? 0)
|
|
|
if (row.brandMode === 'required') {
|
|
|
- row.brandQtyRows = [
|
|
|
- {
|
|
|
- brandId: row.brandId || '',
|
|
|
- brandName: row.brandName || '指定品牌',
|
|
|
- qty: actual
|
|
|
- }
|
|
|
- ]
|
|
|
+ const option = {
|
|
|
+ brandId: row.brandId || '',
|
|
|
+ brandName: row.brandName || '指定品牌'
|
|
|
+ }
|
|
|
+ row.brandOptions = option.brandId ? [option] : []
|
|
|
+ row.brandQtyRows = option.brandId
|
|
|
+ ? [{ brandId: option.brandId, brandName: option.brandName, qty: actual }]
|
|
|
+ : []
|
|
|
return
|
|
|
}
|
|
|
if (row.brandMode === 'any') {
|
|
|
const brands = (detailMap.get(row.productId)?.brands || []).filter(
|
|
|
b => (b.status || 'on') === 'on'
|
|
|
)
|
|
|
- row.brandQtyRows = brands.map(b => ({
|
|
|
+ row.brandOptions = brands.map(b => ({
|
|
|
brandId: b.id || '',
|
|
|
- brandName: b.brandName,
|
|
|
- qty: 0
|
|
|
+ brandName: b.brandName || ''
|
|
|
}))
|
|
|
- if (row.brandQtyRows.length === 1) {
|
|
|
- row.brandQtyRows[0].qty = actual
|
|
|
+ // 芯片交互:默认不预选;仅单品牌时预填实际数量
|
|
|
+ if (row.brandOptions.length === 1) {
|
|
|
+ row.brandQtyRows = [
|
|
|
+ {
|
|
|
+ brandId: row.brandOptions[0].brandId,
|
|
|
+ brandName: row.brandOptions[0].brandName,
|
|
|
+ qty: actual
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ row.actualQty = actual
|
|
|
+ } else {
|
|
|
+ row.brandQtyRows = []
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
@@ -594,11 +596,6 @@ async function handleSubmit() {
|
|
|
color: #334155;
|
|
|
}
|
|
|
|
|
|
-.pl-archive-brand-qty-warn {
|
|
|
- font-size: 12px;
|
|
|
- color: var(--el-color-danger, #ef4444);
|
|
|
-}
|
|
|
-
|
|
|
.pl-plan-freight-section {
|
|
|
.pl-plan-subtitle {
|
|
|
margin-top: 4px;
|