diff --git a/web-admin/src/components/business/product-selector/index.vue b/web-admin/src/components/business/product-selector/index.vue index 749a8185e..9fb7d306a 100644 --- a/web-admin/src/components/business/product-selector/index.vue +++ b/web-admin/src/components/business/product-selector/index.vue @@ -21,7 +21,12 @@ @search="handleQuickSearch" @clear="handleQuickSearchClear" /> - + 新增 () const emit = defineEmits<{ @@ -271,12 +279,20 @@ const formDialogVisible = ref(false) const formProductId = ref(null) const pendingSelectId = ref(null) + /** 限制模式下打开弹窗后「无产品」提示只打一次 */ + let emptyAllowedWarnedOnOpen = false + + const normalizedAllowedIds = computed(() => + (props.allowedProductIds || []).map((id) => String(id).trim()).filter(Boolean) + ) + const isRestrictedMode = computed(() => normalizedAllowedIds.value.length > 0) watch( () => props.visible, (val) => { dialogVisible.value = val if (val) { + emptyAllowedWarnedOnOpen = false quickSearchKeyword.value = '' queryParams.value.pageNum = 1 getList() @@ -316,9 +332,50 @@ return names.length ? names.join('、') : '-' } + function matchesQuickKeyword(product: ProductVO, keyword: string) { + const kw = keyword.toLowerCase() + const name = String(product.productName || '').toLowerCase() + const model = String(product.model || '').toLowerCase() + return name.includes(kw) || model.includes(kw) + } + + /** 按允许的产品 id 并行拉详情,避免分页目录漏选 */ + const getRestrictedList = async () => { + const ids = normalizedAllowedIds.value + const results = await Promise.all( + ids.map(async (id) => { + try { + const res: any = await fetchProductDetail({ id }) + const data = res?.data ?? res + return data?.id != null ? (data as ProductVO) : null + } catch { + return null + } + }) + ) + const fetched = results.filter((p): p is ProductVO => p != null) + if (!fetched.length && !emptyAllowedWarnedOnOpen) { + emptyAllowedWarnedOnOpen = true + ElMessage.warning('所选合同暂无产品明细') + } + const keyword = quickSearchKeyword.value?.trim() + const list = keyword ? fetched.filter((p) => matchesQuickKeyword(p, keyword)) : fetched + productList.value = list + total.value = list.length + if (categoryTree.value.length > 0) { + resolveCategoryNames() + } + await nextTick() + await selectPendingRow() + } + const getList = async () => { loading.value = true try { + if (isRestrictedMode.value) { + await getRestrictedList() + return + } const keyword = quickSearchKeyword.value?.trim() const res = await fetchProductList({ page: queryParams.value.pageNum,