From 4a45d6c79b2157a149afcb3b49ba504ff7c5075f Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期三, 28 十月 2026 11:51:55 +0800
Subject: [PATCH] feat(portal): 门户字号改为保存到数据库全局生效

---
 src/layouts/basic.vue |  111 ++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 64 insertions(+), 47 deletions(-)

diff --git a/src/layouts/basic.vue b/src/layouts/basic.vue
index b6231e5..4b7667b 100644
--- a/src/layouts/basic.vue
+++ b/src/layouts/basic.vue
@@ -1,14 +1,15 @@
 <script lang="ts" setup>
 import type { NotificationItem } from '@vben/layouts';
 
-import type { SystemTenantApi } from '#/api/system/tenant';
 
 import { computed, onMounted, ref, watch } from 'vue';
 
-import { useAccess } from '@vben/access';
+import { useDebounceFn } from '@vueuse/core';
+import { message } from 'ant-design-vue';
+
 import { AuthenticationLoginExpiredModal, useVbenModal } from '@vben/common-ui';
 import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
-import { isTenantEnable, useTabs, useWatermark } from '@vben/hooks';
+import { useWatermark } from '@vben/hooks';
 import {
   AntdProfileOutlined,
   BookOpenText,
@@ -21,14 +22,12 @@
   Help,
   LockScreen,
   Notification,
-  TenantDropdown,
   UserDropdown,
 } from '@vben/layouts';
 import { preferences, usePreferences } from '@vben/preferences';
 import { useAccessStore, useUserStore } from '@vben/stores';
 import { formatDateTime, openWindow } from '@vben/utils';
 
-import { message } from 'ant-design-vue';
 
 import {
   getUnreadNotifyMessageCount,
@@ -36,18 +35,20 @@
   updateAllNotifyMessageRead,
   updateNotifyMessageRead,
 } from '#/api/system/notify/message';
-import { getSimpleTenantList } from '#/api/system/tenant';
 import { $t } from '#/locales';
 import { router } from '#/router';
 import { useAuthStore } from '#/store';
+import {
+  loadPortalUiConfig,
+  savePortalUiConfigToServer,
+} from '#/utils/portal-ui-config';
 import LoginForm from '#/views/_core/authentication/login.vue';
+import PortalBrandText from '#/components/portal/portal-brand-text.vue';
 
 const userStore = useUserStore();
 const authStore = useAuthStore();
 const accessStore = useAccessStore();
-const { hasAccessByCodes } = useAccess();
 const { destroyWatermark, updateWatermark } = useWatermark();
-const { closeOtherTabs, refreshTab } = useTabs();
 
 const notifications = ref<NotificationItem[]>([]);
 const unreadCount = ref(0);
@@ -65,6 +66,11 @@
     },
     icon: AntdProfileOutlined,
     text: $t('ui.widgets.profile'),
+  },
+  {
+    handler: () => router.push({ name: 'Profile', query: { section: 'resetPwd' } }),
+    icon: 'lucide:shield-check',
+    text: '瀵嗙爜璁剧疆',
   },
   // {
   //   handler: () => {
@@ -157,41 +163,45 @@
   handleNotificationGetUnreadCount();
 }
 
-// 绉熸埛鍒楄〃
-const tenants = ref<SystemTenantApi.Tenant[]>([]);
-const tenantEnable = computed(
-  () => hasAccessByCodes(['system:tenant:visit']) && isTenantEnable(),
-);
+// ========== 闂ㄦ埛瀛楀彿鍏ㄥ眬閰嶇疆锛堝瓨鏁版嵁搴擄紝鎵�鏈夌敤鎴峰叡鐢級 ==========
+/** 宸插悓姝ュ埌鏁版嵁搴撶殑瀛楀彿锛岀敤浜庨伩鍏嶈鍙栧悗鍥炲啓 */
+let portalFontBaseline: null | { home: number; menu: number } = null;
+/** 淇濆瓨澶辫触鍙彁绀轰竴娆★紝閬垮厤杩炵画璋冭妭鏃跺弽澶嶅脊绐� */
+let portalFontSaveWarned = false;
 
