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