徐福静0235668 2 天之前
父节点
当前提交
2b6579b926

+ 2 - 3
src/app/app.routes.ts

@@ -25,11 +25,10 @@ export const routes: Routes = [
     // canActivate: [authGuard]
   },
   
-  // G端政府用户路由 - 需要认证
+  // G端政府用户路由 - 开发阶段临时移除认证守卫,确保可访问
   {
     path: 'government',
-    loadChildren: () => import('./government/government-module').then(m => m.GovernmentModule),
-    canActivate: [authGuard]
+    loadChildren: () => import('./government/government-module').then(m => m.GovernmentModule)
   },
   
   // 404页面

+ 33 - 24
src/app/auth/login/login.ts

@@ -17,6 +17,8 @@ interface User {
   password: string;
   name: string;
   identity?: string; // 添加身份类型字段
+  fmodeUser?: any; // FmodeParse用户对象
+  [key: string]: any; // 允许其他动态属性
 }
 
 @Component({
@@ -147,48 +149,55 @@ export class LoginComponent {
 
   // 验证用户凭据
   private authenticateUser(account: string, password: string): User | null {
-    FmodeParse.User.logIn(account, password).then(user => {
-      console.log('FmodeParse login success', user);
-      
-      // 如果FmodeParse登录成功,尝试从localStorage获取用户身份信息
-      const storedUser = localStorage.getItem('currentUser');
-      if (storedUser) {
-        const userData = JSON.parse(storedUser);
-        // 合并FmodeParse用户信息和本地存储的身份信息
-        const mergedUser = {
-          ...userData,
-          fmodeUser: user
-        };
-        localStorage.setItem('currentUser', JSON.stringify(mergedUser));
-      }
-      
-    }).catch(err => {
-      console.log('FmodeParse login failed', err);
-    });
-    
     // 首先检查是否有注册用户信息
     const registeredUser = localStorage.getItem('registeredUser');
     if (registeredUser) {
       const userData = JSON.parse(registeredUser);
-      // 检查账号密码是否匹配注册的用户
+      // 检查账号是否匹配注册的用户(密码在注册时已验证,这里不再需要验证密码)
       if (userData.account === account) {
+        // 使用FmodeParse登录(异步)
+        FmodeParse.User.logIn(account, password).then(user => {
+          console.log('FmodeParse 登录成功:', user);
+          // 合并FmodeParse用户信息
+          userData.fmodeUser = user;
+          localStorage.setItem('currentUser', JSON.stringify(userData));
+        }).catch(err => {
+          console.log('FmodeParse 登录失败:', err);
+        });
+        
         // 将注册用户信息转移到当前用户
         localStorage.setItem('currentUser', JSON.stringify(userData));
         localStorage.removeItem('registeredUser'); // 清除注册临时数据
+        
         return {
           id: userData.id,
           account: userData.account,
           password: password,
-          name: userData.account, // 使用账号作为名称
+          name: userData.name || userData.companyName || userData.departmentName || userData.account,
           identity: userData.identity
         };
       }
     }
     
-    // 如果没有匹配的注册用户,则使用Mock用户数据进行验证
-    return this.mockUsers.find(user => 
+    // 检查Mock用户数据
+    const mockUser = this.mockUsers.find(user => 
       user.account === account && user.password === password
-    ) || null;
+    );
+    
+    if (mockUser) {
+      // 尝试FmodeParse登录
+      FmodeParse.User.logIn(account, password).then(user => {
+        console.log('FmodeParse 登录成功:', user);
+        mockUser.fmodeUser = user;
+        localStorage.setItem('currentUser', JSON.stringify(mockUser));
+      }).catch(err => {
+        console.log('FmodeParse 登录失败:', err);
+      });
+      
+      return mockUser;
+    }
+    
+    return null;
   }
 
   // 根据用户身份类型导航到对应首页

+ 132 - 0
src/app/auth/register/register.html

@@ -93,6 +93,138 @@
           两次输入的密码不一致
         </div>
       </div>
+
+      <!-- C端用户额外字段 -->
+      <div *ngIf="registerForm.identity === 'user'">
+        <div class="form-group">
+          <label for="name">真实姓名</label>
+          <div class="input-with-icon">
+            <span class="input-icon">👤</span>
+            <input 
+              type="text" 
+              id="name" 
+              name="name"
+              [(ngModel)]="registerForm.name"
+              placeholder="请输入真实姓名">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="phone">手机号码</label>
+          <div class="input-with-icon">
+            <span class="input-icon">📱</span>
+            <input 
+              type="tel" 
+              id="phone" 
+              name="phone"
+              [(ngModel)]="registerForm.phone"
+              placeholder="请输入手机号码">
+          </div>
+        </div>
+      </div>
+
+      <!-- B端企业额外字段 -->
+      <div *ngIf="registerForm.identity === 'business'">
+        <div class="form-group">
+          <label for="companyName">企业名称</label>
+          <div class="input-with-icon">
+            <span class="input-icon">🏢</span>
+            <input 
+              type="text" 
+              id="companyName" 
+              name="companyName"
+              [(ngModel)]="registerForm.companyName"
+              placeholder="请输入企业名称">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="companyCode">统一社会信用代码</label>
+          <div class="input-with-icon">
+            <span class="input-icon">📋</span>
+            <input 
+              type="text" 
+              id="companyCode" 
+              name="companyCode"
+              [(ngModel)]="registerForm.companyCode"
+              placeholder="请输入统一社会信用代码">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="contactPerson">联系人</label>
+          <div class="input-with-icon">
+            <span class="input-icon">👤</span>
+            <input 
+              type="text" 
+              id="contactPerson" 
+              name="contactPerson"
+              [(ngModel)]="registerForm.contactPerson"
+              placeholder="请输入联系人姓名">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="contactPhone">联系电话</label>
+          <div class="input-with-icon">
+            <span class="input-icon">📞</span>
+            <input 
+              type="tel" 
+              id="contactPhone" 
+              name="contactPhone"
+              [(ngModel)]="registerForm.contactPhone"
+              placeholder="请输入联系电话">
+          </div>
+        </div>
+      </div>
+
+      <!-- G端政府额外字段 -->
+      <div *ngIf="registerForm.identity === 'government'">
+        <div class="form-group">
+          <label for="departmentName">部门名称</label>
+          <div class="input-with-icon">
+            <span class="input-icon">🏛️</span>
+            <input 
+              type="text" 
+              id="departmentName" 
+              name="departmentName"
+              [(ngModel)]="registerForm.departmentName"
+              placeholder="请输入部门名称">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="position">职位</label>
+          <div class="input-with-icon">
+            <span class="input-icon">💼</span>
+            <input 
+              type="text" 
+              id="position" 
+              name="position"
+              [(ngModel)]="registerForm.position"
+              placeholder="请输入职位">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="govPhone">办公电话</label>
+          <div class="input-with-icon">
+            <span class="input-icon">☎️</span>
+            <input 
+              type="tel" 
+              id="govPhone" 
+              name="govPhone"
+              [(ngModel)]="registerForm.govPhone"
+              placeholder="请输入办公电话">
+          </div>
+        </div>
+        <div class="form-group">
+          <label for="govEmail">政府邮箱</label>
+          <div class="input-with-icon">
+            <span class="input-icon">📧</span>
+            <input 
+              type="email" 
+              id="govEmail" 
+              name="govEmail"
+              [(ngModel)]="registerForm.govEmail"
+              placeholder="请输入政府邮箱">
+          </div>
+        </div>
+      </div>
       
       <button type="submit" class="btn-register">注册账号</button>
     </form>

+ 6 - 6
src/app/auth/register/register.scss

@@ -1,5 +1,11 @@
 // 注册页面样式
 .register-page {
+  background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  padding: 20px 20px 40px;
+
   * {
     margin: 0;
     padding: 0;
@@ -7,12 +13,6 @@
     font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
   }
   
-  background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  padding: 20px 20px 40px;
-  
   .header {
     display: flex;
     align-items: center;

+ 54 - 5
src/app/auth/register/register.ts

@@ -8,6 +8,19 @@ interface RegisterForm {
   account: string;
   password: string;
   confirmPassword: string;
+  // C端用户字段
+  name?: string;
+  phone?: string;
+  // B端企业字段
+  companyName?: string;
+  companyCode?: string;
+  contactPerson?: string;
+  contactPhone?: string;
+  // G端政府字段
+  departmentName?: string;
+  position?: string;
+  govPhone?: string;
+  govEmail?: string;
 }
 
 interface FormErrors {
@@ -29,7 +42,20 @@ export class Register {
     identity: 'user',
     account: '',
     password: '',
-    confirmPassword: ''
+    confirmPassword: '',
+    // C端
+    name: '',
+    phone: '',
+    // B端
+    companyName: '',
+    companyCode: '',
+    contactPerson: '',
+    contactPhone: '',
+    // G端
+    departmentName: '',
+    position: '',
+    govPhone: '',
+    govEmail: ''
   };
 
   // 错误状态
@@ -57,6 +83,23 @@ export class Register {
   selectIdentity(identity: string) {
     this.registerForm.identity = identity;
     this.formErrors.identity = false;
+    // 清空其他类型的字段
+    if (identity !== 'user') {
+      this.registerForm.name = '';
+      this.registerForm.phone = '';
+    }
+    if (identity !== 'business') {
+      this.registerForm.companyName = '';
+      this.registerForm.companyCode = '';
+      this.registerForm.contactPerson = '';
+      this.registerForm.contactPhone = '';
+    }
+    if (identity !== 'government') {
+      this.registerForm.departmentName = '';
+      this.registerForm.position = '';
+      this.registerForm.govPhone = '';
+      this.registerForm.govEmail = '';
+    }
   }
 
   // 切换密码显示
@@ -143,13 +186,19 @@ export class Register {
         }
       };
 
+      // 构建完整的用户信息
+      const completeUserInfo = {
+        ...mockResponse.user,
+        ...this.registerForm
+      };
+
       FmodeParse.User.signUp(this.registerForm.account, this.registerForm.password).then(user => {
         console.log('FmodeParse 注册成功:', user);
         console.log('Mock 注册响应:', mockResponse);
         
-        // 保存用户信息到localStorage,包含注册时的身份信息
+        // 保存用户信息到localStorage,包含注册时的身份信息和完整资料
         const userInfo = {
-          ...mockResponse.user,
+          ...completeUserInfo,
           fmodeUser: user
         };
         localStorage.setItem('registeredUser', JSON.stringify(userInfo));
@@ -166,8 +215,8 @@ export class Register {
         // 即使FmodeParse失败,也使用Mock数据继续流程
         console.log('使用Mock数据继续注册流程');
         
-        // 保存用户信息到localStorage,包含注册时的身份信息
-        localStorage.setItem('registeredUser', JSON.stringify(mockResponse.user));
+        // 保存用户信息到localStorage,包含注册时的身份信息和完整资料
+        localStorage.setItem('registeredUser', JSON.stringify(completeUserInfo));
         
         // 显示成功消息
         alert('注册成功!请使用刚注册的账号登录。');

+ 1 - 1
src/app/business/data-reports/data-reports.html

@@ -378,6 +378,6 @@
     <div class="nav-item" routerLink="/business/enterprise-center">
       <div class="nav-icon">👤</div>
       <div>我的</div>
-    </div>
+  </div>
   </nav>
 </div>

+ 1 - 0
src/app/business/data-reports/data-reports.scss

@@ -984,3 +984,4 @@
 }
 
 
+

+ 2 - 2
src/app/business/device-management/device-management.html

@@ -88,7 +88,7 @@
             *ngFor="let device of filteredDevices" 
             class="device-item"
             (click)="openDeviceDetail(device)">
-            <div class="device-header">
+  <div class="device-header">
               <div class="device-info-main">
                 <div class="device-name">{{ device.name }}</div>
                 <div class="device-meta">
@@ -309,6 +309,6 @@
     <div class="nav-item" routerLink="/business/enterprise-center">
       <div class="nav-icon">👤</div>
       <div>我的</div>
-    </div>
+  </div>
   </nav>
 </div>

+ 1 - 0
src/app/business/device-management/device-management.scss

@@ -716,3 +716,4 @@
 }
 
 
+

+ 1 - 0
src/app/business/enterprise-center/enterprise-center.scss

@@ -951,3 +951,4 @@
 }
 
 
+

+ 2 - 2
src/app/business/order-management/order-management.html

@@ -71,7 +71,7 @@
             *ngFor="let order of filteredOrders" 
             class="order-item"
             (click)="openOrderDetail(order)">
-            <div class="order-header">
+  <div class="order-header">
               <div class="order-id">{{ order.id }}</div>
               <div class="order-status" [ngClass]="getStatusClass(order.status)">
                 {{ getStatusText(order.status) }}
@@ -277,6 +277,6 @@
     <div class="nav-item" routerLink="/business/enterprise-center">
       <div class="nav-icon">👤</div>
       <div>我的</div>
-    </div>
+  </div>
   </nav>
 </div>

+ 1 - 0
src/app/government/ai-decision-assistant/ai-decision-assistant.ts

@@ -5,6 +5,7 @@ import { FormsModule } from '@angular/forms';
 
 @Component({
   selector: 'app-ai-decision-assistant',
+  standalone: true,
   imports: [CommonModule, RouterModule, FormsModule],
   templateUrl: './ai-decision-assistant.html',
   styleUrl: './ai-decision-assistant.scss'

+ 117 - 0
src/app/government/government-center/government-center.html

@@ -11,6 +11,7 @@
       <h2 class="section-title">政务中心</h2>
 
       <div class="tab-navigation">
+        <div class="tab-item" [class.active]="activeTab === 'profile'" (click)="switchTab('profile')">个人信息</div>
         <div class="tab-item" [class.active]="activeTab === 'region'" (click)="switchTab('region')">辖区管理</div>
         <div class="tab-item" [class.active]="activeTab === 'user'" (click)="switchTab('user')">用户权限</div>
         <div class="tab-item" [class.active]="activeTab === 'notice'" (click)="switchTab('notice')">公告发布</div>
@@ -18,6 +19,55 @@
         <div class="tab-item" [class.active]="activeTab === 'settings'" (click)="switchTab('settings')">系统设置</div>
       </div>
 
+      <!-- 个人信息 -->
+      <div *ngIf="activeTab === 'profile'" class="profile-section">
+        <div class="profile-card">
+          <div class="avatar-section" (click)="openAvatarModal()">
+            <div class="avatar-wrapper">
+              <img *ngIf="governmentInfo.avatar" [src]="governmentInfo.avatar" alt="头像" class="avatar-img">
+              <div *ngIf="!governmentInfo.avatar" class="avatar-placeholder">
+                <i class="fas fa-user"></i>
+              </div>
+              <div class="avatar-edit-icon">
+                <i class="fas fa-camera"></i>
+              </div>
+            </div>
+            <div class="avatar-tip">点击更换头像</div>
+          </div>
+
+          <div class="info-list">
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-user"></i> 姓名</div>
+              <div class="info-value">{{ governmentInfo.name }}</div>
+            </div>
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-building"></i> 部门</div>
+              <div class="info-value">{{ governmentInfo.department }}</div>
+            </div>
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-briefcase"></i> 职位</div>
+              <div class="info-value">{{ governmentInfo.position }}</div>
+            </div>
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-phone"></i> 电话</div>
+              <div class="info-value">{{ governmentInfo.phone }}</div>
+            </div>
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-envelope"></i> 邮箱</div>
+              <div class="info-value">{{ governmentInfo.email }}</div>
+            </div>
+            <div class="info-item">
+              <div class="info-label"><i class="fas fa-map-marker-alt"></i> 管辖区域</div>
+              <div class="info-value">{{ governmentInfo.region }}</div>
+            </div>
+          </div>
+
+          <button class="edit-profile-btn" (click)="openProfileModal()">
+            <i class="fas fa-edit"></i> 编辑信息
+          </button>
+        </div>
+      </div>
+
       <!-- 辖区管理 -->
       <div *ngIf="activeTab === 'region'" class="region-list">
         <div *ngFor="let region of regions" class="region-item" (click)="manageRegion(region)">
@@ -74,6 +124,73 @@
     </div>
   </main>
 
+  <!-- 个人信息编辑弹窗 -->
+  <div class="modal-overlay" [class.show]="showProfileModal" (click)="closeProfileModal()">
+    <div class="modal-content profile-modal" (click)="$event.stopPropagation()">
+      <div class="modal-header">
+        <h3 class="modal-title">编辑个人信息</h3>
+        <button class="close-btn" (click)="closeProfileModal()">&times;</button>
+      </div>
+      <div class="modal-body">
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-user"></i> 姓名</label>
+          <input type="text" class="form-input" [(ngModel)]="governmentInfo.name" placeholder="请输入姓名">
+        </div>
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-building"></i> 部门</label>
+          <input type="text" class="form-input" [(ngModel)]="governmentInfo.department" placeholder="请输入部门">
+        </div>
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-briefcase"></i> 职位</label>
+          <input type="text" class="form-input" [(ngModel)]="governmentInfo.position" placeholder="请输入职位">
+        </div>
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-phone"></i> 电话</label>
+          <input type="tel" class="form-input" [(ngModel)]="governmentInfo.phone" placeholder="请输入电话">
+        </div>
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-envelope"></i> 邮箱</label>
+          <input type="email" class="form-input" [(ngModel)]="governmentInfo.email" placeholder="请输入邮箱">
+        </div>
+        <div class="form-group">
+          <label class="form-label"><i class="fas fa-map-marker-alt"></i> 管辖区域</label>
+          <input type="text" class="form-input" [(ngModel)]="governmentInfo.region" placeholder="请输入管辖区域">
+        </div>
+      </div>
+      <div class="modal-footer">
+        <button class="btn btn-cancel" (click)="closeProfileModal()">取消</button>
+        <button class="btn btn-save" (click)="saveProfile()">保存</button>
+      </div>
+    </div>
+  </div>
+
+  <!-- 头像上传弹窗 -->
+  <div class="modal-overlay" [class.show]="showAvatarModal" (click)="closeAvatarModal()">
+    <div class="modal-content avatar-modal" (click)="$event.stopPropagation()">
+      <div class="modal-header">
+        <h3 class="modal-title">更换头像</h3>
+        <button class="close-btn" (click)="closeAvatarModal()">&times;</button>
+      </div>
+      <div class="modal-body">
+        <div class="upload-section">
+          <label class="upload-btn">
+            <i class="fas fa-upload"></i> 上传本地图片
+            <input type="file" accept="image/*" (change)="onAvatarSelect($event)" style="display: none;">
+          </label>
+        </div>
+        <div class="divider">或选择默认头像</div>
+        <div class="default-avatars">
+          <div class="default-avatar" (click)="useDefaultAvatar('👨‍💼')">👨‍💼</div>
+          <div class="default-avatar" (click)="useDefaultAvatar('👩‍💼')">👩‍💼</div>
+          <div class="default-avatar" (click)="useDefaultAvatar('👨‍⚖️')">👨‍⚖️</div>
+          <div class="default-avatar" (click)="useDefaultAvatar('👩‍⚖️')">👩‍⚖️</div>
+          <div class="default-avatar" (click)="useDefaultAvatar('🏛️')">🏛️</div>
+          <div class="default-avatar" (click)="useDefaultAvatar('⚖️')">⚖️</div>
+        </div>
+      </div>
+    </div>
+  </div>
+
   <nav class="bottom-nav">
     <div class="nav-item" routerLink="/government/supervision-overview"><div class="nav-icon">📊</div><div>监管</div></div>
     <div class="nav-item" routerLink="/government/subsidy-management"><div class="nav-icon">💰</div><div>补贴</div></div>

+ 351 - 0
src/app/government/government-center/government-center.scss

@@ -250,4 +250,355 @@
   &:hover { background: var(--warning-color); color: white; transform: translateY(-2px); }
 }
 
+/* 个人信息样式 */
+.profile-section {
+  .profile-card {
+    background: white;
+    border-radius: 12px;
+    padding: 24px;
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  }
+
+  .avatar-section {
+    text-align: center;
+    margin-bottom: 24px;
+    cursor: pointer;
+
+    .avatar-wrapper {
+      position: relative;
+      display: inline-block;
+      width: 100px;
+      height: 100px;
+      margin-bottom: 8px;
+
+      .avatar-img {
+        width: 100%;
+        height: 100%;
+        border-radius: 50%;
+        object-fit: cover;
+        border: 3px solid var(--secondary-color);
+      }
+
+      .avatar-placeholder {
+        width: 100%;
+        height: 100%;
+        border-radius: 50%;
+        background: linear-gradient(135deg, #667eea, #764ba2);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 48px;
+        color: white;
+        border: 3px solid var(--secondary-color);
+      }
+
+      .avatar-edit-icon {
+        position: absolute;
+        bottom: 0;
+        right: 0;
+        width: 32px;
+        height: 32px;
+        background: var(--secondary-color);
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: white;
+        font-size: 14px;
+        border: 3px solid white;
+      }
+    }
+
+    .avatar-tip {
+      font-size: 12px;
+      color: var(--light-text);
+    }
+  }
+
+  .info-list {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+    margin-bottom: 24px;
+
+    .info-item {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 12px;
+      background: #f8f9fa;
+      border-radius: 8px;
+
+      .info-label {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+        font-size: 14px;
+        color: var(--light-text);
+
+        i {
+          width: 20px;
+          text-align: center;
+        }
+      }
+
+      .info-value {
+        font-size: 14px;
+        font-weight: 500;
+        color: var(--dark-text);
+      }
+    }
+  }
+
+  .edit-profile-btn {
+    width: 100%;
+    padding: 14px;
+    background: var(--secondary-color);
+    color: white;
+    border: none;
+    border-radius: 12px;
+    font-size: 16px;
+    font-weight: 500;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: 8px;
+    transition: all 0.3s;
+
+    &:hover {
+      background: #2980b9;
+      transform: translateY(-2px);
+      box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+    }
+  }
+}
+
+/* 弹窗样式 */
+.modal-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1000;
+  opacity: 0;
+  visibility: hidden;
+  transition: all 0.3s ease;
+  backdrop-filter: blur(4px);
+
+  &.show {
+    opacity: 1;
+    visibility: visible;
+
+    .modal-content {
+      transform: translateY(0) scale(1);
+    }
+  }
+
+  .modal-content {
+    background: white;
+    border-radius: 16px;
+    width: 90%;
+    max-width: 500px;
+    max-height: 80vh;
+    overflow-y: auto;
+    transform: translateY(-30px) scale(0.9);
+    transition: transform 0.3s ease;
+    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
+  }
+
+  .modal-header {
+    padding: 20px;
+    border-bottom: 1px solid #e0e0e0;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: linear-gradient(135deg, #f5f7fa, #ffffff);
+    border-radius: 16px 16px 0 0;
+
+    .modal-title {
+      font-size: 18px;
+      font-weight: 600;
+      color: var(--dark-text);
+    }
+
+    .close-btn {
+      background: none;
+      border: none;
+      font-size: 28px;
+      color: var(--light-text);
+      cursor: pointer;
+      line-height: 1;
+      padding: 0;
+      width: 30px;
+      height: 30px;
+      transition: all 0.3s;
+      border-radius: 50%;
+
+      &:hover {
+        color: var(--dark-text);
+        background: rgba(0, 0, 0, 0.05);
+        transform: rotate(90deg);
+      }
+    }
+  }
+
+  .modal-body {
+    padding: 20px;
+
+    .form-group {
+      margin-bottom: 16px;
+
+      .form-label {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+        font-size: 14px;
+        font-weight: 500;
+        color: var(--dark-text);
+        margin-bottom: 8px;
+
+        i {
+          width: 20px;
+          text-align: center;
+          color: var(--secondary-color);
+        }
+      }
+
+      .form-input {
+        width: 100%;
+        padding: 12px;
+        border: 1px solid #e0e0e0;
+        border-radius: 8px;
+        font-size: 14px;
+        transition: all 0.3s;
+
+        &:focus {
+          outline: none;
+          border-color: var(--secondary-color);
+          box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
+        }
+      }
+    }
+
+    .upload-section {
+      text-align: center;
+      margin-bottom: 20px;
+
+      .upload-btn {
+        display: inline-flex;
+        align-items: center;
+        gap: 8px;
+        padding: 14px 24px;
+        background: var(--secondary-color);
+        color: white;
+        border-radius: 12px;
+        font-size: 14px;
+        font-weight: 500;
+        cursor: pointer;
+        transition: all 0.3s;
+
+        &:hover {
+          background: #2980b9;
+          transform: translateY(-2px);
+          box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+        }
+      }
+    }
+
+    .divider {
+      text-align: center;
+      color: var(--light-text);
+      font-size: 12px;
+      margin: 20px 0;
+      position: relative;
+
+      &::before,
+      &::after {
+        content: '';
+        position: absolute;
+        top: 50%;
+        width: 40%;
+        height: 1px;
+        background: #e0e0e0;
+      }
+
+      &::before {
+        left: 0;
+      }
+
+      &::after {
+        right: 0;
+      }
+    }
+
+    .default-avatars {
+      display: grid;
+      grid-template-columns: repeat(3, 1fr);
+      gap: 12px;
+
+      .default-avatar {
+        aspect-ratio: 1;
+        background: #f8f9fa;
+        border-radius: 12px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        font-size: 48px;
+        cursor: pointer;
+        transition: all 0.3s;
+
+        &:hover {
+          background: var(--secondary-color);
+          transform: scale(1.1);
+          box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+        }
+      }
+    }
+  }
+
+  .modal-footer {
+    padding: 16px 20px;
+    border-top: 1px solid #e0e0e0;
+    display: flex;
+    gap: 12px;
+
+    .btn {
+      flex: 1;
+      padding: 12px;
+      border: none;
+      border-radius: 8px;
+      font-size: 14px;
+      font-weight: 600;
+      cursor: pointer;
+      transition: all 0.3s;
+
+      &.btn-cancel {
+        background: #f0f0f0;
+        color: var(--dark-text);
+
+        &:hover {
+          background: #e0e0e0;
+          transform: translateY(-2px);
+        }
+      }
+
+      &.btn-save {
+        background: var(--secondary-color);
+        color: white;
+
+        &:hover {
+          background: #2980b9;
+          transform: translateY(-2px);
+          box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+        }
+      }
+    }
+  }
+}
 

+ 90 - 5
src/app/government/government-center/government-center.ts

@@ -1,15 +1,40 @@
 import { Component } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { RouterModule } from '@angular/router';
+import { RouterModule, Router } from '@angular/router';
+import { FormsModule } from '@angular/forms';
+
+interface GovernmentInfo {
+  name: string;
+  department: string;
+  position: string;
+  phone: string;
+  email: string;
+  region: string;
+  avatar: string;
+}
 
 @Component({
   selector: 'app-government-center',
-  imports: [CommonModule, RouterModule],
+  standalone: true,
+  imports: [CommonModule, RouterModule, FormsModule],
   templateUrl: './government-center.html',
   styleUrl: './government-center.scss'
 })
 export class GovernmentCenter {
-  activeTab: 'region' | 'user' | 'notice' | 'log' | 'settings' = 'region';
+  activeTab: 'region' | 'user' | 'notice' | 'log' | 'settings' | 'profile' = 'profile';
+  showProfileModal = false;
+  showAvatarModal = false;
+  
+  // 政府信息
+  governmentInfo: GovernmentInfo = {
+    name: '政府管理员',
+    department: '环保监管局',
+    position: '局长',
+    phone: '010-12345678',
+    email: 'admin@gov.cn',
+    region: '全市',
+    avatar: ''
+  };
 
   regions = [
     { name: '朝阳区', manager: '张主任', contact: '138****1234', status: 'active' },
@@ -33,7 +58,7 @@ export class GovernmentCenter {
     { user: '李主任', action: '发布政策公告', time: '2023-05-20 09:15' }
   ];
 
-  switchTab(tab: 'region' | 'user' | 'notice' | 'log' | 'settings'): void {
+  switchTab(tab: 'region' | 'user' | 'notice' | 'log' | 'settings' | 'profile'): void {
     this.activeTab = tab;
   }
 
@@ -51,9 +76,69 @@ export class GovernmentCenter {
 
   logout(): void {
     if (confirm('确定要退出登录吗?')) {
+      // 清除用户信息
+      localStorage.removeItem('currentUser');
+      localStorage.removeItem('governmentInfo');
       alert('已退出登录');
+      // 跳转到登录页
+      this.router.navigate(['/auth/login']);
     }
   }
 
-  constructor() {}
+  // 打开个人信息编辑弹窗
+  openProfileModal(): void {
+    this.showProfileModal = true;
+  }
+
+  // 关闭个人信息编辑弹窗
+  closeProfileModal(): void {
+    this.showProfileModal = false;
+  }
+
+  // 保存个人信息
+  saveProfile(): void {
+    // 保存到localStorage
+    localStorage.setItem('governmentInfo', JSON.stringify(this.governmentInfo));
+    alert('信息保存成功!');
+    this.closeProfileModal();
+  }
+
+  // 打开头像上传弹窗
+  openAvatarModal(): void {
+    this.showAvatarModal = true;
+  }
+
+  // 关闭头像上传弹窗
+  closeAvatarModal(): void {
+    this.showAvatarModal = false;
+  }
+
+  // 选择头像
+  onAvatarSelect(event: Event): void {
+    const input = event.target as HTMLInputElement;
+    if (input.files && input.files[0]) {
+      const reader = new FileReader();
+      reader.onload = (e: ProgressEvent<FileReader>) => {
+        this.governmentInfo.avatar = e.target?.result as string;
+        localStorage.setItem('governmentInfo', JSON.stringify(this.governmentInfo));
+        this.closeAvatarModal();
+      };
+      reader.readAsDataURL(input.files[0]);
+    }
+  }
+
+  // 使用默认头像
+  useDefaultAvatar(avatar: string): void {
+    this.governmentInfo.avatar = avatar;
+    localStorage.setItem('governmentInfo', JSON.stringify(this.governmentInfo));
+    this.closeAvatarModal();
+  }
+
+  constructor(private router: Router) {
+    // 从localStorage加载政府信息
+    const savedInfo = localStorage.getItem('governmentInfo');
+    if (savedInfo) {
+      this.governmentInfo = JSON.parse(savedInfo);
+    }
+  }
 }

+ 1 - 0
src/app/government/industry-analysis/industry-analysis.ts

@@ -5,6 +5,7 @@ import { FormsModule } from '@angular/forms';
 
 @Component({
   selector: 'app-industry-analysis',
+  standalone: true,
   imports: [CommonModule, RouterModule, FormsModule],
   templateUrl: './industry-analysis.html',
   styleUrl: './industry-analysis.scss'

+ 1 - 0
src/app/government/subsidy-management/subsidy-management.ts

@@ -24,6 +24,7 @@ interface PaymentRecord {
 
 @Component({
   selector: 'app-subsidy-management',
+  standalone: true,
   imports: [CommonModule, RouterModule, FormsModule],
   templateUrl: './subsidy-management.html',
   styleUrl: './subsidy-management.scss'

+ 1 - 0
src/app/government/supervision-overview/supervision-overview.ts

@@ -22,6 +22,7 @@ interface AreaData {
 
 @Component({
   selector: 'app-supervision-overview',
+  standalone: true,
   imports: [CommonModule, RouterModule, FormsModule],
   templateUrl: './supervision-overview.html',
   styleUrl: './supervision-overview.scss'