feat: 品牌标识用云+数据库矢量图标(favicon + 页眉品牌标)

- Icons.jsx 新增 CloudDbIcon:照 icons8-云 重绘为矢量,左云随主题色、右圆柱用品牌蓝
- GlobalHeader 品牌区前置该图标,原「系统在线」绿点改为挂在其右下角
- index.html 增加 rel=icon / mask-icon 指向 public/favicon.svg
- luxury.css 补品牌样式,并让 :not() 选择器排除 .brand-mark 避免样式误伤
This commit is contained in:
Drsakura
2026-09-10 16:58:52 +08:00
parent 5cff29702b
commit 47f6214056
5 changed files with 38 additions and 3 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import axios from 'axios'
import { BotIcon, ClockIcon, PlusCircleIcon, SearchIcon } from './Icons'
import { BotIcon, ClockIcon, CloudDbIcon, PlusCircleIcon, SearchIcon } from './Icons'
function GlobalHeader({ onOpenAssistant }) {
const [now, setNow] = useState(new Date())
@@ -49,7 +49,7 @@ function GlobalHeader({ onOpenAssistant }) {
return (
<header className="global-header">
<div className="global-header-brand"><span className="header-status-dot" /><div><strong>happy出口通</strong><span>EXPORT OPERATIONS CONSOLE</span></div></div>
<div className="global-header-brand"><span className="brand-mark" title="happy出口通"><CloudDbIcon size={28} /><span className="header-status-dot" /></span><div><strong>happy出口通</strong><span>EXPORT OPERATIONS CONSOLE</span></div></div>
<div className={`global-search ${searchOpen ? 'is-open' : ''}`}>
<SearchIcon size={17} />
<input ref={searchRef} aria-label="搜索 everything" value={query} onFocus={() => setSearchOpen(true)} onChange={event => setQuery(event.target.value)} placeholder="搜索 everything" autoComplete="off" />
+17
View File
@@ -25,6 +25,23 @@ export const FactoryIcon = ({ size = 20, className = '' }) => (
</svg>
)
/* 品牌标识:云 + 数据库圆柱(照 icons8-云 重绘为矢量)
左半边云跟随主题色,右半边圆柱固定品牌蓝;坐标用 24 网格,内部 0.48 缩放。 */
export const CloudDbIcon = ({ size = 20, className = '' }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
{/* 云:闭合圆头轮廓 */}
<g transform="translate(1 6) scale(0.48)" stroke="currentColor" strokeWidth="3.54">
<path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z" />
</g>
{/* 数据库圆柱:顶盖椭圆 + 桶身 + 中间分层线 */}
<g transform="translate(12.4 5.4) scale(0.48)" style={{ stroke: 'var(--primary)' }} strokeWidth="3.54">
<ellipse cx="12" cy="5.5" rx="8.5" ry="3.2" />
<path d="M3.5 5.5V19.5A8.5 3.2 0 0 0 20.5 19.5V5.5" />
<path d="M3.5 12.5A8.5 3.2 0 0 0 20.5 12.5" />
</g>
</svg>
)
export const DownloadIcon = ({ size = 20, className = '' }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
+6 -1
View File
@@ -226,7 +226,7 @@ input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px
.global-header-brand { display: flex; align-items: center; gap: 10px; min-width: 238px; }
.global-header-brand strong, .global-header-brand span { display: block; }
.global-header-brand strong { font-size: 13px; letter-spacing: .02em; }
.global-header-brand span:not(.header-status-dot) { color: var(--text-tertiary); font: 9px var(--font-mono); letter-spacing: .12em; margin-top: 3px; }
.global-header-brand span:not(.header-status-dot):not(.brand-mark) { color: var(--text-tertiary); font: 9px var(--font-mono); letter-spacing: .12em; margin-top: 3px; }
.header-status-dot { width: 8px; height: 8px; flex: 0 0 8px; border-radius: 50%; background: var(--success); box-shadow: 0 0 10px var(--success); }
.global-search { display: flex; align-items: center; gap: 9px; width: min(420px, 35vw); min-height: 38px; padding: 0 11px; color: var(--text-tertiary); background: var(--surface-deep); border: 1px solid var(--border-light); border-radius: 11px; transition: border-color 150ms, box-shadow 150ms; }
.global-search:focus-within { border-color: var(--primary-border); box-shadow: 0 0 0 3px var(--accent-glow); }
@@ -352,3 +352,8 @@ input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px
/* Preserve the dense industrial table's column hierarchy on smaller desktops. */
.table-wrap table { min-width: 980px; }
/* ---- 品牌标识:云 + 数据库(矢量重绘,随主题变色) ---- */
.global-header-brand .brand-mark { position: relative; display: inline-flex; align-items: center; justify-content: center; color: var(--text-primary); }
.global-header-brand .brand-mark svg { display: block; }
.global-header-brand .brand-mark .header-status-dot { position: absolute; right: -1px; bottom: -1px; width: 8px; height: 8px; border-radius: 50%; background: var(--success); box-shadow: 0 0 0 3px var(--bg-primary), 0 0 10px var(--success); }