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