feat: generic branding, remove all Tianpu hardcoding (v1.3.0)

- Replace all 天普/Tianpu text with generic "智慧能源管理平台"
- Change brandName to "EMS Platform" in both zh/en locales
- Update localStorage keys from tianpu-* to ems-*
- Make login subtitle generic

New customers copying this template will get neutral branding
that they customize for their own park/brand.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Du Wenbo
2026-04-06 22:04:11 +08:00
parent 240975b2c0
commit ba190c33ca
12 changed files with 16 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
{ {
"project": "ems-frontend-template", "project": "ems-frontend-template",
"project_version": "1.2.0", "project_version": "1.3.0",
"core_version": "1.1.0", "core_version": "1.3.0",
"last_updated": "2026-04-06", "last_updated": "2026-04-06",
"notes": "Base React/TypeScript UI template for customer frontends" "notes": "Generic branding, removed all Tianpu-specific hardcoding"
} }

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>天普智慧能源管理平台</title> <title>智慧能源管理平台</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@@ -1,7 +1,7 @@
{ {
"name": "frontend", "name": "frontend",
"private": true, "private": true,
"version": "1.2.0", "version": "1.3.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -12,12 +12,12 @@ const ThemeContext = createContext<ThemeContextType>({
export function ThemeProvider({ children }: { children: ReactNode }) { export function ThemeProvider({ children }: { children: ReactNode }) {
const [darkMode, setDarkMode] = useState(() => { const [darkMode, setDarkMode] = useState(() => {
const saved = localStorage.getItem('tianpu-dark-mode'); const saved = localStorage.getItem('ems-dark-mode');
return saved === 'true'; return saved === 'true';
}); });
useEffect(() => { useEffect(() => {
localStorage.setItem('tianpu-dark-mode', String(darkMode)); localStorage.setItem('ems-dark-mode', String(darkMode));
document.documentElement.setAttribute('data-theme', darkMode ? 'dark' : 'light'); document.documentElement.setAttribute('data-theme', darkMode ? 'dark' : 'light');
}, [darkMode]); }, [darkMode]);

View File

@@ -8,7 +8,7 @@ i18n.use(initReactI18next).init({
zh: { translation: zh }, zh: { translation: zh },
en: { translation: en }, en: { translation: en },
}, },
lng: localStorage.getItem('tianpu-lang') || 'zh', lng: localStorage.getItem('ems-lang') || 'zh',
fallbackLng: 'zh', fallbackLng: 'zh',
interpolation: { interpolation: {
escapeValue: false, escapeValue: false,

View File

@@ -29,7 +29,7 @@
"viewAllAlarms": "View all alarms", "viewAllAlarms": "View all alarms",
"profile": "Profile", "profile": "Profile",
"logout": "Sign Out", "logout": "Sign Out",
"brandName": "Tianpu EMS" "brandName": "EMS Platform"
}, },
"common": { "common": {
"save": "Save", "save": "Save",

View File

@@ -29,7 +29,7 @@
"viewAllAlarms": "查看全部告警", "viewAllAlarms": "查看全部告警",
"profile": "个人信息", "profile": "个人信息",
"logout": "退出登录", "logout": "退出登录",
"brandName": "天普EMS" "brandName": "EMS Platform"
}, },
"common": { "common": {
"save": "保存", "save": "保存",

View File

@@ -101,7 +101,7 @@ export default function MainLayout() {
const handleLanguageChange = (lang: string) => { const handleLanguageChange = (lang: string) => {
i18n.changeLanguage(lang); i18n.changeLanguage(lang);
localStorage.setItem('tianpu-lang', lang); localStorage.setItem('ems-lang', lang);
}; };
const userMenu = { const userMenu = {

View File

@@ -131,7 +131,7 @@ export default function BigScreen() {
{/* Header */} {/* Header */}
<div className={styles.header}> <div className={styles.header}>
<span className={styles.headerDate}>{formatDate(clock)}</span> <span className={styles.headerDate}>{formatDate(clock)}</span>
<h1 className={styles.headerTitle}></h1> <h1 className={styles.headerTitle}></h1>
<span className={styles.headerTime}>{formatTime(clock)}</span> <span className={styles.headerTime}>{formatTime(clock)}</span>
</div> </div>

View File

@@ -47,7 +47,7 @@ export default function HUDOverlay({ overview, realtimeData }: HUDOverlayProps)
<div className={styles.hudOverlay}> <div className={styles.hudOverlay}>
<div className={styles.header}> <div className={styles.header}>
<span className={styles.headerDate}>{formatDate(now)}</span> <span className={styles.headerDate}>{formatDate(now)}</span>
<span className={styles.headerTitle}> 3D智慧能源管理平台</span> <span className={styles.headerTitle}>3D智慧能源管理平台</span>
<span className={styles.headerClock}>{formatTime(now)}</span> <span className={styles.headerClock}>{formatTime(now)}</span>
</div> </div>

View File

@@ -71,7 +71,7 @@ export default function BigScreen3D() {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.placeholder}> <div className={styles.placeholder}>
<h2 className={styles.placeholderTitle}> 3D智慧能源管理平台</h2> <h2 className={styles.placeholderTitle}>3D智慧能源管理平台</h2>
<p style={{ color: '#8899aa' }}>...</p> <p style={{ color: '#8899aa' }}>...</p>
</div> </div>
</div> </div>

View File

@@ -54,9 +54,9 @@ export default function LoginPage() {
<div style={{ textAlign: 'center', marginBottom: 32 }}> <div style={{ textAlign: 'center', marginBottom: 32 }}>
<ThunderboltOutlined style={{ fontSize: 48, color: '#1890ff' }} /> <ThunderboltOutlined style={{ fontSize: 48, color: '#1890ff' }} />
<Title level={3} style={{ marginTop: 12, marginBottom: 4 }}> <Title level={3} style={{ marginTop: 12, marginBottom: 4 }}>
</Title> </Title>
<Text type="secondary"> · </Text> <Text type="secondary"> · </Text>
</div> </div>
<Form onFinish={onFinish} size="large"> <Form onFinish={onFinish} size="large">
<Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}> <Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}>