Blame view

src/layouts/default/header/LayoutHeader.tsx 8.2 KB
vben authored
1
2
import './index.less';
vben authored
3
import type { FunctionalComponent } from 'vue';
vben authored
4
import type { Component } from '/@/components/types';
vben authored
5
vben authored
6
7
8
9
10
import {
  defineComponent,
  unref,
  computed,
  ref,
11
12
  nextTick,
  watchEffect,
vben authored
13
14
  // nextTick
} from 'vue';
15
vben authored
16
import { Layout, Tooltip, Badge } from 'ant-design-vue';
vben authored
17
import { AppLogo } from '/@/components/Application';
陈文彬 authored
18
import UserDropdown from './UserDropdown';
vben authored
19
import LayoutMenu from '../menu';
vben authored
20
import LayoutBreadcrumb from './LayoutBreadcrumb.vue';
vben authored
21
import LockAction from './actions/LockAction';
vben authored
22
23
import LayoutTrigger from '../LayoutTrigger';
import NoticeAction from './notice/NoticeActionItem.vue';
陈文彬 authored
24
25
26
27
28
import {
  RedoOutlined,
  FullscreenExitOutlined,
  FullscreenOutlined,
  LockOutlined,
vben authored
29
  BugOutlined,
陈文彬 authored
30
} from '@ant-design/icons-vue';
vben authored
31
32

import { AppSearch } from '/@/components/Application';
vben authored
33
import { useModal } from '/@/components/Modal';
34
陈文彬 authored
35
36
import { useFullscreen } from '/@/hooks/web/useFullScreen';
import { useTabs } from '/@/hooks/web/useTabs';
37
import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
vben authored
38
39
40
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
vben authored
41
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
vben authored
42
43
import { useRouter } from 'vue-router';
44
45
46

import { errorStore } from '/@/store/modules/error';
vben authored
47
48
import { PageEnum } from '/@/enums/pageEnum';
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
vben authored
49
50
import { AppLocalePicker } from '/@/components/Application';
import { useI18n } from '/@/hooks/web/useI18n';
vben authored
51
import { propTypes } from '/@/utils/propTypes';
vben authored
52
import { useLayoutContext } from '../useLayoutContext';
vben authored
53
vben authored
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
interface TooltipItemProps {
  title: string;
}

