Browse Source

feat:finance-demo002

0235711 6 hours ago
parent
commit
704207e613

+ 18 - 13
src/app/pages/finance/project-records/project-records.html

@@ -1,6 +1,11 @@
 <div class="finance-project-records">
   <!-- 顶部标题区 -->
   <header class="page-header">
+    <div class="header-top">
+      <button class="back-to-dashboard-btn" routerLink="/finance/dashboard">
+        <i class="fa fa-arrow-left"></i> 返回工作台
+      </button>
+    </div>
     <div class="header-content">
       <h1>项目财务档案</h1>
       <p class="subtitle">管理所有项目的财务状态和报价信息</p>
@@ -31,7 +36,7 @@
     </div>
     
     <div class="project-items">
-      <div *ngFor="let project of projects()" class="project-item">
+      <div *ngFor="let project of projects() || []" class="project-item">
         <div class="project-info">
           <div class="project-id">{{ project.id }}</div>
           <div class="project-main">
@@ -41,13 +46,13 @@
               <span class="date">{{ formatDate(project.updatedAt) }}</span>
             </div>
             <div class="project-details">
-              <span>{{ getProjectType(project) }}</span>
-              <span>{{ getTechnicalType(project) }}</span>
+              <span>{{ getProjectTypeLabel(project) }}</span>
+              <span>{{ getTechnicalTypeLabel(project) }}</span>
             </div>
           </div>
-          <div *ngIf="getQuoteTypeLabel(project)" class="quote-type-tag {{ getQuoteTypeClass(project) }}">
-            {{ getQuoteTypeLabel(project) }}
-          </div>
+          <div *ngIf="project && getQuoteTypeLabel(project)" class="quote-type-tag {{ getQuoteTypeClass(project) }}">
+              {{ getQuoteTypeLabel(project) }}
+            </div>
         </div>
         
         <div class="project-status">
@@ -115,14 +120,14 @@
             
             <div class="form-group">
               <label>方案类型</label>
-              <input formControlName="方案类型" type="text" readonly>
+              <input formControlName="planType" type="text" readonly>
             </div>
           </div>
           
           <div class="form-row">
             <div class="form-group">
               <label>技术类型</label>
-              <select formControlName="技术类型">
+              <select formControlName="technicalType">
                 <option value="建模">建模</option>
                 <option value="渲染">渲染</option>
                 <option value="后期">后期</option>
@@ -164,17 +169,17 @@
       
       <div class="modal-body">
         <div class="log-header" *ngIf="selectedProject()">
-          <div class="project-name">{{ selectedProject()!.name }}</div>
-          <div class="client-info">客户: {{ selectedProject()!.clientName }}</div>
-          <div class="sales-info">销售: {{ selectedProject()!.salesPerson }}</div>
+          <div class="project-name">{{ selectedProject()?.name }}</div>
+          <div class="client-info">客户: {{ selectedProject()?.clientName }}</div>
+          <div class="sales-info">销售: {{ selectedProject()?.salesPerson }}</div>
         </div>
         
         <div class="log-list" *ngIf="selectedProject()">
-          <div *ngIf="selectedProject()!.communicationLog.length === 0" class="no-logs">
+          <div *ngIf="selectedProject()?.communicationLog && selectedProject()?.communicationLog?.length === 0" class="no-logs">
             暂无沟通记录
           </div>
           
-          <div *ngFor="let log of selectedProject()!.communicationLog" class="log-item">
+          <div *ngFor="let log of selectedProject()?.communicationLog || []" class="log-item">
             <div class="log-content" [class.has-red-line]="log.hasRedLineContent">
               {{ log.content }}
             </div>

+ 30 - 0
src/app/pages/finance/project-records/project-records.scss

