gaoluyang
2026-10-20 008e168d50c53c5436b8f7398bc6b446f7ac5ee0
fix(auth): 登录页恢复标品布局,主题色还原默认蓝色

- 登录页改用 AuthPageLayout,移除自定义 herbal 主题场景
- 删除朱砂红主色覆盖与 herbal-theme.css,背景恢复默认偏白
- 增加一次性迁移,将浏览器缓存的旧主色重置为默认蓝色

Co-Authored-By: Claude Code <noreply@anthropic.com>
已删除2个文件
已修改5个文件
241 ■■■■■ 文件已修改
src/bootstrap.ts 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/auth-scene.vue 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/auth.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/preferences.ts 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/herbal-theme.css 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/_core/authentication/login.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/bootstrap.ts
@@ -7,7 +7,6 @@
import { initStores } from './packages/stores/src';
import './packages/styles/src';
import './packages/styles/src/antd/index.css';
import './styles/herbal-theme.css';
import { useTitle } from '@vueuse/core';
src/layouts/auth-scene.vue
ÎļþÒÑɾ³ý
src/layouts/auth.vue
@@ -1,16 +1,15 @@
<script lang="ts" setup>
import { computed, onMounted } from 'vue';
import { preferences, usePreferences } from '@vben/preferences';
import { AuthPageLayout } from '@vben/layouts';
import { preferences } from '@vben/preferences';
import { $t } from '#/locales';
import { useCompanyConfigStore } from '#/store/company-config';
import AuthenticationToolbar from '../packages/effects/layouts/src/authentication/toolbar.vue';
import AuthScene from './auth-scene.vue';
declare const __APP_LOGO__: string;
const companyConfigStore = useCompanyConfigStore();
const { isDark } = usePreferences();
onMounted(() => {
  // ç™»å½•页展示 loginTitle:启动加载走的是纯函数(不填 store),进入登录页时拉取一次
@@ -20,26 +19,29 @@
const appName = computed(() => preferences.copyright.companyName);
// ç™»å½•页 logo ä¼˜å…ˆå–数据库配置(preferences.logo.source),未配置时回退编译期默认 __APP_LOGO__
const logo = computed(() => {
  const source = (isDark.value && preferences.logo.sourceDark) || preferences.logo.source || __APP_LOGO__;
  const source = preferences.logo.source || __APP_LOGO__;
  // æœªé…ç½®å…¬å¸æ ‡å¿—时不展示框架演示 Logo。
  return source?.includes('@vbenjs/static-source') ? '' : source;
});
const pageTitle = computed(() => companyConfigStore.loginTitle || '滋补品行业数字化管理平台');
const pageDescription = computed(() => companyConfigStore.loginDescription || '传承中医药精华 Â· æœåŠ¡å¥åº·ç¾Žå¥½ç”Ÿæ´»');
const logoDark = computed(() => preferences.logo.sourceDark);
// æ ‡é¢˜/描述优先取公司信息配置,未配置时回退标品文案
const pageTitle = computed(
  () => companyConfigStore.loginTitle || $t('authentication.pageTitle'),
);
const pageDescription = computed(
  () => companyConfigStore.loginDescription || $t('authentication.pageDesc'),
);
</script>
<template>
  <AuthScene
  <AuthPageLayout
    :app-name="appName"
    :logo="logo"
    :platform-description="pageDescription"
    :platform-title="pageTitle"
    :logo-dark="logoDark"
    :page-description="pageDescription"
    :page-title="pageTitle"
  >
    <template #toolbar><AuthenticationToolbar :toolbar-list="['language', 'theme']" /></template>
    <RouterView v-slot="{ Component, route }">
      <KeepAlive :include="['Login']">
        <component :is="Component" :key="route.fullPath" />
      </KeepAlive>
    </RouterView>
  </AuthScene>
    <!-- è‡ªå®šä¹‰å·¥å…·æ  -->
    <!-- <template #toolbar></template> -->
  </AuthPageLayout>
</template>
src/main.ts
@@ -1,5 +1,4 @@
import { watch } from 'vue';
import { initPreferences, preferences, preferencesManager } from './packages/preferences/src';
import { initPreferences, preferencesManager } from './packages/preferences/src';
import { unmountGlobalLoading } from './packages/utils/src';
import { overridesPreferences, preferencesExtension } from './preferences';
@@ -25,27 +24,21 @@
    overrides: overridesPreferences,
  });
  // é¦–次升级同步品牌主色,避免旧的蓝色偏好遮盖本次主题更新。
  // å‡çº§åŽç”¨æˆ·åœ¨åå¥½è®¾ç½®ä¸­é€‰æ‹©çš„颜色和明暗模式仍会保留。
  document.documentElement.dataset.brandTheme = 'herbal';
  const brandThemeKey = `${namespace}-herbal-theme-v1`;
  // æ¢å¤æ ‡å“é»˜è®¤è“è‰²ä¸»é¢˜ï¼šæ¸…掉之前缓存的朱砂红品牌色。
  // ä¸€æ¬¡æ€§è¿ç§»ï¼Œä¹‹åŽç”¨æˆ·åœ¨åå¥½è®¾ç½®ä¸­é€‰æ‹©çš„颜色仍会保留。
  const themeMigrationKey = `${namespace}-default-blue-theme-v1`;
  const defaultTheme = {
    theme: { builtinType: 'default' as const, colorPrimary: 'hsl(212 100% 45%)' },
  };
  try {
    if (!localStorage.getItem(brandThemeKey)) {
      preferencesManager.updatePreferences({
        theme: { builtinType: 'custom', colorPrimary: '#a51d24' },
      });
      localStorage.setItem(brandThemeKey, '1');
    if (!localStorage.getItem(themeMigrationKey)) {
      preferencesManager.updatePreferences(defaultTheme);
      localStorage.setItem(themeMigrationKey, '1');
      localStorage.removeItem(`${namespace}-herbal-theme-v1`);
    }
  } catch {
    preferencesManager.updatePreferences({
      theme: { builtinType: 'custom', colorPrimary: '#a51d24' },
    });
    preferencesManager.updatePreferences(defaultTheme);
  }
  watch(
    () => preferences.theme.colorPrimary,
    (color) => { document.documentElement.dataset.herbalPalette = String(color.toLowerCase() === '#a51d24'); },
    { immediate: true, flush: 'sync' },
  );
  // å¼ºåˆ¶è¦†ç›–公司 logo å’Œ favicon,绕过 localStorage ç¼“å­˜
  if (__APP_LOGO__) {
src/preferences.ts
@@ -20,10 +20,6 @@
 */
export const overridesPreferences = defineOverridesPreferences({
  // overrides
  theme: {
    builtinType: 'custom',
    colorPrimary: '#a51d24',
  },
  app: {
    /** åŽç«¯è·¯ç”±æ¨¡å¼ */
    accessMode: 'backend',
src/styles/herbal-theme.css
ÎļþÒÑɾ³ý
src/views/_core/authentication/login.vue
@@ -126,7 +126,7 @@
</script>
<template>
  <div class="herbal-login">
  <div>
    <AuthenticationLogin
      ref="loginRef"
      :form-schema="formSchema"
@@ -138,14 +138,7 @@
      :show-forget-password="false"
      :show-doc-link="false"
      @submit="handleLogin"
    >
      <template #title>
        <div class="herbal-login__heading">
          <h1>{{ $t('authentication.welcomeBack') }}<svg class="herbal-login__seal" viewBox="0 0 20 30" aria-hidden="true"><rect x="1" y="1" width="18" height="28" rx="2"/><path d="M5 5h10v8H5V5Zm0 12h10v8H5v-8Zm5-12v8m0 4v8"/></svg></h1>
          <p>{{ $t('authentication.loginSubtitle') }}</p>
        </div>
      </template>
    </AuthenticationLogin>
    />
    <Verification
      ref="verifyRef"
      v-if="captchaEnable"
@@ -158,24 +151,3 @@
    />
  </div>
</template>
<style scoped>
.herbal-login__heading{margin-bottom:32px}
.herbal-login__heading h1{font-size:clamp(28px,2.4vw,36px);font-weight:700;line-height:1.4;letter-spacing:-.02em;margin:0 0 12px;color:#29251f;display:flex;align-items:center;gap:14px}
.herbal-login__heading p{font-size:15px;line-height:1.7;color:#756d63;margin:0}
.herbal-login__seal{width:20px;height:30px;flex-shrink:0;color:#a51d24;fill:none;stroke:currentColor;stroke-width:1.2}
.herbal-login :deep(input:not([type='checkbox'])){min-height:56px;border-radius:9px;border:1px solid #ddd6cc;background:rgba(255,255,255,.82);padding:12px 16px;font-size:16px;color:#30281f}
.herbal-login :deep(input::placeholder){color:#7a7167;opacity:1}
.herbal-login :deep(input:focus-visible){outline:2px solid #a51d24;outline-offset:3px}
.herbal-login :deep(input[autocomplete='current-password']){padding-right:44px}
.herbal-login :deep(button[aria-label='login']){min-height:58px;margin-top:8px;border-radius:9px;background:#a51d24;color:#fff;font-size:19px;font-weight:600;letter-spacing:.12em;box-shadow:0 5px 12px rgba(137,24,30,.12)}
.herbal-login :deep(button[aria-label='login']:hover){background:#87171d}
.herbal-login :deep(button[aria-label='login']:focus-visible){outline:2px solid #a51d24;outline-offset:4px}
.herbal-login :deep(button[aria-label='login']:disabled){opacity:.65;cursor:wait}
:global(.dark .herbal-login__heading h1){color:#f5eee4}
:global(.dark .herbal-login__heading p){color:#d1c1ae}
:global(.dark .herbal-login__seal){color:#eea5a4}
:global(.dark .herbal-login input:not([type='checkbox'])){background:#302720;border-color:#6f5b48;color:#f5eee4}
:global(.dark .herbal-login input::placeholder){color:#c2b29e}
@media(max-width:540px){.herbal-login__heading h1{font-size:28px}.herbal-login__heading p{font-size:14px}.herbal-login :deep(input:not([type='checkbox'])){min-height:52px}}
</style>