From 08c4c2180a78bc2f67141e0bb0943757346bb77b Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 17 七月 2026 14:58:02 +0800
Subject: [PATCH] 银川 1.新增生产计划页面 2.销售订单流程生产流程修改 3.客户管理公私海逻辑修改
---
src/components/crm-customer-select.vue | 166 +++++++++++++++++++++++++++++++++++++------------------
1 files changed, 112 insertions(+), 54 deletions(-)
diff --git a/src/components/crm-customer-select.vue b/src/components/crm-customer-select.vue
index 8f982bc..64dcc12 100644
--- a/src/components/crm-customer-select.vue
+++ b/src/components/crm-customer-select.vue
@@ -1,75 +1,133 @@
<script lang="ts" setup>
import type { CrmCustomerApi } from '#/api/crm/customer';
-import { computed, ref, watch } from 'vue';
+import { computed, ref, useAttrs, watch } from 'vue';
-import { Select } from 'ant-design-vue';
+import { IconifyIcon } from '@vben/icons';
-import { getCustomerSimpleList } from '#/api/crm/customer';
+import { Input, Tooltip } from 'ant-design-vue';
-interface Props {
- value?: number;
- disabled?: boolean;
-}
+import { getCustomer } from '#/api/crm/customer';
-const props = withDefaults(defineProps<Props>(), {
- value: undefined,
- disabled: false,
-});
+import CrmCustomerSelectDialog from './crm-customer-select-dialog.vue';
-const emit = defineEmits(['update:value', 'change']);
+defineOptions({ name: 'CrmCustomerSelect', inheritAttrs: false });
-const customerList = ref<CrmCustomerApi.Customer[]>([]);
-const loading = ref(false);
-
-const options = computed(() => {
- return customerList.value.map((item) => ({
- label: item.name,
- value: item.id,
- }));
-});
-
-const selectedValue = ref(props.value);
-
-watch(
- () => props.value,
- (val) => {
- selectedValue.value = val;
+const props = withDefaults(
+ defineProps<{
+ allowClear?: boolean;
+ disabled?: boolean;
+ modelValue?: number;
+ placeholder?: string;
+ }>(),
+ {
+ allowClear: true,
+ disabled: false,
+ modelValue: undefined,
+ placeholder: '璇烽�夋嫨瀹㈡埛',
},
);
+const emit = defineEmits<{
+ change: [item: CrmCustomerApi.Customer | undefined];
+ 'update:modelValue': [value: number | undefined];
+}>();
+const attrs = useAttrs();
+const dialogRef = ref<InstanceType<typeof CrmCustomerSelectDialog>>();
+const hovering = ref(false);
+const selectedItem = ref<CrmCustomerApi.Customer>();
-watch(selectedValue, (val) => {
- emit('update:value', val);
- const customer = customerList.value.find((item) => item.id === val);
- emit('change', customer);
-});
+const displayLabel = computed(() => selectedItem.value?.name ?? '');
+const showClear = computed(
+ () =>
+ props.allowClear &&
+ !props.disabled &&
+ hovering.value &&
+ props.modelValue !== null,
+);
-async function loadCustomers() {
- if (customerList.value.length > 0) return;
- loading.value = true;
- try {
- customerList.value = await getCustomerSimpleList();
- } finally {
- loading.value = false;
+async function resolveCustomerById(id: number | undefined) {
+ if (!id) {
+ selectedItem.value = undefined;
+ return;
}
+ if (selectedItem.value?.id === id) {
+ return;
+ }
+ selectedItem.value = await getCustomer(id);
}
-function filterOption(input: string, option: any) {
- return option.label.toLowerCase().includes(input.toLowerCase());
+watch(
+ () => props.modelValue,
+ (value) => {
+ resolveCustomerById(value);
+ },
+ { immediate: true },
+);
+
+function clearSelected() {
+ selectedItem.value = undefined;
+ emit('update:modelValue', undefined);
+ emit('change', undefined);
}
-loadCustomers();
+function handleClick(event: MouseEvent) {
+ if (props.disabled) {
+ return;
+ }
+ const target = event.target as HTMLElement;
+ if (showClear.value && target.closest('.ant-input-suffix')) {
+ event.stopPropagation();
+ clearSelected();
+ return;
+ }
+ const selectedIds = (
+ props.modelValue === null ? [] : [props.modelValue]
+ ) as number[];
+ dialogRef.value?.open(selectedIds, { multiple: false });
+}
+
+function handleSelected(rows: CrmCustomerApi.Customer[]) {
+ const item = rows[0];
+ if (!item) {
+ return;
+ }
+ selectedItem.value = item;
+ emit('update:modelValue', item.id);
+ emit('change', item);
+}
</script>
<template>
- <Select
- v-model:value="selectedValue"
- :options="options"
- :loading="loading"
- :disabled="disabled"
- placeholder="璇烽�夋嫨瀹㈡埛"
- show-search
- :filter-option="filterOption"
- allow-clear
- />
-</template>
\ No newline at end of file
+ <div
+ v-bind="attrs"
+ class="w-full"
+ :class="disabled ? 'cursor-not-allowed' : 'cursor-pointer'"
+ @click="handleClick"
+ @mouseenter="hovering = true"
+ @mouseleave="hovering = false"
+ >
+ <Tooltip :mouse-enter-delay="0.5" :open="selectedItem ? undefined : false">
+ <template #title>
+ <div v-if="selectedItem" class="leading-6">
+ <div>鍚嶇О锛歿{ selectedItem.name || '-' }}</div>
+ <div>鎵嬫満锛歿{ selectedItem.mobile || '-' }}</div>
+ <div>鍦板尯锛歿{ selectedItem.areaName || '-' }}</div>
+ </div>
+ </template>
+ <Input
+ :disabled="disabled"
+ :placeholder="placeholder"
+ :value="displayLabel"
+ readonly
+ >
+ <template #suffix>
+ <IconifyIcon
+ class="size-4"
+ :icon="showClear ? 'lucide:circle-x' : 'lucide:search'"
+ />
+ </template>
+ </Input>
+ </Tooltip>
+ </div>
+ <CrmCustomerSelectDialog ref="dialogRef" @selected="handleSelected" />
+</template>
--
Gitblit v1.9.3