@@ -11,6 +11,9 @@
 /* 顶部标题区 */
 .page-header {
   margin-bottom: 24px;
+  .header-top {
+    margin-bottom: 16px;
+  }
   .header-content {
     h1 {
       font-size: 28px;
@@ -25,6 +28,33 @@
   }
 }
 
+.back-to-dashboard-btn {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 16px;
+  background-color: #f5f5f5;
+  color: #007aff;
+  border: 1px solid #d1d1d6;
+  border-radius: 8px;
+  font-size: 14px;
+  font-weight: 500;
+  cursor: pointer;
+  transition: all 0.2s ease;
+  text-decoration: none;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+}
+
+.back-to-dashboard-btn:hover {
+  background-color: #e5e5ea;
+  transform: translateY(-1px);
+}
+
+.back-to-dashboard-btn:active {
+  transform: translateY(0);
+  background-color: #d1d1d6;
+}
+
 /* 搜索和筛选区 */
 .search-filter-section {
   margin-bottom: 24px;

+ 54 - 41
src/app/pages/finance/project-records/project-records.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
 import { CommonModule } from '@angular/common';
+import { RouterModule } from '@angular/router';
 import { signal } from '@angular/core';
 
 // 项目财务状态类型定义
@@ -27,8 +28,8 @@ export interface Project {
   name: string;
   clientName: string;
   salesPerson: string;
-  方案类型?: string;
-  技术类型?: string;
+  planType?: string;
+  technicalType?: string;
   area?: number;
   price: number;
   cost: number;
@@ -48,7 +49,7 @@ export interface HourlyRateConfig {
 
 @Component({
   selector: 'app-project-records',
-  imports: [CommonModule, ReactiveFormsModule],
+  imports: [CommonModule, ReactiveFormsModule, RouterModule],
   templateUrl: './project-records.html',
   styleUrls: ['./project-records.scss']
 })
@@ -87,8 +88,8 @@ export class ProjectRecords implements OnInit {
     // 初始化报价表单
     this.quoteForm = this.fb.group({
       projectId: [''],
-      '方案类型': [''],
-      '技术类型': [''],
+      planType: [''],
+      technicalType: [''],
       area: [0],
       profitRate: [30]
     });
@@ -108,8 +109,8 @@ export class ProjectRecords implements OnInit {
         name: '现代风格住宅室内设计',
         clientName: '星光地产',
         salesPerson: '张三',
-        方案类型: '室内设计',
-        技术类型: '建模/渲染/后期',
+        planType: '室内设计',
+        technicalType: '建模/渲染/后期',
         area: 120,
         price: 85000,
         cost: 55000,
@@ -123,8 +124,8 @@ export class ProjectRecords implements OnInit {
         name: '商业办公空间设计',
         clientName: '未来科技有限公司',
         salesPerson: '李四',
-        方案类型: '办公设计',
-        技术类型: '建模/渲染',
+        planType: '办公设计',
+        technicalType: '建模/渲染',
         area: 350,
         price: 120000,
         cost: 80000,
@@ -145,8 +146,8 @@ export class ProjectRecords implements OnInit {
         name: '餐饮空间改造设计',
         clientName: '悦享餐饮集团',
         salesPerson: '王五',
-        方案类型: '餐饮设计',
-        技术类型: '建模/渲染/后期',
+        planType: '餐饮设计',
+        technicalType: '建模/渲染/后期',
         area: 180,
         price: 95000,
         cost: 65000,
@@ -167,8 +168,8 @@ export class ProjectRecords implements OnInit {
         name: '酒店大堂设计',
         clientName: '环球酒店集团',
         salesPerson: '赵六',
-        方案类型: '酒店设计',
-        技术类型: '建模/渲染/后期',
+        planType: '酒店设计',
+        technicalType: '建模/渲染/后期',
         area: 500,
         price: 250000,
         cost: 160000,
@@ -189,8 +190,8 @@ export class ProjectRecords implements OnInit {
         name: '品牌展厅设计',
         clientName: '时尚家居品牌',
         salesPerson: '张三',
-        方案类型: '展厅设计',
-        技术类型: '建模/渲染',
+        planType: '展厅设计',
+        technicalType: '建模/渲染',
         area: 200,
         price: 110000,
         cost: 70000,
@@ -211,8 +212,8 @@ export class ProjectRecords implements OnInit {
         name: '别墅花园景观设计',
         clientName: '私人业主',
         salesPerson: '李四',
-        方案类型: '景观设计',
-        技术类型: '渲染/后期',
+        planType: '景观设计',
+        technicalType: '渲染/后期',
         area: 300,
         price: 75000,
         cost: 45000,
@@ -233,8 +234,8 @@ export class ProjectRecords implements OnInit {
         name: '零售店空间设计',
         clientName: '潮流服饰品牌',
         salesPerson: '王五',
-        方案类型: '零售设计',
-        技术类型: '建模/渲染/后期',
+        planType: '零售设计',
+        technicalType: '建模/渲染/后期',
         area: 150,
         price: 80000,
         cost: 50000,
@@ -255,13 +256,13 @@ export class ProjectRecords implements OnInit {
     this.projects.set(mockProjects);
   }
 
-  // 打开报价弹窗
+  // 打开报价模态框
   openQuoteModal(project: Project): void {
     this.selectedProject.set(project);
     this.quoteForm.patchValue({
       projectId: project.id,
-      '方案类型': project.方案类型 || '',
-      '技术类型': project.技术类型 || '',
+      planType: project.planType || '',
+      technicalType: project.technicalType || '',
       area: project.area || 0,
       profitRate: 30
     });
@@ -273,28 +274,40 @@ export class ProjectRecords implements OnInit {
     if (!this.selectedProject()) return;
 
     const formValue = this.quoteForm.value;
-    const area = formValue.area || 0;
-    const profitRate = formValue.profitRate || 30;
+    const { area = 0, profitRate = 30, planType, technicalType } = formValue;
     
-    // 简单的报价计算逻辑,实际项目中可能更复杂
-    let cost = area * 300; // 假设每平米成本300元
-    let price = cost * (1 + profitRate / 100);
+    let baseCost = 0;
     
-    // 根据技术类型调整价格
-    if (formValue.技术类型 === '建模/渲染/后期') {
-      price *= 1.3;
-    } else if (formValue.技术类型 === '建模/渲染') {
-      price *= 1.1;
+    // 基于方案类型和技术类型计算基础成本
+    if (planType === '室内设计') {
+      baseCost = area * 300;
+    } else if (planType === '办公设计') {
+      baseCost = area * 250;
+    } else if (planType === '餐饮设计') {
+      baseCost = area * 350;
+    } else if (planType === '酒店设计') {
+      baseCost = area * 400;
+    } else if (planType === '展厅设计') {
+      baseCost = area * 500;
     }
+    
+    // 基于技术复杂度调整
+    if (technicalType?.includes('后期')) {
+      baseCost *= 1.2;
+    }
+    
+    // 计算带利润率的报价
+    const price = Math.round(baseCost * (1 + profitRate / 100));
 
     // 更新项目数据
     const updatedProjects = this.projects().map(project => {
       if (project.id === this.selectedProject()?.id) {
         return {
           ...project,
-          技术类型: formValue.技术类型,
+          planType: planType,
+          technicalType: technicalType,
           area: area,
-          cost: cost,
+          cost: baseCost,
           price: price,
           profitRate: profitRate,
           financialStatus: 'quoted' as FinancialStatus,
@@ -419,13 +432,13 @@ export class ProjectRecords implements OnInit {
     }).format(amount);
   }
 
-  // 获取项目类型
-  getProjectType(project: Project): string {
-    return project.方案类型 || '未定义';
+  // 获取项目类型标签
+  getProjectTypeLabel(project: Project): string {
+    return project.planType || '未设置';
   }
-
-  // 获取技术类型
-  getTechnicalType(project: Project): string {
-    return project.技术类型 || '未定义';
+  
+  // 获取技术类型标签
+  getTechnicalTypeLabel(project: Project): string {
+    return project.technicalType || '未设置';
   }
 }

+ 52 - 41
src/app/pages/finance/reconciliation/reconciliation.html

@@ -1,12 +1,15 @@
 <div class="reconciliation-container">
   <!-- 页面标题和操作按钮 -->
-  <div class="page-header">
-    <h2>对账管理</h2>
-    <div class="header-actions">
-      <button class="btn btn-primary" (click)="startReconciliation()">
-        开始新对账
-      </button>
+  <div class="page-header" style="display: flex !important; flex-direction: row !important; align-items: center !important;">
+    <div class="header-top" style="width: auto !important; margin-right: 20px;">
+      <a class="back-to-dashboard-btn" routerLink="/finance/dashboard">
+        <i class="fa fa-arrow-left"></i> 返回工作台
+      </a>
     </div>
+    <h2 style="margin-right: 20px; margin-bottom: 0 !important;">对账管理</h2>
+    <button class="btn btn-primary" (click)="startReconciliation()">
+      <i class="fa fa-plus-circle"></i> 开始新对账
+    </button>
   </div>
 
   <!-- 过滤和搜索区域 -->
@@ -25,9 +28,9 @@
     <div class="filter-group">
       <label>对账期间:</label>
       <div class="date-range">
-        <input type="date" [ngModel]="dateRangeFilter().start | date:'yyyy-MM-dd'" (ngModelChange)="updateDateRangeStart($event)" class="form-control date-input">
+        <input type="date" [ngModel]="dateRangeFilter().start ? (dateRangeFilter().start | date:'yyyy-MM-dd') : ''" (ngModelChange)="updateDateRangeStart($event)" class="form-control date-input">
         <span>至</span>
-        <input type="date" [ngModel]="dateRangeFilter().end | date:'yyyy-MM-dd'" (ngModelChange)="updateDateRangeEnd($event)" class="form-control date-input">
+        <input type="date" [ngModel]="dateRangeFilter().end ? (dateRangeFilter().end | date:'yyyy-MM-dd') : ''" (ngModelChange)="updateDateRangeEnd($event)" class="form-control date-input">
       </div>
     </div>
   </div>
@@ -54,7 +57,7 @@
           </tr>
         </thead>
         <tbody>
-          <tr *ngFor="let record of reconciliationRecords()" (click)="viewReconciliationDetail(record)">
+            <tr *ngFor="let record of reconciliationRecords() || []" (click)="viewReconciliationDetail(record)">
             <td>{{ record.id }}</td>
             <td>{{ formatDate(record.date) }}</td>
             <td>{{ formatDate(record.periodStart) }} - {{ formatDate(record.periodEnd) }}</td>
@@ -77,7 +80,7 @@
   <!-- 未对账交易表格 -->
   <div class="section-card">
     <div class="section-header">
-      <h3>未对账交易 ({{ unreconciledTransactions().length }} 笔)</h3>
+      <h3>未对账交易 ({{ unreconciledTransactions().length || 0 }} 笔)</h3>
     </div>
     
     <div class="table-responsive">
@@ -95,7 +98,7 @@
           </tr>
         </thead>
         <tbody>
-          <tr *ngFor="let transaction of unreconciledTransactions()">
+            <tr *ngFor="let transaction of unreconciledTransactions() || []">
             <td>{{ transaction.id }}</td>
             <td>{{ formatDate(transaction.date) }}</td>
             <td><span class="transaction-type {{ getTransactionTypeClass(transaction.type) }}">{{ getTransactionTypeText(transaction.type) }}</span></td>
@@ -118,7 +121,7 @@
   <div class="modal-overlay" *ngIf="showDetailModal()" (click)="showDetailModal.set(false)">
     <div class="modal-content" (click)="$event.stopPropagation()">
       <div class="modal-header">
-        <h3>对账详情 - {{ selectedRecord()?.id }}</h3>
+        <h3>对账详情 - {{ selectedRecord()?.id || '' }}</h3>
         <button class="modal-close" (click)="showDetailModal.set(false)">&times;</button>
       </div>
       
@@ -126,35 +129,35 @@
         <div class="detail-grid">
           <div class="detail-item">
             <label>对账日期:</label>
-            <span>{{ formatDate(selectedRecord()!.date) }}</span>
+            <span>{{ selectedRecord()?.date ? formatDate(selectedRecord()?.date) : '-' }}</span>
           </div>
           <div class="detail-item">
             <label>对账期间:</label>
-            <span>{{ formatDate(selectedRecord()!.periodStart) }} - {{ formatDate(selectedRecord()!.periodEnd) }}</span>
+            <span>{{ selectedRecord()?.periodStart ? formatDate(selectedRecord()?.periodStart) : '-' }} - {{ selectedRecord()?.periodEnd ? formatDate(selectedRecord()?.periodEnd) : '-' }}</span>
           </div>
           <div class="detail-item">
             <label>状态:</label>
-            <span class="status-badge {{ getStatusClass(selectedRecord()!.status) }}">{{ getStatusText(selectedRecord()!.status) }}</span>
+            <span class="status-badge {{ getStatusClass(selectedRecord()?.status || 'pending') }}">{{ getStatusText(selectedRecord()?.status || 'pending') }}</span>
           </div>
           <div class="detail-item">
             <label>总金额:</label>
-            <span>{{ formatAmount(selectedRecord()!.totalAmount) }}</span>
+            <span>{{ formatAmount(selectedRecord()?.totalAmount || 0) }}</span>
           </div>
           <div class="detail-item">
             <label>已对账金额:</label>
-            <span>{{ formatAmount(selectedRecord()!.reconciledAmount) }}</span>
+            <span>{{ formatAmount(selectedRecord()?.reconciledAmount || 0) }}</span>
           </div>
           <div class="detail-item">
             <label>差异金额:</label>
-            <span>{{ formatAmount(selectedRecord()!.discrepancyAmount) }}</span>
+            <span>{{ formatAmount(selectedRecord()?.discrepancyAmount || 0) }}</span>
           </div>
           <div class="detail-item">
             <label>对账人:</label>
-            <span>{{ selectedRecord()!.reconciledBy || '-' }}</span>
+            <span>{{ selectedRecord()?.reconciledBy || '-' }}</span>
           </div>
           <div class="detail-item full-width">
             <label>备注:</label>
-            <span>{{ selectedRecord()!.notes || '-' }}</span>
+            <span>{{ selectedRecord()?.notes || '-' }}</span>
           </div>
         </div>
         
@@ -173,17 +176,21 @@
                 </tr>
               </thead>
               <tbody>
-                <tr *ngFor="let transaction of selectedRecord()!.transactions">
-                  <td>{{ transaction.id }}</td>
-                  <td>{{ formatDate(transaction.date) }}</td>
-                  <td><span class="transaction-type {{ getTransactionTypeClass(transaction.type) }}">{{ getTransactionTypeText(transaction.type) }}</span></td>
-                  <td>{{ formatAmount(transaction.amount) }}</td>
-                  <td>{{ transaction.projectName }}</td>
-                  <td>{{ transaction.description }}</td>
-                </tr>
-                <tr *ngIf="selectedRecord()!.transactions.length === 0">
-                  <td colspan="6" class="no-data">暂无交易记录</td>
-                </tr>
+                <ng-container *ngIf="selectedRecord()?.transactions && selectedRecord()!.transactions!.length > 0; else noTransactions">
+                  <tr *ngFor="let transaction of (selectedRecord()?.transactions || [])">
+                    <td>{{ transaction.id }}</td>
+                    <td>{{ formatDate(transaction.date) }}</td>
+                    <td><span class="transaction-type {{ getTransactionTypeClass(transaction.type) }}">{{ getTransactionTypeText(transaction.type) }}</span></td>
+                    <td>{{ formatAmount(transaction.amount) }}</td>
+                    <td>{{ transaction.projectName }}</td>
+                    <td>{{ transaction.description }}</td>
+                  </tr>
+                </ng-container>
+                <ng-template #noTransactions>
+                  <tr>
+                    <td colspan="6" class="no-data">暂无交易记录</td>
+                  </tr>
+                </ng-template>
               </tbody>
             </table>
           </div>
@@ -236,16 +243,20 @@
                 </tr>
               </thead>
               <tbody>
-                <tr *ngFor="let transaction of getFilteredUnreconciledTransactions()">
-                  <td>{{ transaction.id }}</td>
-                  <td>{{ formatDate(transaction.date) }}</td>
-                  <td><span class="transaction-type {{ getTransactionTypeClass(transaction.type) }}">{{ getTransactionTypeText(transaction.type) }}</span></td>
-                  <td>{{ formatAmount(transaction.amount) }}</td>
-                  <td>{{ transaction.projectName }}</td>
-                </tr>
-                <tr *ngIf="!hasFilteredUnreconciledTransactions()">
-                  <td colspan="5" class="no-data">暂无符合条件的交易</td>
-                </tr>
+                <ng-container *ngIf="getFilteredUnreconciledTransactions().length > 0; else noFilteredTransactions">
+                  <tr *ngFor="let transaction of (getFilteredUnreconciledTransactions() || [])">
+                    <td>{{ transaction.id }}</td>
+                    <td>{{ formatDate(transaction.date) }}</td>
+                    <td><span class="transaction-type {{ getTransactionTypeClass(transaction.type) }}">{{ getTransactionTypeText(transaction.type) }}</span></td>
+                    <td>{{ formatAmount(transaction.amount) }}</td>
+                    <td>{{ transaction.projectName }}</td>
+                  </tr>
+                </ng-container>
+                <ng-template #noFilteredTransactions>
+                  <tr>
+                    <td colspan="5" class="no-data">暂无符合条件的交易</td>
+                  </tr>
+                </ng-template>
               </tbody>
             </table>
           </div>

+ 635 - 324
src/app/pages/finance/reconciliation/reconciliation.scss

@@ -1,440 +1,642 @@
 // 对账管理页面样式
 
+// 定义主题颜色
+$primary-color: #007bff;
+$primary-hover: #0056b3;
+$secondary-color: #6c757d;
+$success-color: #28a745;
+$warning-color: #ffc107;
+$danger-color: #dc3545;
+$info-color: #17a2b8;
+
+$background-light: #f8fafc;
+$background-white: #ffffff;
+$border-color: #e2e8f0;
+$text-primary: #1e293b;
+$text-secondary: #64748b;
+$text-muted: #94a3b8;
+
 .reconciliation-container {
-  padding: 20px;
+  padding: 24px;
   max-width: 1400px;
   margin: 0 auto;
+  background-color: $background-light;
 
   // 页面标题和操作按钮
-  .page-header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    margin-bottom: 24px;
-
-    h2 {
-      font-size: 24px;
-      font-weight: 600;
-      color: #2c3e50;
-      margin: 0;
-    }
+    .page-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 28px;
+      padding-bottom: 20px;
+      border-bottom: 2px solid $border-color;
+      background-color: $background-white;
+      padding: 24px;
+      border-radius: 12px;
+      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
+
+      .header-top {
+        margin-bottom: 0;
+      }
 
-    .header-actions {
-      button {
-        padding: 8px 20px;
+      h2 {
+        font-size: 28px;
+        font-weight: 700;
+        color: $text-primary;
+        margin: 0;
+        letter-spacing: -0.5px;
+      }
+
+      .header-actions {
+        button {
+          padding: 10px 24px;
+          font-size: 14px;
+          font-weight: 500;
+          border-radius: 8px;
+          transition: all 0.3s ease;
+          box-shadow: 0 2px 4px rgba(0, 123, 255, 0.1);
+          &:hover {
+            transform: translateY(-1px);
+            box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2);
+          }
+        }
+      }
+
+      .back-to-dashboard-btn {
+        display: inline-flex;
+        align-items: center;
+        gap: 8px;
+        padding: 10px 16px;
+        background-color: $background-white;
+        color: $primary-color;
+        border: 1px solid $border-color;
+        border-radius: 8px;
         font-size: 14px;
-        border-radius: 4px;
+        font-weight: 500;
+        cursor: pointer;
         transition: all 0.3s ease;
+        text-decoration: none;
+        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+
         &:hover {
+          background-color: $primary-color;
+          border-color: $primary-color;
+          color: white;
           transform: translateY(-1px);
-          box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 4px 12px rgba(0, 123, 255, 0.2);
+        }
+
+        &:active {
+          transform: translateY(0);
         }
       }
     }
-  }
 
   // 过滤区域
-  .filter-section {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 20px;
-    margin-bottom: 24px;
-    padding: 16px;
-    background-color: #f8f9fa;
-    border-radius: 8px;
-
-    .filter-group {
+    .filter-section {
       display: flex;
-      flex-direction: column;
-      gap: 8px;
-      min-width: 200px;
+      flex-wrap: wrap;
+      gap: 20px;
+      margin-bottom: 28px;
+      padding: 24px;
+      background-color: $background-white;
+      border-radius: 12px;
+      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
 
-      label {
-        font-size: 14px;
-        font-weight: 500;
-        color: #495057;
-      }
-
-      select,
-      .form-control {
-        padding: 8px 12px;
-        border: 1px solid #ced4da;
-        border-radius: 4px;
-        font-size: 14px;
-        transition: border-color 0.3s ease;
-
-        &:focus {
-          outline: none;
-          border-color: #007bff;
-          box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
-        }
-      }
-
-      .date-range {
+      .filter-group {
         display: flex;
-        align-items: center;
-        gap: 12px;
+        flex-direction: column;
+        gap: 8px;
+        min-width: 220px;
 
-        .date-input {
-          flex: 1;
+        label {
+          font-size: 13px;
+          font-weight: 600;
+          color: $text-secondary;
+          text-transform: uppercase;
+          letter-spacing: 0.5px;
         }
 
-        span {
+        select,
+        .form-control {
+          padding: 12px 16px;
+          border: 1px solid $border-color;
+          border-radius: 8px;
           font-size: 14px;
-          color: #6c757d;
+          transition: all 0.3s ease;
+          background-color: $background-white;
+
+          &:focus {
+            outline: none;
+            border-color: $primary-color;
+            box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
+          }
         }
-      }
-    }
-  }
 
-  // 卡片样式
-  .section-card {
-    background-color: #ffffff;
-    border-radius: 8px;
-    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-    margin-bottom: 24px;
-    overflow: hidden;
+        .date-range {
+          display: flex;
+          align-items: center;
+          gap: 12px;
 
-    .section-header {
-      padding: 16px 20px;
-      border-bottom: 1px solid #e9ecef;
+          .date-input {
+            flex: 1;
+          }
 
-      h3 {
-        font-size: 18px;
-        font-weight: 600;
-        color: #2c3e50;
-        margin: 0;
+          span {
+            font-size: 14px;
+            color: $text-muted;
+            font-weight: 500;
+          }
+        }
       }
     }
-  }
-
-  // 表格样式
-  .table-responsive {
-    overflow-x: auto;
 
-    .table {
-      width: 100%;
-      border-collapse: collapse;
+    // 卡片样式
+    .section-card {
+      background-color: $background-white;
+      border-radius: 12px;
+      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
+      margin-bottom: 28px;
+      overflow: hidden;
+      transition: transform 0.3s ease, box-shadow 0.3s ease;
+
+      &:hover {
+        transform: translateY(-2px);
+        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
+      }
 
-      thead {
-        background-color: #f8f9fa;
-        border-bottom: 2px solid #dee2e6;
+      .section-header {
+        padding: 20px 24px;
+        border-bottom: 1px solid $border-color;
+        background-color: #fafbfc;
 
-        th {
-          padding: 12px 16px;
-          text-align: left;
-          font-size: 14px;
+        h3 {
+          font-size: 20px;
           font-weight: 600;
-          color: #495057;
-          white-space: nowrap;
+          color: $text-primary;
+          margin: 0;
+          display: flex;
+          align-items: center;
+          gap: 8px;
         }
       }
+    }
 
-      tbody {
-        tr {
-          border-bottom: 1px solid #e9ecef;
-          transition: background-color 0.2s ease;
+  // 表格样式
+    .table-responsive {
+      overflow-x: auto;
+      border-radius: 8px;
+      margin: 0;
+      background-color: $background-white;
 
-          &:hover {
-            background-color: #f8f9fa;
+      .table {
+        width: 100%;
+        border-collapse: collapse;
+        border-spacing: 0;
+        margin-bottom: 0;
+
+        thead {
+          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+
+          th {
+            padding: 16px;
+            text-align: left;
+            font-size: 13px;
+            font-weight: 600;
+            color: white;
+            white-space: nowrap;
+            letter-spacing: 0.5px;
+            text-transform: uppercase;
+            border-bottom: none;
           }
+        }
 
-          td {
-            padding: 12px 16px;
-            font-size: 14px;
-            color: #212529;
-            vertical-align: middle;
+        tbody {
+          tr {
+            border-bottom: 1px solid $border-color;
+            transition: all 0.3s ease;
+            position: relative;
+            overflow: hidden;
 
-            .btn {
-              padding: 4px 12px;
-              font-size: 12px;
-              border-radius: 4px;
-              transition: all 0.2s ease;
+            &:hover {
+              background-color: #f8fafc;
+              transform: translateX(2px);
+            }
 
-              &:hover {
-                transform: translateY(-1px);
-              }
+            &:last-child {
+              border-bottom: none;
             }
 
-            .btn-view {
-              background-color: #6c757d;
-              color: white;
-              border: none;
+            td {
+              padding: 16px;
+              font-size: 14px;
+              color: $text-primary;
+              vertical-align: middle;
+              font-weight: 500;
+              transition: all 0.3s ease;
+
+              .btn {
+                padding: 6px 16px;
+                font-size: 13px;
+                border-radius: 6px;
+                transition: all 0.3s ease;
+                font-weight: 500;
+
+                &:hover {
+                  transform: translateY(-1px);
+                  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+                }
+              }
+
+              .btn-view {
+                background-color: $info-color;
+                color: white;
+                border: none;
 
-              &:hover {
-                background-color: #5a6268;
+                &:hover {
+                  background-color: #138496;
+                }
               }
             }
           }
-        }
 
-        .no-data {
-          text-align: center;
-          padding: 40px 16px !important;
-          color: #6c757d;
-          font-style: italic;
+          .no-data {
+            text-align: center;
+            padding: 60px 16px !important;
+            color: $text-muted;
+            font-style: normal;
+            font-size: 15px;
+            font-weight: 500;
+          }
         }
       }
-    }
 
-    // 小表格样式
-    .table-small {
-      thead th,
-      tbody td {
-        padding: 8px 12px;
-        font-size: 12px;
+      // 小表格样式
+      .table-small {
+        thead th,
+        tbody td {
+          padding: 12px;
+          font-size: 13px;
+        }
+
+        thead {
+          background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+        }
       }
     }
-  }
 
   // 状态标签样式
-  .status-badge {
-    padding: 4px 8px;
-    border-radius: 12px;
-    font-size: 12px;
-    font-weight: 500;
-    text-align: center;
-    min-width: 60px;
-
-    &.status-pending {
-      background-color: #fff3cd;
-      color: #856404;
-    }
+    .status-badge {
+      padding: 6px 12px;
+      border-radius: 50px;
+      font-size: 12px;
+      font-weight: 600;
+      text-align: center;
+      min-width: 80px;
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+      transition: all 0.3s ease;
+      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 
-    &.status-partial {
-      background-color: #e3f2fd;
-      color: #0d47a1;
-    }
+      &:hover {
+        transform: translateY(-1px);
+        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+      }
 
-    &.status-completed {
-      background-color: #d4edda;
-      color: #155724;
-    }
+      &.status-pending {
+        background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
+        color: #c7794c;
+      }
 
-    &.status-discrepancy {
-      background-color: #f8d7da;
-      color: #721c24;
-    }
-  }
-
-  // 交易类型标签样式
-  .transaction-type {
-    padding: 4px 8px;
-    border-radius: 12px;
-    font-size: 12px;
-    font-weight: 500;
-    text-align: center;
-
-    &.transaction-payment {
-      background-color: #d4edda;
-      color: #155724;
-    }
+      &.status-partial {
+        background: linear-gradient(135deg, #e0c3fc 0%, #8ec5fc 100%);
+        color: #5e4b8b;
+      }
+
+      &.status-completed {
+        background: linear-gradient(135deg, #c1fcd3 0%, #02b875 100%);
+        color: white;
+      }
 
-    &.transaction-expense {
-      background-color: #f8d7da;
-      color: #721c24;
+      &.status-discrepancy {
+        background: linear-gradient(135deg, #ffc6ff 0%, #b967ff 100%);
+        color: white;
+      }
     }
 
-    &.transaction-refund {
-      background-color: #fff3cd;
-      color: #856404;
+    // 交易类型标签样式
+    .transaction-type {
+      padding: 6px 12px;
+      border-radius: 50px;
+      font-size: 12px;
+      font-weight: 600;
+      text-align: center;
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+      transition: all 0.3s ease;
+      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+      &:hover {
+        transform: translateY(-1px);
+        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+      }
+
+      &.transaction-payment {
+        background: linear-gradient(135deg, #c1fcd3 0%, #02b875 100%);
+        color: white;
+      }
+
+      &.transaction-expense {
+        background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
+        color: #c74a50;
+      }
+
+      &.transaction-refund {
+        background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
+        color: #c7794c;
+      }
     }
-  }
 
   // 按钮样式
-  .btn {
-    padding: 8px 16px;
-    border: none;
-    border-radius: 4px;
-    font-size: 14px;
-    cursor: pointer;
-    transition: all 0.3s ease;
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
-
-    &:disabled {
-      opacity: 0.6;
-      cursor: not-allowed;
-      transform: none !important;
-    }
+    .btn {
+      padding: 10px 20px;
+      border: none;
+      border-radius: 8px;
+      font-size: 14px;
+      font-weight: 500;
+      cursor: pointer;
+      transition: all 0.3s ease;
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      gap: 8px;
+      text-transform: uppercase;
+      letter-spacing: 0.5px;
+      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+      &:disabled {
+        opacity: 0.6;
+        cursor: not-allowed;
+        transform: none !important;
+        box-shadow: none;
+      }
 
-    &.btn-primary {
-      background-color: #007bff;
-      color: white;
+      &.btn-primary {
+        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+        color: white;
 
-      &:hover:not(:disabled) {
-        background-color: #0056b3;
-        transform: translateY(-1px);
+        &:hover:not(:disabled) {
+          transform: translateY(-2px);
+          box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
+        }
       }
-    }
 
-    &.btn-secondary {
-      background-color: #6c757d;
-      color: white;
+      &.btn-secondary {
+        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+        color: $text-primary;
+        border: 1px solid $border-color;
 
-      &:hover:not(:disabled) {
-        background-color: #5a6268;
-        transform: translateY(-1px);
+        &:hover:not(:disabled) {
+          transform: translateY(-2px);
+          box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
+          background: linear-gradient(135deg, #e6e9f0 0%, #d1d8e0 100%);
+        }
       }
-    }
 
-    &.btn-sm {
-      padding: 4px 12px;
-      font-size: 12px;
+      &.btn-sm {
+        padding: 6px 16px;
+        font-size: 13px;
+        text-transform: none;
+        letter-spacing: normal;
+      }
+
+      // 成功状态按钮
+      &.btn-success {
+        background: linear-gradient(135deg, #c1fcd3 0%, #02b875 100%);
+        color: white;
+
+        &:hover:not(:disabled) {
+          transform: translateY(-2px);
+          box-shadow: 0 6px 16px rgba(2, 184, 117, 0.4);
+        }
+      }
+
+      // 危险状态按钮
+      &.btn-danger {
+        background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
+        color: #c74a50;
+
+        &:hover:not(:disabled) {
+          transform: translateY(-2px);
+          box-shadow: 0 6px 16px rgba(255, 154, 158, 0.4);
+        }
+      }
     }
-  }
 
   // 模态框样式
-  .modal-overlay {
-    position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background-color: rgba(0, 0, 0, 0.5);
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    z-index: 1000;
-  }
-
-  .modal-content {
-    background-color: white;
-    border-radius: 8px;
-    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
-    width: 90%;
-    max-width: 800px;
-    max-height: 90vh;
-    display: flex;
-    flex-direction: column;
-    overflow: hidden;
+    .modal-overlay {
+      position: fixed;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      background-color: rgba(0, 0, 0, 0.6);
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      z-index: 1000;
+      backdrop-filter: blur(4px);
+      animation: fadeIn 0.3s ease;
+    }
+
+    @keyframes fadeIn {
+      from { opacity: 0; }
+      to { opacity: 1; }
+    }
+
+    .modal-content {
+      background-color: $background-white;
+      border-radius: 16px;
+      box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
+      width: 90%;
+      max-width: 800px;
+      max-height: 90vh;
+      display: flex;
+      flex-direction: column;
+      overflow: hidden;
+      animation: slideIn 0.3s ease;
+      border: 1px solid $border-color;
+    }
+
+    @keyframes slideIn {
+      from { 
+        opacity: 0;
+        transform: translateY(-20px);
+      }
+      to { 
+        opacity: 1;
+        transform: translateY(0);
+      }
+    }
 
     .modal-header {
       display: flex;
       justify-content: space-between;
       align-items: center;
-      padding: 16px 20px;
-      border-bottom: 1px solid #e9ecef;
+      padding: 24px 32px;
+      border-bottom: 1px solid $border-color;
+      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+      color: white;
 
       h3 {
-        font-size: 18px;
+        font-size: 22px;
         font-weight: 600;
-        color: #2c3e50;
         margin: 0;
+        display: flex;
+        align-items: center;
+        gap: 10px;
       }
 
       .modal-close {
-        background: none;
+        background: rgba(255, 255, 255, 0.2);
         border: none;
         font-size: 24px;
         cursor: pointer;
-        color: #6c757d;
+        color: white;
         padding: 0;
-        width: 32px;
-        height: 32px;
+        width: 40px;
+        height: 40px;
         display: flex;
         align-items: center;
         justify-content: center;
-        border-radius: 4px;
+        border-radius: 50%;
+        transition: all 0.3s ease;
 
         &:hover {
-          background-color: #f8f9fa;
-          color: #212529;
+          background: rgba(255, 255, 255, 0.3);
+          transform: rotate(90deg);
         }
       }
     }
 
     .modal-body {
-      padding: 20px;
+      padding: 32px;
       overflow-y: auto;
       flex: 1;
 
       // 详情网格样式
       .detail-grid {
         display: grid;
-        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
-        gap: 16px;
-        margin-bottom: 24px;
+        grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+        gap: 20px;
+        margin-bottom: 32px;
 
         .detail-item {
           display: flex;
           flex-direction: column;
-          gap: 4px;
+          gap: 8px;
+          padding: 16px;
+          background-color: #f8fafc;
+          border-radius: 12px;
+          border: 1px solid $border-color;
+          transition: all 0.3s ease;
+
+          &:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
+          }
 
           &.full-width {
             grid-column: 1 / -1;
           }
 
           label {
-            font-size: 14px;
-            font-weight: 500;
-            color: #6c757d;
+            font-size: 13px;
+            font-weight: 600;
+            color: $text-secondary;
+            text-transform: uppercase;
+            letter-spacing: 0.5px;
           }
 
           span {
-            font-size: 14px;
-            color: #212529;
+            font-size: 16px;
+            font-weight: 500;
+            color: $text-primary;
           }
         }
       }
 
       // 交易记录区域
       .transactions-section {
-        margin-top: 24px;
+        margin-top: 32px;
 
         h4 {
-          font-size: 16px;
+          font-size: 18px;
           font-weight: 600;
-          color: #2c3e50;
-          margin-bottom: 16px;
+          color: $text-primary;
+          margin-bottom: 20px;
+          display: flex;
+          align-items: center;
+          gap: 8px;
         }
       }
 
       // 表单样式
       .form-group {
-        margin-bottom: 16px;
+        margin-bottom: 24px;
 
         label {
           display: block;
           font-size: 14px;
-          font-weight: 500;
-          color: #495057;
-          margin-bottom: 6px;
+          font-weight: 600;
+          color: $text-secondary;
+          margin-bottom: 8px;
+          text-transform: uppercase;
+          letter-spacing: 0.5px;
         }
 
         .form-control {
           width: 100%;
-          padding: 8px 12px;
-          border: 1px solid #ced4da;
-          border-radius: 4px;
+          padding: 12px 16px;
+          border: 1px solid $border-color;
+          border-radius: 8px;
           font-size: 14px;
-          transition: border-color 0.3s ease;
+          transition: all 0.3s ease;
+          background-color: $background-white;
 
           &:focus {
             outline: none;
-            border-color: #007bff;
-            box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
+            border-color: $primary-color;
+            box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
           }
         }
 
         textarea {
           resize: vertical;
-          min-height: 80px;
+          min-height: 100px;
         }
       }
 
       // 对账预览
       .reconciliation-preview {
-        margin-top: 24px;
+        margin-top: 32px;
         padding-top: 24px;
-        border-top: 1px solid #e9ecef;
+        border-top: 1px solid $border-color;
 
         h4 {
-          font-size: 16px;
+          font-size: 18px;
           font-weight: 600;
-          color: #2c3e50;
-          margin-bottom: 16px;
+          color: $text-primary;
+          margin-bottom: 20px;
+          display: flex;
+          align-items: center;
+          gap: 8px;
         }
       }
     }
@@ -442,83 +644,192 @@
     .modal-footer {
       display: flex;
       justify-content: flex-end;
-      gap: 12px;
-      padding: 16px 20px;
-      border-top: 1px solid #e9ecef;
-      background-color: #f8f9fa;
+      gap: 16px;
+      padding: 24px 32px;
+      border-top: 1px solid $border-color;
+      background-color: #f8fafc;
     }
 
     // 对账模态框特定样式
-    &.reconcile-modal {
+    .reconcile-modal {
       max-width: 900px;
     }
-  }
 
   // 响应式设计
-  @media (max-width: 768px) {
-    padding: 12px;
+    @media (max-width: 768px) {
+      padding: 16px;
 
-    .page-header {
-      flex-direction: column;
-      gap: 16px;
-      align-items: stretch;
+      .page-header {
+        flex-direction: column;
+        gap: 16px;
+        align-items: stretch;
+        padding: 16px;
 
-      h2 {
-        font-size: 20px;
-      }
+        h2 {
+          font-size: 24px;
+          text-align: center;
+        }
 
-      .header-actions {
-        text-align: center;
+        .header-actions {
+          text-align: center;
+          order: 3;
+        }
+
+        .back-to-dashboard-btn {
+          justify-content: center;
+          order: 1;
+        }
       }
-    }
 
-    .filter-section {
-      flex-direction: column;
+      .filter-section {
+        flex-direction: column;
+        padding: 16px;
 
-      .filter-group {
-        min-width: auto;
+        .filter-group {
+          min-width: auto;
+          width: 100%;
+        }
       }
-    }
 
-    .modal-content {
-      width: 95%;
-      margin: 10px;
+      .section-card {
+        margin-bottom: 20px;
 
-      .modal-header {
-        padding: 12px 16px;
+        .section-header {
+          padding: 16px;
 
-        h3 {
-          font-size: 16px;
+          h3 {
+            font-size: 18px;
+          }
         }
       }
 
-      .modal-body {
-        padding: 16px;
+      .table-responsive {
+        .table {
+          thead {
+            display: none;
+          }
+
+          tbody tr {
+            display: block;
+            margin-bottom: 16px;
+            border-radius: 8px;
+            border: 1px solid $border-color;
+            overflow: hidden;
+          }
+
+          tbody td {
+            display: flex;
+            justify-content: space-between;
+            padding: 12px 16px;
+            border-bottom: 1px solid $border-color;
+            text-align: right;
+
+            &:before {
+              content: attr(data-label);
+              font-weight: 600;
+              color: $text-secondary;
+              text-align: left;
+            }
+
+            &:last-child {
+              border-bottom: none;
+            }
+
+            .btn {
+              padding: 4px 12px;
+              font-size: 12px;
+              margin-left: auto;
+            }
 
-        .detail-grid {
-          grid-template-columns: 1fr;
+            .status-badge,
+            .transaction-type {
+              margin-left: auto;
+            }
+          }
         }
       }
 
-      .modal-footer {
-        padding: 12px 16px;
-        flex-direction: column;
+      .modal-content {
+        width: 95%;
+        margin: 10px;
+        border-radius: 12px;
+
+        .modal-header {
+          padding: 16px 20px;
+
+          h3 {
+            font-size: 18px;
+          }
+        }
+
+        .modal-body {
+          padding: 16px;
+
+          .detail-grid {
+            grid-template-columns: 1fr;
+            gap: 12px;
+
+            .detail-item {
+              padding: 12px;
+            }
+          }
+
+          .form-group {
+            margin-bottom: 16px;
+          }
+
+          .transactions-section,
+          .reconciliation-preview {
+            margin-top: 20px;
+
+            h4 {
+              font-size: 16px;
+            }
+          }
+        }
+
+        .modal-footer {
+          padding: 16px 20px;
+          flex-direction: column;
+        }
       }
     }
 
-    .table-responsive {
-      .table {
-        thead th,
-        tbody td {
-          padding: 8px 12px;
-          font-size: 12px;
+    // 超小屏幕适配
+    @media (max-width: 480px) {
+      .page-header {
+        padding: 12px;
+      }
+
+      .filter-section {
+        padding: 12px;
+      }
+
+      .table-responsive {
+        .table {
+          tbody td {
+            padding: 8px 12px;
+            font-size: 13px;
+          }
+        }
+      }
+
+      .modal-content {
+        .modal-header {
+          padding: 12px 16px;
+
+          h3 {
+            font-size: 16px;
+          }
+        }
+
+        .modal-body {
+          padding: 12px;
         }
 
-        .btn {
-          padding: 2px 8px;
-          font-size: 10px;
+        .modal-footer {
+          padding: 12px 16px;
         }
       }
     }
-  }
 }

+ 3 - 3
src/app/pages/finance/reconciliation/reconciliation.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormBuilder, FormGroup, ReactiveFormsModule, FormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
 import { signal } from '@angular/core';
 
 // 对账状态类型定义
@@ -49,7 +50,7 @@ export interface ReconciliationRecord {
 
 @Component({
   selector: 'app-reconciliation',
-  imports: [CommonModule, ReactiveFormsModule, FormsModule],
+  imports: [CommonModule, ReactiveFormsModule, FormsModule, RouterModule],
   templateUrl: './reconciliation.html',
   styleUrls: ['./reconciliation.scss']
 })
@@ -316,7 +317,7 @@ export class Reconciliation implements OnInit {
   }
 
   // 格式化日期
-  formatDate(date: Date): string {
+  formatDate(date: Date | undefined | null): string {
     if (!date) return '';
     return new Date(date).toLocaleDateString('zh-CN');
   }
@@ -334,7 +335,6 @@ export class Reconciliation implements OnInit {
   // 应用日期范围过滤
   applyDateRangeFilter(start: Date | null, end: Date | null): void {
     this.dateRangeFilter.set({ start, end });
-    // 这里应该实现过滤逻辑,但为了简化,我们假设它会在模板中使用
   }
 
   // 应用状态过滤

+ 13 - 8
src/app/pages/finance/reports/reports.html

@@ -1,5 +1,10 @@
 <div class="reports-container">
   <div class="reports-header">
+    <div class="header-top">
+      <button class="back-to-dashboard-btn" routerLink="/finance/dashboard">
+        <i class="fa fa-arrow-left"></i> 返回工作台
+      </button>
+    </div>
     <h1>报表管理</h1>
     <p>生成、查看和导出各类财务报表</p>
   </div>
@@ -17,7 +22,7 @@
             (ngModelChange)="selectedReportType.set($event)"
             class="form-select"
           >
-            <option *ngFor="let type of reportTypes" [value]="type.value">
+            <option *ngFor="let type of reportTypes || []" [value]="type.value">
               {{ type.label }}
             </option>
           </select>
@@ -31,7 +36,7 @@
             (ngModelChange)="selectedTimePeriod.set($event)"
             class="form-select"
           >
-            <option *ngFor="let period of timePeriods" [value]="period.value">
+            <option *ngFor="let period of timePeriods || []" [value]="period.value">
               {{ period.label }}
             </option>
           </select>
@@ -67,7 +72,7 @@
             (ngModelChange)="selectedChartType.set($event)"
             class="form-select"
           >
-            <option *ngFor="let chart of chartTypes" [value]="chart.value">
+            <option *ngFor="let chart of chartTypes || []" [value]="chart.value">
               {{ chart.label }}
             </option>
           </select>
@@ -241,15 +246,15 @@
   <div class="historical-reports">
     <div class="history-header">
       <h2>历史报表</h2>
-      <div class="history-count">{{ historicalReports().length }} 份记录</div>
+      <div class="history-count">{{ historicalReports().length || 0 }} 份记录</div>
     </div>
     
     <div class="history-list">
       <div 
-        *ngFor="let report of historicalReports()" 
-        class="history-item" 
-        (click)="viewHistoricalReport(report)"
-      >
+          *ngFor="let report of historicalReports() || []" 
+          class="history-item" 
+          (click)="viewHistoricalReport(report)"
+        >
         <div class="history-icon">{{ getReportTypeIcon(report.type) }}</div>
         <div class="history-content">
           <div class="history-title">{{ report.title }}</div>

+ 32 - 0
src/app/pages/finance/reports/reports.scss

@@ -9,6 +9,38 @@
   text-align: center;
 }
 
+.header-top {
+  margin-bottom: 20px;
+  text-align: left;
+}
+
+.back-to-dashboard-btn {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 16px;
+  background-color: #f5f5f5;
+  color: #4a90e2;
+  border: 1px solid #ddd;
+  border-radius: 6px;
+  font-size: 14px;
+  font-weight: 500;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  text-decoration: none;
+}
+
+.back-to-dashboard-btn:hover {
+  background-color: #4a90e2;
+  color: white;
+  border-color: #4a90e2;
+  transform: translateY(-1px);
+}
+
+.back-to-dashboard-btn:active {
+  transform: translateY(0);
+}
+
 .reports-header h1 {
   font-size: 28px;
   font-weight: 600;

+ 2 - 1
src/app/pages/finance/reports/reports.ts

@@ -1,6 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
+import { RouterModule } from '@angular/router';
 import { signal } from '@angular/core';
 
 // 报表类型定义
@@ -48,7 +49,7 @@ export interface ReportData {
 
 @Component({
   selector: 'app-reports',
-  imports: [CommonModule, FormsModule],
+  imports: [CommonModule, FormsModule, RouterModule],
   templateUrl: './reports.html',
   styleUrl: './reports.scss'
 })