Parcourir la source

✨ feat(header): 统一移动端一级页面HeaderLogo组件

- 创建移动端页面头部组件PageHeader.tsx,支持logo和标题显示
- 实现银龄岗位、人才库、智库等核心页面HeaderLogo组件替换
- 制定HeaderLogo组件使用规范文档,明确导入和布局标准
- 更新政策资讯、时间银行等服务页面,统一品牌视觉展示

📝 docs: 添加移动端HeaderLogo实施计划文档

- 记录当前页面状态,标记已完成和待更新页面
- 定义HeaderLogo组件属性和样式规范
- 制定优先级实施步骤和验证检查清单
- 提供代码示例和布局结构参考
yourname il y a 9 mois
Parent
commit
08c3c6ae3e

+ 165 - 0
mobile-header-logo-implementation-plan.md

@@ -0,0 +1,165 @@
+# 移动端一级页面HeaderLogo统一实施计划
+
+## 项目概述
+统一移动端所有一级页面顶部显示,采用HeaderLogo组件实现品牌一致性。
+
+## 当前状态分析
+
+### 已实现页面
+- ✅ **NewHomePage.tsx** - 已正确使用HeaderLogo组件
+  ```tsx
+  import HeaderLogo from '../components/HeaderLogo';
+  // 使用位置:第334行
+  <HeaderLogo className="flex-1" />
+  ```
+
+### 待更新页面
+- ❌ **SilverJobsPage.tsx** - 使用自定义标题"银龄岗位"
+- ❌ **SilverTalentsPage.tsx** - 使用自定义标题"银龄人才库"
+- ❌ **SilverWisdomPage.tsx** - 需要检查
+- ❌ **TimeBankPage.tsx** - 需要检查
+- ❌ **PolicyNewsPage.tsx** - 需要检查
+- ❌ **ElderlyUniversityPage.tsx** - 需要检查
+
+## HeaderLogo组件特性
+
+### 组件属性
+```typescript
+interface HeaderLogoProps {
+  className?: string;
+  logoSize?: 'sm' | 'md' | 'lg';  // 默认: 'md'
+  showName?: boolean;             // 默认: true
+}
+```
+
+### 样式规范
+- 水墨风格配色方案
+- 响应式设计
+- 支持自定义样式扩展
+
+## 更新规范
+
+### 1. 导入语句
+```typescript
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
+```
+
+### 2. 使用标准
+- **一级页面**:使用HeaderLogo作为顶部品牌标识
+- **二级页面**:可使用页面特定标题
+- **logoSize**:一级页面使用`md`(默认)
+- **className**:根据需要调整布局
+
+### 3. 布局结构
+```tsx
+<header className="sticky top-0 z-10 shadow-sm border-b px-4 py-4" 
+        style={{ backgroundColor: 'rgba(255,255,255,0.8)', borderColor: INK_COLORS.ink.medium }}>
+  <div className="flex items-center justify-between">
+    <HeaderLogo />
+    {/* 右侧操作按钮区域 */}
+    <div className="flex items-center space-x-2">
+      {/* 搜索、设置等按钮 */}
+    </div>
+  </div>
+</header>
+```
+
+## 页面更新清单
+
+### 优先级1:核心业务页面
+1. **SilverJobsPage.tsx** - 银龄岗位页面
+2. **SilverTalentsPage.tsx** - 银龄人才页面
+3. **SilverWisdomPage.tsx** - 银龄知识页面
+
+### 优先级2:服务页面
+4. **TimeBankPage.tsx** - 时间银行页面
+5. **PolicyNewsPage.tsx** - 政策资讯页面
+6. **ElderlyUniversityPage.tsx** - 老年大学页面
+
+### 优先级3:用户相关页面
+7. **ProfilePage/index.tsx** - 用户资料页面
+8. **MemberPage.tsx** - 会员中心页面
+
+## 实施步骤
+
+### 步骤1:更新SilverJobsPage.tsx
+```diff
+- import { INK_COLORS } from '@/client/mobile/styles/colors';
++ import HeaderLogo from '@/client/mobile/components/HeaderLogo';
++ import { INK_COLORS } from '@/client/mobile/styles/colors';
+
+- <div>
+-   <h1 className="font-serif text-xl font-bold" style={{ color: INK_COLORS.ink.deep }}>银龄岗位</h1>
+-   <p className="text-xs mt-1" style={{ color: INK_COLORS.text.secondary }}>发现适合银龄人才的优质岗位</p>
+- </div>
++ <HeaderLogo />
+```
+
+### 步骤2:更新SilverTalentsPage.tsx
+```diff
+- <h1 className="font-serif text-2xl font-bold tracking-wide"
+-   style={{ color: COLORS.text.primary }}>
+-   银龄人才库
+- </h1>
++ <HeaderLogo />
+```
+
+### 步骤3:批量更新其他页面
+统一使用HeaderLogo组件,移除自定义标题文本。
+
+## 验证检查
+
+### 1. 功能验证
+- [ ] 所有一级页面正确显示HeaderLogo
+- [ ] 品牌标识一致性
+- [ ] 响应式布局正常
+- [ ] 交互功能正常
+
+### 2. 视觉验证
+- [ ] 色彩方案统一
+- [ ] 字体大小一致
+- [ ] 间距布局合理
+- [ ] 移动端适配良好
+
+### 3. 用户体验
+- [ ] 品牌认知度提升
+- [ ] 页面导航清晰
+- [ ] 操作按钮易于访问
+
+## 技术实现
+
+### 代码模式
+```tsx
+// 标准头部组件
+const PageHeader: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
+  <header className="sticky top-0 z-10 shadow-sm border-b px-4 py-4"
+          style={{ backgroundColor: 'rgba(255,255,255,0.8)', borderColor: INK_COLORS.ink.medium }}>
+    <div className="flex items-center justify-between">
+      <HeaderLogo />
+      {children}
+    </div>
+  </header>
+);
+
+// 使用方式
+<PageHeader>
+  <div className="flex items-center space-x-2">
+    <SearchButton />
+    <SettingsButton />
+  </div>
+</PageHeader>
+```
+
+## 注意事项
+
+1. **向后兼容**:确保不影响现有功能
+2. **性能优化**:HeaderLogo组件已优化,无需额外处理
+3. **无障碍**:保持可访问性标准
+4. **测试覆盖**:需要验证所有目标页面
+
+## 完成标准
+
+- [ ] 所有一级页面使用HeaderLogo组件
+- [ ] 品牌视觉统一性达成
+- [ ] 用户体验无明显下降
+- [ ] 代码审查通过

