From dab1e0a3e0b1279ee7be77d359ffc93a831455d4 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 24 八月 2026 17:57:27 +0800
Subject: [PATCH] feat(preferences): 公司品牌信息化编辑与全局联动(登录页/菜单栏/网页标题),偏好设置 tab
---
src/packages/locales/src/langs/en-US/preferences.json | 19 ++
src/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue | 11 +
src/api/system/company-config/index.ts | 27 +++
src/bootstrap.ts | 14 ++
src/store/index.ts | 1
src/packages/effects/layouts/src/widgets/preferences/blocks/index.ts | 1
src/packages/locales/src/langs/zh-CN/preferences.json | 19 ++
src/packages/effects/layouts/src/widgets/preferences/blocks/company/company.vue | 151 +++++++++++++++++++++
src/packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue | 25 +++
src/store/company-config.ts | 71 ++++++++++
src/api/system/storage/index.ts | 11 +
src/layouts/auth.vue | 21 ++
src/utils/company-config.ts | 32 ++++
13 files changed, 397 insertions(+), 6 deletions(-)
diff --git a/src/api/system/company-config/index.ts b/src/api/system/company-config/index.ts
new file mode 100644
index 0000000..dbd1405
--- /dev/null
+++ b/src/api/system/company-config/index.ts
@@ -0,0 +1,27 @@
+import { requestClient } from '#/api/request';
+
+export namespace SystemCompanyConfigApi {
+ /** 鍏徃鍝佺墝淇℃伅 */
+ export interface CompanyConfig {
+ id?: number;
+ companyName?: string;
+ logoUrl?: string;
+ logoBlobId?: number;
+ loginTitle?: string;
+ loginDescription?: string;
+ }
+}
+
+/** 鑾峰緱鍏徃鍝佺墝淇℃伅锛堝厤鐧诲綍鍏紑锛岀櫥褰曢〉 / 搴旂敤鍚姩鏃朵娇鐢級 */
+export async function getCompanyConfig() {
+ return requestClient.get<SystemCompanyConfigApi.CompanyConfig | null>(
+ '/system/company-config/get',
+ );
+}
+
+/** 淇濆瓨鍏徃鍝佺墝淇℃伅 */
+export async function saveCompanyConfig(
+ data: SystemCompanyConfigApi.CompanyConfig,
+) {
+ return requestClient.post<number>('/system/company-config/save', data);
+}
diff --git a/src/api/system/storage/index.ts b/src/api/system/storage/index.ts
index 994d3ad..d1c3557 100644
--- a/src/api/system/storage/index.ts
+++ b/src/api/system/storage/index.ts
@@ -45,6 +45,17 @@
);
}
+/** 鍏叡鏂囦欢涓婁紶锛堟案涔呮湁鏁堬紝杩斿洖姘镐箙鍏紑 previewURL锛岀敤浜庣櫥褰曢〉绛夊厤鐧诲綍灞曠ず鐨勫満鏅級 */
+export function publicUploadFile(files: globalThis.File[]) {
+ const formData = new FormData();
+ files.forEach((file) => formData.append('files', file));
+ return requestClient.post<SystemStorageApi.StorageBlob[]>(
+ '/system/storage-blob/public-upload',
+ formData,
+ { headers: { 'Content-Type': 'multipart/form-data' } },
+ );
+}
+
/** 鏌ヨ闄勪欢鍒楄〃 */
export function listAttachments(params: SystemStorageApi.AttachmentListParams) {
return requestClient.get<SystemStorageApi.StorageBlob[]>(
diff --git a/src/bootstrap.ts b/src/bootstrap.ts
index 6a97710..bbfb549 100644
--- a/src/bootstrap.ts
+++ b/src/bootstrap.ts
@@ -18,6 +18,9 @@
import App from './app.vue';
import { router } from './router';
+import { getCompanyConfig } from '#/api/system/company-config';
+import { applyCompanyConfig } from '#/utils/company-config';
+
async function bootstrap(namespace: string) {
// 鍒濆鍖栫粍浠堕�傞厤鍣�
await initComponentAdapter();
@@ -49,6 +52,17 @@
// 閰嶇疆 pinia-store
await initStores(app, { namespace });
+ // 鍔犺浇鍏徃鍝佺墝淇℃伅锛堜粠鍚庣锛屽厤鐧诲綍鎺ュ彛锛夛紝鑱斿姩鐧诲綍椤�/鑿滃崟鏍�/缃戦〉鏍囬銆�
+ // 娉細姝ゆ椂 pinia 灏氭湭鍦ㄧ粍浠跺婵�娲伙紝杩欓噷鐢ㄧ函鍑芥暟锛屼笉渚濊禆 store銆�
+ try {
+ const companyConfig = await getCompanyConfig();
+ if (companyConfig) {
+ applyCompanyConfig(companyConfig);
+ }
+ } catch {
+ // 鍚庣涓嶅彲鐢ㄦ垨鏈厤缃紝淇濇寔缂栬瘧鏈熼粯璁�
+ }
+
// 瀹夎鏉冮檺鎸囦护
registerAccessDirective(app);
diff --git a/src/layouts/auth.vue b/src/layouts/auth.vue
index 1cdccb9..b3386c1 100644
--- a/src/layouts/auth.vue
+++ b/src/layouts/auth.vue
@@ -1,16 +1,31 @@
<script lang="ts" setup>
-import { computed } from 'vue';
+import { computed, onMounted } from 'vue';
import { AuthPageLayout } from '@vben/layouts';
import { preferences } from '@vben/preferences';
import { $t } from '#/locales';
+import { useCompanyConfigStore } from '#/store/company-config';
declare const __APP_LOGO__: string;
+
+const companyConfigStore = useCompanyConfigStore();
+
+onMounted(() => {
+ // 鐧诲綍椤靛睍绀� loginTitle锛氬惎鍔ㄥ姞杞借蛋鐨勬槸绾嚱鏁帮紙涓嶅~ store锛夛紝杩涘叆鐧诲綍椤垫椂鎷夊彇涓�娆�
+ companyConfigStore.loadFromServer();
+});
const appName = computed(() => preferences.copyright.companyName);
const logo = computed(() => __APP_LOGO__ || preferences.logo.source);
const logoDark = computed(() => preferences.logo.sourceDark);
+// 鐧诲綍椤垫爣棰�/鎻忚堪浼樺厛鍙栧悗绔厤缃紝鏈厤缃椂鍥為��鍒� i18n 榛樿
+const pageTitle = computed(
+ () => companyConfigStore.loginTitle || $t('authentication.pageTitle'),
+);
+const pageDescription = computed(
+ () => companyConfigStore.loginDescription || $t('authentication.pageDesc'),
+);
</script>
<template>
@@ -18,8 +33,8 @@
:app-name="appName"
:logo="logo"
:logo-dark="logoDark"
- :page-description="$t('authentication.pageDesc')"
- :page-title="$t('authentication.pageTitle')"
+ :page-description="pageDescription"
+ :page-title="pageTitle"
>
<!-- 鑷畾涔夊伐鍏锋爮 -->
<!-- <template #toolbar></template> -->
diff --git a/src/packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue b/src/packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue
index 8898556..fbaa8a3 100644
--- a/src/packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue
+++ b/src/packages/@core/ui-kit/shadcn-ui/src/components/segmented/segmented.vue
@@ -5,17 +5,22 @@
import { TabsTrigger } from 'reka-ui';
+import { cn } from '../../../../../base/shared/src/utils';
+
import { Tabs, TabsContent, TabsList } from '../../ui';
import TabsIndicator from './tabs-indicator.vue';
interface Props {
defaultValue?: string;
tabs?: SegmentedItem[];
+ /** 鏄惁鍏佽妯悜婊氬姩锛歵ab 杈冨鏃跺惎鐢紝鍚� tab 鎸夊唴瀹瑰搴︽帓鍒楋紝瓒呭嚭閮ㄥ垎鍙粦鍔� */
+ scrollable?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
defaultValue: '',
tabs: () => [],
+ scrollable: false,
});
const activeTab = defineModel<string>();
@@ -25,12 +30,18 @@
});
const tabsStyle = computed(() => {
+ if (props.scrollable) {
+ return undefined;
+ }
return {
'grid-template-columns': `repeat(${props.tabs.length}, minmax(0, 1fr))`,
};
});
const tabsIndicatorStyle = computed(() => {
+ if (props.scrollable) {
+ return undefined;
+ }
return {
width: `${(100 / props.tabs.length).toFixed(0)}%`,
};
@@ -45,14 +56,22 @@
<Tabs v-model="activeTab" :default-value="getDefaultValue">
<TabsList
:style="tabsStyle"
- class="bg-accent outline-heavy! relative grid w-full outline-2!"
+ :class="
+ cn(
+ 'bg-accent outline-heavy! relative outline-2!',
+ // 鍙粴鍔ㄦā寮忥細宸﹀榻愶紙瑕嗙洊 reka-ui 鐨� justify-center锛屽惁鍒欏唴瀹硅秴瀹芥椂宸︿晶琚尋鍑轰笖鏃犳硶婊氬姩锛夈�佸叏瀹姐�佹í鍚戞粴鍔�
+ scrollable
+ ? 'flex! w-full! overflow-x-auto justify-start!'
+ : 'grid w-full',
+ )
+ "
>
- <TabsIndicator :style="tabsIndicatorStyle" />
+ <TabsIndicator v-if="!scrollable" :style="tabsIndicatorStyle" />
<template v-for="tab in tabs" :key="tab.value">
<TabsTrigger
:value="tab.value"
:class="activeClass(tab.value)"
- class="hover:text-primary z-20 inline-flex items-center justify-center rounded-md px-3 py-1 text-sm font-medium whitespace-nowrap disabled:pointer-events-none disabled:opacity-50"
+ class="hover:text-primary z-20 inline-flex shrink-0 items-center justify-center rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap disabled:pointer-events-none disabled:opacity-50"
>
{{ tab.label }}
</TabsTrigger>
diff --git a/src/packages/effects/layouts/src/widgets/preferences/blocks/company/company.vue b/src/packages/effects/layouts/src/widgets/preferences/blocks/company/company.vue
new file mode 100644
index 0000000..24fcdf0
--- /dev/null
+++ b/src/packages/effects/layouts/src/widgets/preferences/blocks/company/company.vue
@@ -0,0 +1,151 @@
+<script setup lang="ts">
+import { message } from 'ant-design-vue';
+import { Button, Input, Upload } from 'ant-design-vue';
+import { onMounted, ref } from 'vue';
+
+// 娉ㄦ剰锛氭湰鏂囦欢浣嶄簬 @vben 鐨� packages 鍐呴儴锛屾棤娉曚娇鐢ㄥ簲鐢ㄥ眰鍒悕 #/锛岄渶鐢ㄧ浉瀵硅矾寰勶紙涓庡悓鐩綍 custom.vue 淇濇寔涓�鑷达級
+import { publicUploadFile } from '../../../../../../../../api/system/storage';
+import { $t } from '../../../../../../../locales/src';
+import { useCompanyConfigStore } from '../../../../../../../../store/company-config';
+
+defineOptions({
+ name: 'PreferenceCompanyConfig',
+});
+
+const companyConfigStore = useCompanyConfigStore();
+
+const companyName = ref(companyConfigStore.companyName);
+const loginTitle = ref(companyConfigStore.loginTitle);
+const loginDescription = ref(companyConfigStore.loginDescription);
+const logoUrl = ref(companyConfigStore.logoUrl);
+const uploading = ref(false);
+
+// 鎵撳紑鍖哄潡鏃朵粠鍚庣鎷夊彇鏈�鏂板叕鍙搁厤缃苟鍥炲~琛ㄥ崟锛坰tore 鍒濆�煎彲鑳戒负绌猴紝鍥犲惎鍔ㄥ姞杞借蛋鐨勬槸绾嚱鏁帮級
+onMounted(async () => {
+ await companyConfigStore.loadFromServer();
+ companyName.value = companyConfigStore.companyName;
+ loginTitle.value = companyConfigStore.loginTitle;
+ loginDescription.value = companyConfigStore.loginDescription;
+ logoUrl.value = companyConfigStore.logoUrl;
+});
+
+/** 涓婁紶 logo锛堟案涔呭叕寮�锛屼緵鐧诲綍椤靛厤鐧诲綍灞曠ず锛� */
+async function handleBeforeUpload(file: File) {
+ uploading.value = true;
+ try {
+ const blobs = await publicUploadFile([file]);
+ const blob = blobs?.[0];
+ if (blob?.previewURL || blob?.url) {
+ logoUrl.value = blob.previewURL || blob.url || '';
+ message.success($t('preferences.company.uploadSuccess'));
+ } else {
+ message.error($t('preferences.company.uploadFailed'));
+ }
+ } catch {
+ message.error($t('preferences.company.uploadFailed'));
+ } finally {
+ uploading.value = false;
+ }
+ // 杩斿洖 false锛岄樆姝㈢粍浠堕粯璁や笂浼狅紙宸查�氳繃鎺ュ彛涓婁紶锛�
+ return false;
+}
+
+async function handleSave() {
+ if (!companyName.value.trim()) {
+ message.warning($t('preferences.company.companyNameRequired'));
+ return;
+ }
+ try {
+ await companyConfigStore.save({
+ companyName: companyName.value.trim(),
+ logoUrl: logoUrl.value || undefined,
+ loginTitle: loginTitle.value,
+ loginDescription: loginDescription.value,
+ });
+ message.success($t('preferences.company.saveSuccess'));
+ } catch {
+ message.error($t('preferences.company.saveFailed'));
+ }
+}
+</script>
+
+<template>
+ <div class="flex flex-col">
+ <!-- 鍏徃鍚嶇О -->
+ <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1">
+ <span class="flex items-center text-sm">
+ {{ $t('preferences.company.companyName') }}
+ </span>
+ <Input
+ v-model:value="companyName"
+ :placeholder="$t('preferences.company.companyNamePlaceholder')"
+ class="w-41.25"
+ allow-clear
+ />
+ </div>
+
+ <!-- 鐧诲綍椤垫爣棰� -->
+ <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1">
+ <span class="flex items-center text-sm">
+ {{ $t('preferences.company.loginTitle') }}
+ </span>
+ <Input
+ v-model:value="loginTitle"
+ :placeholder="$t('preferences.company.loginTitlePlaceholder')"
+ class="w-41.25"
+ allow-clear
+ />
+ </div>
+
+ <!-- 鐧诲綍椤垫弿杩� -->
+ <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1">
+ <span class="flex items-center text-sm">
+ {{ $t('preferences.company.loginDescription') }}
+ </span>
+ <Input
+ v-model:value="loginDescription"
+ :placeholder="$t('preferences.company.loginDescriptionPlaceholder')"
+ class="w-41.25"
+ allow-clear
+ />
+ </div>
+
+ <!-- 鍏徃 Logo -->
+ <div class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1">
+ <span class="flex items-center text-sm">
+ {{ $t('preferences.company.logo') }}
+ </span>
+ <div class="flex items-center gap-2">
+ <Upload
+ :show-upload-list="false"
+ accept="image/*"
+ :before-upload="handleBeforeUpload"
+ >
+ <Button size="small" :loading="uploading">
+ {{ $t('preferences.company.uploadLogo') }}
+ </Button>
+ </Upload>
+ <img
+ v-if="logoUrl"
+ :src="logoUrl"
+ alt="company-logo"
+ class="h-9 w-9 rounded border border-border object-contain"
+ />
+ <span v-else class="text-xs text-muted-foreground">
+ {{ $t('preferences.company.logoEmpty') }}
+ </span>
+ </div>
+ </div>
+
+ <div v-if="uploading" class="px-2 pb-1 text-xs text-muted-foreground">
+ {{ $t('preferences.company.uploading') }}
+ </div>
+
+ <!-- 淇濆瓨 -->
+ <div class="mt-3 px-2">
+ <Button type="primary" class="w-full" @click="handleSave">
+ {{ $t('preferences.company.save') }}
+ </Button>
+ </div>
+ </div>
+</template>
diff --git a/src/packages/effects/layouts/src/widgets/preferences/blocks/index.ts b/src/packages/effects/layouts/src/widgets/preferences/blocks/index.ts
index b1b8eac..5b62459 100644
--- a/src/packages/effects/layouts/src/widgets/preferences/blocks/index.ts
+++ b/src/packages/effects/layouts/src/widgets/preferences/blocks/index.ts
@@ -1,4 +1,5 @@
export { default as Block } from './block.vue';
+export { default as Company } from './company/company.vue';
export { default as Custom } from './custom/custom.vue';
export { default as Animation } from './general/animation.vue';
export { default as General } from './general/general.vue';
diff --git a/src/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue b/src/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
index 12f4076..5b3a05e 100644
--- a/src/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
+++ b/src/packages/effects/layouts/src/widgets/preferences/preferences-drawer.vue
@@ -43,6 +43,7 @@
Breadcrumb,
BuiltinTheme,
ColorMode,
+ Company,
Content,
Copyright,
Custom,
@@ -256,6 +257,10 @@
label: $t('preferences.general'),
value: 'general',
},
+ {
+ label: $t('preferences.company.title'),
+ value: 'company',
+ },
];
if (showCustomTab.value) {
@@ -352,6 +357,7 @@
<VbenSegmented
v-model="activeTab"
:tabs="tabs"
+ scrollable
:class="{
'sticky-tabs-header': appEnableStickyPreferencesNavigationBar,
}"
@@ -526,6 +532,11 @@
/>
</Block>
</template>
+ <template #company>
+ <Block :title="$t('preferences.company.title')">
+ <Company />
+ </Block>
+ </template>
<template #custom>
<Block :title="customTabTitle">
<Custom
diff --git a/src/packages/locales/src/langs/en-US/preferences.json b/src/packages/locales/src/langs/en-US/preferences.json
index d027227..853651a 100644
--- a/src/packages/locales/src/langs/en-US/preferences.json
+++ b/src/packages/locales/src/langs/en-US/preferences.json
@@ -229,5 +229,24 @@
"placeholder": "Please enter the default report title"
}
}
+ },
+ "company": {
+ "title": "Company Info",
+ "companyName": "Company Name",
+ "companyNamePlaceholder": "Please enter company name",
+ "companyNameRequired": "Company name is required",
+ "loginTitle": "Login Page Title",
+ "loginTitlePlaceholder": "Enter login page title (optional)",
+ "loginDescription": "Login Page Description",
+ "loginDescriptionPlaceholder": "Enter login page description (optional)",
+ "logo": "Company Logo",
+ "uploadLogo": "Upload Logo",
+ "uploadSuccess": "Logo uploaded successfully",
+ "uploadFailed": "Logo upload failed",
+ "uploading": "Uploading...",
+ "logoEmpty": "No logo set",
+ "save": "Save",
+ "saveSuccess": "Company info saved successfully",
+ "saveFailed": "Failed to save company info"
}
}
diff --git a/src/packages/locales/src/langs/zh-CN/preferences.json b/src/packages/locales/src/langs/zh-CN/preferences.json
index 8cbc607..aa36730 100644
--- a/src/packages/locales/src/langs/zh-CN/preferences.json
+++ b/src/packages/locales/src/langs/zh-CN/preferences.json
@@ -229,5 +229,24 @@
"placeholder": "璇疯緭鍏ユ姤琛ㄩ粯璁ゆ爣棰�"
}
}
+ },
+ "company": {
+ "title": "鍏徃淇℃伅",
+ "companyName": "鍏徃鍚嶇О",
+ "companyNamePlaceholder": "璇疯緭鍏ュ叕鍙稿悕绉�",
+ "companyNameRequired": "鍏徃鍚嶇О涓嶈兘涓虹┖",
+ "loginTitle": "鐧诲綍椤垫爣棰�",
+ "loginTitlePlaceholder": "璇疯緭鍏ョ櫥褰曢〉鏍囬锛堝彲閫夛級",
+ "loginDescription": "鐧诲綍椤垫弿杩�",
+ "loginDescriptionPlaceholder": "璇疯緭鍏ョ櫥褰曢〉鎻忚堪锛堝彲閫夛級",
+ "logo": "鍏徃 Logo",
+ "uploadLogo": "涓婁紶 Logo",
+ "uploadSuccess": "Logo 涓婁紶鎴愬姛",
+ "uploadFailed": "Logo 涓婁紶澶辫触",
+ "uploading": "涓婁紶涓�...",
+ "logoEmpty": "鏈缃� Logo",
+ "save": "淇濆瓨",
+ "saveSuccess": "鍏徃淇℃伅淇濆瓨鎴愬姛",
+ "saveFailed": "鍏徃淇℃伅淇濆瓨澶辫触"
}
}
diff --git a/src/store/company-config.ts b/src/store/company-config.ts
new file mode 100644
index 0000000..1668f86
--- /dev/null
+++ b/src/store/company-config.ts
@@ -0,0 +1,71 @@
+import { ref } from 'vue';
+import { defineStore } from 'pinia';
+
+import {
+ getCompanyConfig,
+ saveCompanyConfig as saveCompanyConfigApi,
+} from '#/api/system/company-config';
+import { applyCompanyConfig } from '#/utils/company-config';
+
+/**
+ * 鍏徃鍝佺墝淇℃伅鍏ㄥ眬閰嶇疆
+ *
+ * 鍚姩鏃朵粠鍚庣鍔犺浇锛屼繚瀛樻椂鍐欏洖鍚庣锛涘苟灏嗗叕鍙稿悕/logo 鍚屾鍒� preferences锛�
+ * 浠庤�岃仈鍔ㄧ櫥褰曢〉銆佽彍鍗曟爮銆佺綉椤垫爣棰樼瓑鎵�鏈夋秷璐圭偣銆�
+ */
+export const useCompanyConfigStore = defineStore('companyConfig', () => {
+ const companyName = ref('');
+ const logoUrl = ref('');
+ const loginTitle = ref('');
+ const loginDescription = ref('');
+
+ /** 灏嗗叕鍙镐俊鎭簲鐢ㄥ埌 preferences锛岃仈鍔ㄧ櫥褰曢〉/鑿滃崟鏍�/鏍囬 */
+ function applyToPreferences() {
+ applyCompanyConfig({
+ companyName: companyName.value,
+ logoUrl: logoUrl.value,
+ });
+ }
+
+ /** 浠庡悗绔姞杞藉叕鍙搁厤缃苟搴旂敤 */
+ async function loadFromServer() {
+ try {
+ const config = await getCompanyConfig();
+ if (config) {
+ companyName.value = config.companyName ?? '';
+ logoUrl.value = config.logoUrl ?? '';
+ loginTitle.value = config.loginTitle ?? '';
+ loginDescription.value = config.loginDescription ?? '';
+ applyToPreferences();
+ }
+ } catch {
+ // 鍚庣涓嶅彲鐢ㄦ垨鏈厤缃紝淇濇寔缂栬瘧鏈熼粯璁�
+ }
+ }
+
+ /** 淇濆瓨鍏徃閰嶇疆鍒板悗绔苟搴旂敤 */
+ async function save(data: {
+ companyName: string;
+ logoUrl?: string;
+ logoBlobId?: number;
+ loginTitle?: string;
+ loginDescription?: string;
+ }) {
+ await saveCompanyConfigApi(data);
+ companyName.value = data.companyName;
+ logoUrl.value = data.logoUrl ?? '';
+ loginTitle.value = data.loginTitle ?? '';
+ loginDescription.value = data.loginDescription ?? '';
+ applyToPreferences();
+ }
+
+ return {
+ companyName,
+ logoUrl,
+ loginTitle,
+ loginDescription,
+ applyToPreferences,
+ loadFromServer,
+ save,
+ };
+});
diff --git a/src/store/index.ts b/src/store/index.ts
index 269586e..10d8c3d 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -1 +1,2 @@
export * from './auth';
+export * from './company-config';
diff --git a/src/utils/company-config.ts b/src/utils/company-config.ts
new file mode 100644
index 0000000..4f57dcc
--- /dev/null
+++ b/src/utils/company-config.ts
@@ -0,0 +1,32 @@
+import { preferencesManager } from '@vben/preferences';
+
+/** 鍏徃鍝佺墝淇℃伅锛堜笌鍚庣 system_company_config 琛ㄥ瓧娈靛搴旓級 */
+export interface CompanyConfigData {
+ companyName?: string;
+ logoUrl?: string;
+ loginTitle?: string;
+ loginDescription?: string;
+}
+
+/**
+ * 灏嗗叕鍙稿搧鐗屼俊鎭簲鐢ㄥ埌鍏ㄥ眬锛�
+ * - 鍏徃鍚� 鈫� preferences.app.name / copyright.companyName锛堣仈鍔ㄨ彍鍗曟爮銆佺櫥褰曢〉銆佺綉椤垫爣棰樸�佺増鏉冿級
+ * - logo 鈫� preferences.logo.source锛堣仈鍔ㄧ櫥褰曢〉銆佷晶杈规爮 logo锛�
+ * - 鏈夊叕鍙稿悕鏃讹紝璁剧疆 document.title锛堝熀纭�鏍囬锛宒ynamicTitle 寮�鍚椂璺敱鏍囬鍦ㄦ鍩虹涓婃嫾鎺ワ級
+ */
+export function applyCompanyConfig(config: CompanyConfigData) {
+ const updates: Record<string, any> = {};
+ if (config.logoUrl) {
+ updates.logo = { source: config.logoUrl };
+ }
+ if (config.companyName) {
+ updates.app = { name: config.companyName };
+ updates.copyright = { companyName: config.companyName };
+ }
+ if (Object.keys(updates).length > 0) {
+ preferencesManager.updatePreferences(updates);
+ }
+ if (config.companyName) {
+ document.title = config.companyName;
+ }
+}
--
Gitblit v1.9.3