-/** 鑾峰彇绉熸埛鍒楄〃 */
-async function handleGetTenantList() {
-  if (tenantEnable.value) {
-    tenants.value = await getSimpleTenantList();
-  }
-}
-
-/** 澶勭悊绉熸埛鍒囨崲 */
-async function handleTenantChange(tenant: SystemTenantApi.Tenant) {
-  if (!tenant || !tenant.id) {
-    message.error('鍒囨崲绉熸埛澶辫触');
+const persistPortalFontConfig = useDebounceFn(async () => {
+  const home = preferences.app.homeFontSize;
+  const menu = preferences.navigation.fontSize;
+  if (portalFontBaseline && portalFontBaseline.home === home && portalFontBaseline.menu === menu) {
     return;
   }
-  // 璁剧疆璁块棶绉熸埛 ID
-  accessStore.setVisitTenantId(tenant.id as number);
-  // 鍏抽棴鍏朵粬鏍囩椤碉紝鍙繚鐣欏綋鍓嶉〉
-  await closeOtherTabs();
-  // 鍒锋柊褰撳墠椤甸潰
-  await refreshTab();
-  // 鎻愮ず鍒囨崲鎴愬姛
-  message.success(`鍒囨崲褰撳墠绉熸埛涓�: ${tenant.name}`);
-}
+  try {
+    await savePortalUiConfigToServer({ homeFontSize: home, menuFontSize: menu });
+    portalFontBaseline = { home, menu };
+    portalFontSaveWarned = false;
+  } catch {
+    if (!portalFontSaveWarned) {
+      portalFontSaveWarned = true;
+      message.warning('瀛楀彿宸插湪鏈満鐢熸晥锛屼絾淇濆瓨鍒板叏灞�澶辫触锛岃纭鏄惁鏈夊弬鏁伴厤缃慨鏀规潈闄�');
+    }
+  }
+}, 800);
+
+watch(
+  () => [preferences.app.homeFontSize, preferences.navigation.fontSize],
+  () => persistPortalFontConfig(),
+);
 
 // ========== 鍒濆鍖� ==========
-onMounted(() => {
+onMounted(async () => {
+  // 璇诲彇鏁版嵁搴撲腑鐨勫叏灞�瀛楀彿閰嶇疆骞跺簲鐢�
+  await loadPortalUiConfig();
+  portalFontBaseline = {
+    home: preferences.app.homeFontSize,
+    menu: preferences.navigation.fontSize,
+  };
   // 棣栨鍔犺浇鏈鏁伴噺
   handleNotificationGetUnreadCount();
-  // 鑾峰彇绉熸埛鍒楄〃
-  handleGetTenantList();
   // 杞鍒锋柊鏈鏁伴噺
   setInterval(
     () => {
@@ -269,9 +279,13 @@
 </script>
 
 <template>
-  <BasicLayout @clear-preferences-and-logout="handleLogout">
+  <BasicLayout class="supply-portal-shell" @clear-preferences-and-logout="handleLogout" @click-logo="router.push('/analytics')">
+    <template #logo-text>
+      <PortalBrandText />
+    </template>
     <template #user-dropdown>
       <UserDropdown
+        show-text
         :avatar
         :menus
         :text="userStore.userInfo?.nickname"
@@ -280,6 +294,9 @@
         @logout="handleLogout"
         @clear-preferences-and-logout="handleLogout"
       />
+    </template>
+    <template #header-right-165>
+      <button type="button" class="portal-personal-entry" aria-label="涓汉涓績" title="涓汉涓績" :class="{ 'is-current': router.currentRoute.value.name === 'Profile' }" @click="router.push({ name: 'Profile' })"><IconifyIcon icon="lucide:user-round" /><span>涓汉涓績</span></button>
     </template>
     <template #notification>
       <Notification
@@ -293,16 +310,16 @@
         @on-click="handleClick"
       />
     </template>
-    <!-- <template #header-right-1>
-      <div v-if="tenantEnable">
-        <TenantDropdown
-          class="mr-2"
-          :tenant-list="tenants"
-          :visit-tenant-id="accessStore.visitTenantId"
-          @success="handleTenantChange"
-        />
-      </div>
-    </template> -->
+    <template v-if="router.hasRoute('MesWorkbench') && accessStore.accessMenus.some((menu) => /鐢熶骇|MES/i.test(menu.name))" #header-right-170>
+      <button
+        type="button"
+        class="flex cursor-pointer items-center gap-1.5 rounded-md border-none bg-primary/15 px-3 py-1.5 text-sm font-medium text-primary transition-colors hover:bg-primary/25"
+        @click="router.push({ name: 'MesWorkbench' })"
+      >
+        <IconifyIcon icon="lucide:factory" class="size-4" />
+        <span>宸ヤ綔鍙�</span>
+      </button>
+    </template>
     <template #extra>
       <AuthenticationLoginExpiredModal
         v-model:open="accessStore.loginExpired"

--
Gitblit v1.9.3