liu
3 天以前 e47bc9e53ed3d64016c1e0db67d280e63b367e07
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<script lang="ts" setup>
import type { AftersalesTicketApi } from '#/api/aftersales/ticket';
 
import { computed, ref, useAttrs, watch } from 'vue';
 
import { IconifyIcon } from '@vben/icons';
 
import { Input, Tooltip } from 'ant-design-vue';
 
import { getTicket } from '#/api/aftersales/ticket';
 
import AftersalesTicketSelectDialog from './select-dialog.vue';
 
defineOptions({ name: 'AftersalesTicketSelect', inheritAttrs: false });
 
const props = withDefaults(
  defineProps<{
    allowClear?: boolean;
    disabled?: boolean;
    modelValue?: number;
    placeholder?: string;
  }>(),
  {
    allowClear: true,
    disabled: false,
    modelValue: undefined,
    placeholder: '请选择售后工单',
  },
);
 
const emit = defineEmits(['change', 'update:modelValue']);
 
const attrs = useAttrs();
const dialogRef = ref<InstanceType<typeof AftersalesTicketSelectDialog>>();
const hovering = ref(false);
const selectedItem = ref<AftersalesTicketApi.Ticket>();
 
const displayLabel = computed(() => selectedItem.value?.no ?? '');
const showClear = computed(
  () => props.allowClear && !props.disabled && hovering.value && props.modelValue !== null,
);
 
async function resolveItemById(id: number | undefined) {
  if (!id) { selectedItem.value = undefined; return; }
  if (selectedItem.value?.id === id) return;
  selectedItem.value = await getTicket(id);
}
 
watch(() => props.modelValue, (value) => { resolveItemById(value); }, { immediate: true });
 
function clearSelected() {
  selectedItem.value = undefined;
  emit('update:modelValue', undefined);
  emit('change', undefined);
}
 
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: AftersalesTicketApi.Ticket[]) {
  const item = rows[0];
  if (!item) return;
  selectedItem.value = item;
  emit('update:modelValue', item.id);
  emit('change', item);
}
</script>
 
<template>
  <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.no || '-' }}</div>
          <div>主题:{{ selectedItem.name || '-' }}</div>
          <div>客户:{{ selectedItem.customerName || '-' }}</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>
  <AftersalesTicketSelectDialog ref="dialogRef" @selected="handleSelected" />
</template>