+ 48 - 0
src/client/mobile/components/PageHeader.tsx

@@ -0,0 +1,48 @@
+import React from 'react';
+import HeaderLogo from './HeaderLogo';
+import { INK_COLORS } from '../styles/colors';
+
+interface PageHeaderProps {
+  title?: string;
+  rightContent?: React.ReactNode;
+  showLogo?: boolean;
+  className?: string;
+}
+
+const PageHeader: React.FC<PageHeaderProps> = ({ 
+  title,
+  rightContent,
+  showLogo = true,
+  className = ''
+}) => {
+  return (
+    <header 
+      className={`shadow-sm sticky top-0 z-10 border-b border-opacity-20 px-4 py-4 ${className}`}
+      style={{ 
+        backgroundColor: COLORS.ink.light,
+        borderColor: COLORS.ink.medium 
+      }}
+    >
+      <div className="flex items-center justify-between">
+        {showLogo ? (
+          <HeaderLogo />
+        ) : (
+          title && (
+            <h1 className="font-serif text-xl font-bold tracking-wide" style={{ color: COLORS.text.primary }}>
+              {title}
+            </h1>
+          )
+        )}
+        {rightContent && (
+          <div className="flex items-center space-x-2">
+            {rightContent}
+          </div>
+        )}
+      </div>
+    </header>
+  );
+};
+
+const COLORS = INK_COLORS;
+
+export default PageHeader;

+ 8 - 12
src/client/mobile/pages/PolicyNewsPage.tsx

