bowen
2023-10-10 30b3ee5c89c31cb5794faab40e800c36507d258a
提交 | 用户 | age
cd8e92 1 <template>
52257f 2   <div :class="bem()" class="flex px-2 py-1.5 items-center">
V 3     <slot name="headerTitle" v-if="slots.headerTitle"></slot>
4     <BasicTitle :helpMessage="helpMessage" v-if="!slots.headerTitle && title">
8a1406 5       {{ title }}
V 6     </BasicTitle>
3b6b4f 7     <div
cb1759 8       class="flex items-center flex-1 cursor-pointer justify-self-stretch"
3b6b4f 9       v-if="search || toolbar"
L 10     >
11       <div :class="getInputSearchCls" v-if="search">
8a1406 12         <InputSearch
V 13           :placeholder="t('common.searchText')"
14           size="small"
15           allowClear
60577d 16           v-model:value="searchValue"
8a1406 17         />
cd8e92 18       </div>
V 19       <Dropdown @click.prevent v-if="toolbar">
20         <Icon icon="ion:ellipsis-vertical" />
21         <template #overlay>
22           <Menu @click="handleMenuClick">
4628d9 23             <template v-for="item in toolbarList" :key="item.value">
V 24               <MenuItem v-bind="{ key: item.value }">
25                 {{ item.label }}
26               </MenuItem>
27               <MenuDivider v-if="item.divider" />
28             </template>
cd8e92 29           </Menu>
V 30         </template>
31       </Dropdown>
32     </div>
33   </div>
34 </template>
52257f 35 <script lang="ts" setup>
762e5d 36   import { type PropType, computed, ref, watch, useSlots } from 'vue';
30b3ee 37   import {
B 38     Dropdown,
39     Menu,
40     MenuItem,
41     MenuDivider,
42     InputSearch,
43     type MenuProps,
44   } from 'ant-design-vue';
762e5d 45   import Icon from '@/components/Icon/Icon.vue';
cd8e92 46   import { BasicTitle } from '/@/components/Basic';
V 47   import { useI18n } from '/@/hooks/web/useI18n';
203729 48   import { useDebounceFn } from '@vueuse/core';
52257f 49   import { createBEM } from '/@/utils/bem';
d21578 50   import { ToolbarEnum } from '../types/tree';
cd8e92 51
52257f 52   const searchValue = ref('');
cd8e92 53
52257f 54   const [bem] = createBEM('tree-header');
V 55
56   const props = defineProps({
57     helpMessage: {
58       type: [String, Array] as PropType<string | string[]>,
59       default: '',
cd8e92 60     },
52257f 61     title: {
V 62       type: String,
63       default: '',
64     },
65     toolbar: {
66       type: Boolean,
67       default: false,
68     },
69     checkable: {
70       type: Boolean,
71       default: false,
72     },
73     search: {
74       type: Boolean,
75       default: false,
76     },
77     searchText: {
78       type: String,
79       default: '',
80     },
81     checkAll: {
82       type: Function,
83       default: undefined,
84     },
85     expandAll: {
86       type: Function,
87       default: undefined,
88     },
89   } as const);
90   const emit = defineEmits(['strictly-change', 'search']);
91
92   const slots = useSlots();
93   const { t } = useI18n();
94
95   const getInputSearchCls = computed(() => {
96     const titleExists = slots.headerTitle || props.title;
97     return [
98       'mr-1',
99       'w-full',
100       {
101         ['ml-5']: titleExists,
cd8e92 102       },
52257f 103     ];
V 104   });
3b6b4f 105
52257f 106   const toolbarList = computed(() => {
V 107     const { checkable } = props;
108     const defaultToolbarList = [
109       { label: t('component.tree.expandAll'), value: ToolbarEnum.EXPAND_ALL },
110       {
111         label: t('component.tree.unExpandAll'),
112         value: ToolbarEnum.UN_EXPAND_ALL,
113         divider: checkable,
114       },
115     ];
7156e4 116
52257f 117     return checkable
V 118       ? [
119           { label: t('component.tree.selectAll'), value: ToolbarEnum.SELECT_ALL },
7156e4 120           {
52257f 121             label: t('component.tree.unSelectAll'),
V 122             value: ToolbarEnum.UN_SELECT_ALL,
7156e4 123             divider: checkable,
V 124           },
52257f 125           ...defaultToolbarList,
V 126           { label: t('component.tree.checkStrictly'), value: ToolbarEnum.CHECK_STRICTLY },
127           { label: t('component.tree.checkUnStrictly'), value: ToolbarEnum.CHECK_UN_STRICTLY },
128         ]
129       : defaultToolbarList;
cd8e92 130   });
52257f 131
30b3ee 132   const handleMenuClick: MenuProps['onClick'] = ({ key }) => {
52257f 133     switch (key) {
V 134       case ToolbarEnum.SELECT_ALL:
135         props.checkAll?.(true);
136         break;
137       case ToolbarEnum.UN_SELECT_ALL:
138         props.checkAll?.(false);
139         break;
140       case ToolbarEnum.EXPAND_ALL:
141         props.expandAll?.(true);
142         break;
143       case ToolbarEnum.UN_EXPAND_ALL:
144         props.expandAll?.(false);
145         break;
146       case ToolbarEnum.CHECK_STRICTLY:
147         emit('strictly-change', false);
148         break;
149       case ToolbarEnum.CHECK_UN_STRICTLY:
150         emit('strictly-change', true);
151         break;
152     }
30b3ee 153   };
52257f 154
V 155   function emitChange(value?: string): void {
156     emit('search', value);
157   }
158
159   const debounceEmitChange = useDebounceFn(emitChange, 200);
160
161   watch(
162     () => searchValue.value,
163     (v) => {
164       debounceEmitChange(v);
165     },
166   );
167
168   watch(
169     () => props.searchText,
170     (v) => {
171       if (v !== searchValue.value) {
172         searchValue.value = v;
173       }
174     },
175   );
176 </script>