feat(crm): wire alias/brand manage dialog into contract product lines.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
a80a01b37d
commit
449250518f
1 file changed
+113
-38
@@ -273,47 +273,69 @@
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="别名" min-width="100">
|
||||
<el-table-column label="别名" min-width="140">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-if="(scope.row.aliasOptions || []).length"
|
||||
v-model="scope.row.aliasName"
|
||||
placeholder="不选则用产品名称"
|
||||
clearable
|
||||
filterable
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="name in scope.row.aliasOptions"
|
||||
:key="name"
|
||||
:label="name"
|
||||
:value="name"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else class="text-muted">—</span>
|
||||
<div class="line-meta-cell">
|
||||
<el-select
|
||||
v-if="(scope.row.aliasOptions || []).length"
|
||||
v-model="scope.row.aliasName"
|
||||
placeholder="不选则用产品名称"
|
||||
clearable
|
||||
filterable
|
||||
size="small"
|
||||
class="line-meta-cell__control"
|
||||
>
|
||||
<el-option
|
||||
v-for="name in scope.row.aliasOptions"
|
||||
:key="name"
|
||||
:label="name"
|
||||
:value="name"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else class="text-muted line-meta-cell__empty">—</span>
|
||||
<el-button
|
||||
v-if="scope.row.productId"
|
||||
link
|
||||
type="primary"
|
||||
class="line-meta-cell__btn"
|
||||
@click="openAliasBrandManage(scope.row, 'alias')"
|
||||
>
|
||||
<el-icon><Setting /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="品牌" min-width="100">
|
||||
<el-table-column label="品牌" min-width="140">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-if="(scope.row.brandOptions || []).length"
|
||||
v-model="scope.row.brandId"
|
||||
placeholder="不限品牌"
|
||||
clearable
|
||||
filterable
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
@change="(val) => handleBrandIdChange(scope.row, val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in scope.row.brandOptions"
|
||||
:key="b.id"
|
||||
:label="b.brandName"
|
||||
:value="b.id"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else class="text-muted">—</span>
|
||||
<div class="line-meta-cell">
|
||||
<el-select
|
||||
v-if="(scope.row.brandOptions || []).length"
|
||||
v-model="scope.row.brandId"
|
||||
placeholder="不限品牌"
|
||||
clearable
|
||||
filterable
|
||||
size="small"
|
||||
class="line-meta-cell__control"
|
||||
@change="(val) => handleBrandIdChange(scope.row, val)"
|
||||
>
|
||||
<el-option
|
||||
v-for="b in scope.row.brandOptions"
|
||||
:key="b.id"
|
||||
:label="b.brandName"
|
||||
:value="b.id"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else class="text-muted line-meta-cell__empty">—</span>
|
||||
<el-button
|
||||
v-if="scope.row.productId"
|
||||
link
|
||||
type="primary"
|
||||
class="line-meta-cell__btn"
|
||||
@click="openAliasBrandManage(scope.row, 'brand')"
|
||||
>
|
||||
<el-icon><Setting /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="型号/规格" prop="productModel" min-width="100" :show-overflow-tooltip="true">
|
||||
@@ -548,6 +570,14 @@
|
||||
@confirm="handleProductSelected"
|
||||
/>
|
||||
|
||||
<ProductAliasBrandDialog
|
||||
v-model="aliasBrandManageVisible"
|
||||
:product-id="aliasBrandManageProductId"
|
||||
:product-name="aliasBrandManageProductName"
|
||||
:mode="aliasBrandManageMode"
|
||||
@saved="handleAliasBrandManaged"
|
||||
/>
|
||||
|
||||
<!-- 客户选择器 -->
|
||||
<CustomerSelector :visible="customerSelectorVisible" @update:visible="customerSelectorVisible = $event" @confirm="handleCustomerConfirm" />
|
||||
|
||||
@@ -601,7 +631,8 @@ import {
|
||||
Promotion,
|
||||
Loading,
|
||||
ArrowDown,
|
||||
ArrowUp
|
||||
ArrowUp,
|
||||
Setting
|
||||
} from '@element-plus/icons-vue'
|
||||
import {
|
||||
buildUploadFileListFromField,
|
||||
@@ -614,12 +645,14 @@ import ContractAttachmentPanel from './ContractAttachmentPanel.vue'
|
||||
import { getOpportunity } from '@/api/crm/opportunity'
|
||||
import { getQuote } from '@/api/crm/quote'
|
||||
import ProductSelector from './ProductSelector.vue'
|
||||
import ProductAliasBrandDialog from '@/components/business/product-alias-brand-dialog/index.vue'
|
||||
import CustomerSelector from '@/components/CustomerSelector.vue'
|
||||
import ContactSelector from '@/components/ContactSelector.vue'
|
||||
import QuoteSelector from '@/components/QuoteSelector.vue'
|
||||
import { removeProductsNotAllowedByHazard } from '@/utils/crm-supplier-hazard'
|
||||
import {
|
||||
applyBrandSelectChange,
|
||||
applyManagedProductMetaToLines,
|
||||
initLineBrandMetaFromProduct,
|
||||
prepareLineAliasAndBrandForSubmit,
|
||||
resolveAliasFromSavedName
|
||||
@@ -1682,6 +1715,29 @@ const handleBrandIdChange = (row: ExtendedContractProductForm, val: string | und
|
||||
applyBrandSelectChange(row, val, row.brandOptions || [])
|
||||
}
|
||||
|
||||
const aliasBrandManageVisible = ref(false)
|
||||
const aliasBrandManageProductId = ref('')
|
||||
const aliasBrandManageProductName = ref('')
|
||||
const aliasBrandManageMode = ref<'alias' | 'brand'>('alias')
|
||||
|
||||
function openAliasBrandManage(row: ExtendedContractProductForm, mode: 'alias' | 'brand') {
|
||||
if (!row.productId) return
|
||||
aliasBrandManageProductId.value = String(row.productId)
|
||||
aliasBrandManageProductName.value = String(
|
||||
row.standardProductName || row.productName || ''
|
||||
)
|
||||
aliasBrandManageMode.value = mode
|
||||
aliasBrandManageVisible.value = true
|
||||
}
|
||||
|
||||
function handleAliasBrandManaged(product: Record<string, any>) {
|
||||
applyManagedProductMetaToLines(
|
||||
form.value.products || [],
|
||||
aliasBrandManageProductId.value,
|
||||
product
|
||||
)
|
||||
}
|
||||
|
||||
async function enrichContractProductBrandMeta(lines: ExtendedContractProductForm[]) {
|
||||
await Promise.all(
|
||||
(lines || []).map(async (line) => {
|
||||
@@ -2597,4 +2653,23 @@ const loadSupplierList = async () => {
|
||||
.ml-2 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.line-meta-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
.line-meta-cell__control {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.line-meta-cell__empty {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.line-meta-cell__btn {
|
||||
flex-shrink: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user