@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
 import { useQueryClient } from '@tanstack/react-query';
 import { usePolicyNewsData, type PolicyNewsItem } from '../hooks/usePolicyNewsData';
 import PolicyNewsCard from '../components/PolicyNewsCard';
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
 import { SkeletonLoader } from '../components/SkeletonLoader';
 import {
   CalendarDaysIcon,
@@ -155,32 +156,27 @@ const PolicyNewsPage: React.FC = () => {
   return (
     <div className="min-h-screen pb-16" style={{ backgroundColor: COLORS.ink.light }}>
       {/* 头部导航 */}
-      <header 
+      <header
         className="sticky top-0 z-10 shadow-sm border-b border-opacity-20"
-        style={{ 
+        style={{
           backgroundColor: COLORS.ink.light,
-          borderColor: COLORS.ink.medium 
+          borderColor: COLORS.ink.medium
         }}
       >
         <div className="px-4 py-4">
           <div className="flex items-center justify-between mb-3">
-            <h1 
-              className={FONT_STYLES.title}
-              style={{ color: COLORS.text.primary }}
-            >
-              政策资讯
-            </h1>
+            <HeaderLogo />
             <button
               onClick={handleRefresh}
               disabled={isRefreshing}
               className="p-2 rounded-full transition-all duration-300 hover:shadow-md"
-              style={{ 
+              style={{
                 backgroundColor: 'rgba(255,255,255,0.7)',
                 color: COLORS.text.primary
               }}
             >
-              <ArrowPathIcon 
-                className={`w-5 h-5 ${isRefreshing ? 'animate-spin' : ''}`} 
+              <ArrowPathIcon
+                className={`w-5 h-5 ${isRefreshing ? 'animate-spin' : ''}`}
               />
             </button>
           </div>

+ 2 - 4
src/client/mobile/pages/SilverJobsPage.tsx

@@ -2,6 +2,7 @@ import React, { useState } from 'react';
 import { useNavigate } from 'react-router-dom';
 import { JobCard } from '@/client/mobile/components/silver-jobs/JobCard';
 import { useJobs, JobItem } from '@/client/mobile/hooks/useJobs';
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
 import { INK_COLORS } from '@/client/mobile/styles/colors';
 
 const SilverJobsPage: React.FC = () => {
@@ -23,10 +24,7 @@ const SilverJobsPage: React.FC = () => {
       {/* 头部导航栏 */}
       <header className="sticky top-0 z-10 shadow-sm border-b px-4 py-4" style={{ backgroundColor: 'rgba(255,255,255,0.8)', borderColor: INK_COLORS.ink.medium }}>
         <div className="flex items-center justify-between">
-          <div>
-            <h1 className="font-serif text-xl font-bold" style={{ color: INK_COLORS.ink.deep }}>银龄岗位</h1>
-            <p className="text-xs mt-1" style={{ color: INK_COLORS.text.secondary }}>发现适合银龄人才的优质岗位</p>
-          </div>
+          <HeaderLogo />
           <div className="flex items-center space-x-2">
             <button className="p-2 rounded-full" style={{ backgroundColor: INK_COLORS.accent.blue + '20', color: INK_COLORS.accent.blue }}>🔍</button>
             <button className="p-2 rounded-full" style={{ backgroundColor: INK_COLORS.accent.green + '20', color: INK_COLORS.accent.green }}>⚙️</button>

+ 8 - 12
src/client/mobile/pages/SilverTalentsPage.tsx

@@ -1,6 +1,7 @@
 import React, { useState } from 'react';
 import { useNavigate } from 'react-router-dom';
 import { useSilverTalentsData } from '../hooks/useSilverTalentsData';
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
 import { MagnifyingGlassIcon, UserIcon } from '@heroicons/react/24/outline';
 import { HeartIcon } from '@heroicons/react/24/solid';
 
@@ -82,24 +83,19 @@ const SilverTalentsPage: React.FC = () => {
   return (
     <div className="min-h-screen" style={{ backgroundColor: COLORS.ink.light }}>
       {/* 头部导航 - 水墨风格 */}
-      <header 
+      <header
         className="shadow-sm sticky top-0 z-10 border-b border-opacity-20 px-4 py-4"
-        style={{ 
-          backgroundColor: COLORS.ink.light, 
-          borderColor: COLORS.ink.medium 
+        style={{
+          backgroundColor: COLORS.ink.light,
+          borderColor: COLORS.ink.medium
         }}
       >
         <div className="flex items-center justify-between">
-          <h1 
-            className="font-serif text-2xl font-bold tracking-wide"
-            style={{ color: COLORS.text.primary }}
-          >
-            银龄人才库
-          </h1>
-          <UserIcon 
+          <HeaderLogo />
+          <UserIcon
             className="w-6 h-6 cursor-pointer transition-colors duration-300 hover:text-orange-600"
             style={{ color: COLORS.ink.dark }}
-            onClick={() => navigate('/profile')} 
+            onClick={() => navigate('/profile')}
           />
         </div>
       </header>

+ 8 - 12
src/client/mobile/pages/SilverWisdomPage.tsx

@@ -2,6 +2,7 @@ import React, { useState } from 'react';
 import { useNavigate } from 'react-router-dom';
 import { useSilverWisdomData } from '../hooks/useSilverWisdomData';
 import type { SilverWisdomItem } from '../hooks/useSilverWisdomData';
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
 import {
   MagnifyingGlassIcon,
   UserIcon,
@@ -117,24 +118,19 @@ const SilverWisdomPage: React.FC = () => {
   return (
     <div className="min-h-screen" style={{ backgroundColor: COLORS.ink.light }}>
       {/* 头部导航 - 水墨风格 */}
-      <header 
+      <header
         className="shadow-sm sticky top-0 z-10 border-b border-opacity-20 px-4 py-4"
-        style={{ 
-          backgroundColor: COLORS.ink.light, 
-          borderColor: COLORS.ink.medium 
+        style={{
+          backgroundColor: COLORS.ink.light,
+          borderColor: COLORS.ink.medium
         }}
       >
         <div className="flex items-center justify-between">
-          <h1 
-            className={FONT_STYLES.sectionTitle}
-            style={{ color: COLORS.text.primary }}
-          >
-            银龄智库
-          </h1>
-          <UserIcon 
+          <HeaderLogo />
+          <UserIcon
             className="w-6 h-6 cursor-pointer transition-colors duration-300 hover:text-orange-600"
             style={{ color: COLORS.ink.dark }}
-            onClick={() => navigate('/profile')} 
+            onClick={() => navigate('/profile')}
           />
         </div>
       </header>

+ 4 - 5
src/client/mobile/pages/TimeBankPage.tsx

@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
 import { ClockIcon, TrophyIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
 import TimeBankCard from '../components/TimeBankCard';
 import { useTimeBankData } from '../hooks/useTimeBankData';
+import HeaderLogo from '@/client/mobile/components/HeaderLogo';
 import { SkeletonLoader } from '../components/SkeletonLoader';
 import { INK_COLORS } from '../styles/colors';
 import { FONT_STYLES } from '../styles/typography';
@@ -92,21 +93,19 @@ const TimeBankPage: React.FC = () => {
   return (
     <div className="min-h-screen" style={{ backgroundColor: COLORS.ink.light }}>
       {/* 头部导航 */}
-      <header 
+      <header
         className="shadow-sm sticky top-0 z-10 border-b border-opacity-20 px-4 py-4"
         style={{ backgroundColor: COLORS.ink.light, borderColor: COLORS.ink.medium }}
       >
         <div className="flex items-center justify-between">
-          <h1 className={`${FONT_STYLES.title}`} style={{ color: COLORS.text.primary }}>
-            时间银行
-          </h1>
+          <HeaderLogo />
           <button
             onClick={refreshActivities}
             disabled={refreshing}
             className="p-2 rounded-full transition-all duration-300 hover:shadow-md"
             style={{ backgroundColor: 'rgba(255,255,255,0.7)' }}
           >
-            <ArrowPathIcon 
+            <ArrowPathIcon
               className={`w-5 h-5 ${refreshing ? 'animate-spin' : ''}`}
               style={{ color: COLORS.ink.dark }}
             />