const TooltipItem: FunctionalComponent<TooltipItemProps> = (props, { slots }) => {
  return (
    <Tooltip>
      {{
        title: () => props.title,
        default: () => slots.default?.(),
      }}
    </Tooltip>
  );
};
陈文彬 authored
69
export default defineComponent({
vben authored
70
  name: 'LayoutHeader',
vben authored
71
  props: {
vben authored
72
    fixed: propTypes.bool,
vben authored
73
74
  },
  setup(props) {
75
    let logoEl: Element | null | undefined;
76
77
    const logoWidthRef = ref(200);
vben authored
78
    const logoRef = ref<ComponentRef>(null);
vben authored
79
80
81

    const injectValue = useLayoutContext();
82
    const { refreshPage } = useTabs();
83
    const { t } = useI18n();
vben authored
84
vben authored
85
    const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsHorizontal } = useMenuSetting();
vben authored
86
vben authored
87
    const { getShowLocale } = useLocaleSetting();
vben authored
88
89
90
    const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();

    const {
vben authored
91
      getHeaderTheme,
vben authored
92
93
94
95
96
97
98
99
100
      getShowRedo,
      getUseLockPage,
      getShowFullScreen,
      getShowNotice,
      getShowContent,
      getShowBread,
      getShowHeaderLogo,
    } = useHeaderSetting();
101
    const { push } = useRouter();
陈文彬 authored
102
103
    const [register, { openModal }] = useModal();
    const { toggleFullscreen, isFullscreenRef } = useFullscreen();
104
105
106
107
108
109
110
111
    useWindowSizeFn(
      () => {
        calcTopMenuWidth();
      },
      100,
      { immediate: false }
    );
陈文彬 authored
112
113

    const headerClass = computed(() => {
vben authored
114
      const theme = unref(getHeaderTheme);
陈文彬 authored
115
116
      return theme ? `layout-header__header--${theme}` : '';
    });
vben authored
117
vben authored
118
119
120
121
    const isPc = computed(() => {
      return !unref(injectValue.isMobile);
    });
vben authored
122
123
124
125
126
127
    const getSplitType = computed(() => {
      return unref(getSplit) ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE;
    });

    const getMenuMode = computed(() => {
      return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null;
128
129
    });
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
    watchEffect(() => {
      if (unref(getIsHorizontal)) {
        calcTopMenuWidth();
      }
    });

    function calcTopMenuWidth() {
      nextTick(() => {
        if (!unref(getShowTopMenu)) return;
        let width = 0;
        if (!logoEl) {
          logoEl = unref(logoRef)?.$el;
        }
        if (!logoEl) return;
        width += logoEl.clientWidth;
        logoWidthRef.value = width + 80;
      });
    }
vben authored
149
    function handleToErrorList() {
vben authored
150
151
152
      push(PageEnum.ERROR_LOG_PAGE).then(() => {
        errorStore.commitErrorListCountState(0);
      });
vben authored
153
154
    }
陈文彬 authored
155
156
157
    function handleLockPage() {
      openModal(true);
    }
158
vben authored
159
    function renderHeaderContent() {
160
      const width = unref(logoWidthRef);
vben authored
161
162
163
      return (
        <div class="layout-header__content ">
          {unref(getShowHeaderLogo) && (
vben authored
164
            <AppLogo class={`layout-header__logo`} ref={logoRef} theme={unref(getHeaderTheme)} />
vben authored
165
          )}
陈文彬 authored
166
vben authored
167
168
169
          {unref(getShowContent) && (
            <div class="layout-header__left">
              {unref(getShowHeaderTrigger) && (
vben authored
170
                <LayoutTrigger theme={unref(getHeaderTheme)} sider={false} />
vben authored
171
              )}
vben authored
172
173
174
              {unref(getShowBread) && unref(isPc) && (
                <LayoutBreadcrumb showIcon={unref(getShowBreadCrumbIcon)} />
              )}
vben authored
175
176
            </div>
          )}
177
vben authored
178
          {unref(getShowTopMenu) && unref(isPc) && (
179
180
            <div class={[`layout-header__menu `]} style={{ width: `calc(100% - ${width}px)` }}>
              {/* <div class={[`layout-header__menu `]}> */}
vben authored
181
182
              <LayoutMenu
                isHorizontal={true}
vben authored
183
                // class={`justify-${unref(getTopMenuAlign)}`}
vben authored
184
                theme={unref(getHeaderTheme)}
vben authored
185
186
187
188
189
190
191
192
                splitType={unref(getSplitType)}
                menuMode={unref(getMenuMode)}
              />
            </div>
          )}
        </div>
      );
    }
193
vben authored
194
    function renderActionDefault(Comp: Component | any, event: Fn) {
陈文彬 authored
195
      return (
vben authored
196
197
        <div class="layout-header__action-item" onClick={event}>
          <Comp class="layout-header__action-icon" />
vben authored
198
199
200
        </div>
      );
    }
201
vben authored
202
203
204
    function renderAction() {
      return (
        <div class={`layout-header__action`}>
vben authored
205
206
          {unref(isPc) && <AppSearch class="layout-header__action-item" />}
vben authored
207
          {unref(getUseErrorHandle) && unref(isPc) && (
vben authored
208
            <TooltipItem title={t('layout.header.tooltipErrorLog')}>
vben authored
209
210
211
212
213
214
215
216
217
218
219
              {() => (
                <Badge
                  count={errorStore.getErrorListCountState}
                  offset={[0, 10]}
                  dot
                  overflowCount={99}
                >
                  {() => renderActionDefault(BugOutlined, handleToErrorList)}
                </Badge>
              )}
            </TooltipItem>
vben authored
220
          )}
陈文彬 authored
221
vben authored
222
          {unref(getUseLockPage) && unref(isPc) && (
vben authored
223
            <TooltipItem title={t('layout.header.tooltipLock')}>
vben authored
224
225
              {() => renderActionDefault(LockOutlined, handleLockPage)}
            </TooltipItem>
vben authored
226
227
          )}
vben authored
228
          {unref(getShowNotice) && unref(isPc) && (
vben authored
229
230
231
            <TooltipItem title={t('layout.header.tooltipNotify')}>
              {() => <NoticeAction />}
            </TooltipItem>
vben authored
232
          )}
vben authored
233
vben authored
234
          {unref(getShowRedo) && unref(isPc) && (
vben authored
235
            <TooltipItem title={t('layout.header.tooltipRedo')}>
vben authored
236
237
              {() => renderActionDefault(RedoOutlined, refreshPage)}
            </TooltipItem>
陈文彬 authored
238
          )}
vben authored
239
vben authored
240
          {unref(getShowFullScreen) && unref(isPc) && (
vben authored
241
242
243
244
245
246
247
            <TooltipItem
              title={
                unref(isFullscreenRef)
                  ? t('layout.header.tooltipExitFull')
                  : t('layout.header.tooltipEntryFull')
              }
            >
vben authored
248
249
250
251
252
253
254
              {() => {
                const Icon = !unref(isFullscreenRef) ? (
                  <FullscreenOutlined />
                ) : (
                  <FullscreenExitOutlined />
                );
                return renderActionDefault(Icon, toggleFullscreen);
vben authored
255
              }}
vben authored
256
            </TooltipItem>
vben authored
257
          )}
vben authored
258
259
260
261
262
263
264
265
          <UserDropdown class="layout-header__user-dropdown" />
          {unref(getShowLocale) && (
            <AppLocalePicker
              reload={true}
              showText={false}
              class="layout-header__action-item locale"
            />
          )}
vben authored
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
        </div>
      );
    }

    function renderHeaderDefault() {
      return (
        <>
          {renderHeaderContent()}
          {renderAction()}
          <LockAction onRegister={register} />
        </>
      );
    }

    return () => {
      return (
vben authored
282
283
284
        <Layout.Header
          class={['layout-header', 'flex p-0 px-4 ', unref(headerClass), { fixed: props.fixed }]}
        >
vben authored
285
          {() => renderHeaderDefault()}
陈文彬 authored
286
287
288
289
290
        </Layout.Header>
      );
    };
  },
});