design.md 9.9 KB

Design Document: UI Enhancements

Overview

本设计对现有系统进行多项UI增强和优化:

  1. 全局隐藏所有表格中的ID列,使界面更简洁
  2. 工作记录列表增加结算状态筛选功能
  3. 仪表盘年度汇总结算状态显示优化
  4. 导出报表中未结算状态的视觉标注

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Frontend (React)                        │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              List Components (5个)                   │    │
│  │  - PersonList.jsx: 移除ID列                         │    │
│  │  - ItemList.jsx: 移除ID列                           │    │
│  │  - SupplierList.jsx: 移除ID列                       │    │
│  │  - WorkRecordList.jsx: 移除ID列 + 增加结算筛选      │    │
│  │  - AdminList.jsx: 移除ID列                          │    │
│  └─────────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │                   Dashboard.jsx                      │    │
│  │  - 年度汇总: 合并结算状态列,调整位置               │    │
│  │  - 人员按供应商明细: 已结算状态黑色字体             │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Backend (Flask)                         │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              work_record_service.py                  │    │
│  │  - get_all(): 支持 is_settled 筛选参数              │    │
│  └─────────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │               export_service.py                      │    │
│  │  - 年度汇总: 未结算列底色标注                       │    │
│  │  - 明细表: 未结算行底色标注                         │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘

Components and Interfaces

Frontend Component Changes

1. List Components - 隐藏ID列

需要修改的组件:

  • PersonList.jsx - 移除 ID 列定义
  • ItemList.jsx - 移除 ID 列定义
  • SupplierList.jsx - 移除 ID 列定义
  • WorkRecordList.jsx - 移除 ID 列定义
  • AdminList.jsx - 移除 ID 列定义

修改方式:从 columns 数组中删除 { title: 'ID', dataIndex: 'id', ... } 对象。

2. WorkRecordList - 增加结算状态筛选

在筛选区域增加结算状态下拉框:

// 新增状态
const [selectedSettlement, setSelectedSettlement] = useState(null)

// 筛选选项
const settlementOptions = [
  { label: '全部', value: null },
  { label: '已结算', value: true },
  { label: '未结算', value: false }
]

// 在筛选区域增加
<Select
  placeholder="结算状态"
  allowClear
  style={{ width: '100%' }}
  value={selectedSettlement}
  onChange={setSelectedSettlement}
  options={settlementOptions}
/>

API调用时传递 is_settled 参数:

if (selectedSettlement !== null) {
  params.is_settled = selectedSettlement
}

3. Dashboard - 年度汇总结算状态优化

将"已结算"和"未结算"两列合并为单一"结算状态"列,放在"人员"列后面:

const yearlySummaryColumns = [
  {
    title: '人员',
    dataIndex: 'person_name',
    key: 'person_name',
    fixed: 'left',
    width: 100
  },
  {
    title: '结算状态',
    key: 'settlement_status',
    width: 180,
    render: (_, record) => (
      <span>
        已结算: ¥{(record.settled_total || 0).toFixed(2)} / 
        未结算: ¥{(record.unsettled_total || 0).toFixed(2)}
      </span>
    )
  },
  // ... 月份列 ...
  {
    title: '年度合计',
    dataIndex: 'yearly_total',
    // ...
  }
]

4. Dashboard - 人员按供应商明细已结算状态字体颜色

修改 supplierBreakdownColumns 中的结算状态列渲染:

{
  title: '结算状态',
  dataIndex: 'is_settled',
  key: 'is_settled',
  align: 'center',
  render: (value) => value ? (
    <span style={{ color: '#000000' }}>已结算</span>  // 黑色
  ) : (
    <span style={{ color: '#fa8c16' }}>未结算</span>  // 保持橙色
  )
}

Backend API Changes

Work Record Service - 支持结算状态筛选

修改 work_record_service.pyget_all() 方法,支持 is_settled 查询参数:

@staticmethod
def get_all(person_id=None, date=None, year=None, month=None, is_settled=None):
    query = WorkRecord.query
    
    # ... 现有筛选逻辑 ...
    
    # 新增结算状态筛选
    if is_settled is not None:
        query = query.filter(WorkRecord.is_settled == is_settled)
    
    return query.order_by(WorkRecord.work_date.desc()).all()

修改路由接收参数:

is_settled = request.args.get('is_settled')
if is_settled is not None:
    is_settled = is_settled.lower() == 'true'

Export Service Changes

1. 年度汇总未结算列底色标注

使用浅橙色背景 (#FFF2E8) 标注"未结算"列:

from openpyxl.styles import PatternFill

UNSETTLED_FILL = PatternFill(start_color='FFF2E8', end_color='FFF2E8', fill_type='solid')

# 在 _create_yearly_summary_sheet 中
# 为未结算列标题应用底色
cell = ws.cell(row=1, column=16, value='未结算')
cell.fill = UNSETTLED_FILL

# 为未结算列数据单元格应用底色
cell = ws.cell(row=row_idx, column=16, value=round(unsettled, 2))
cell.fill = UNSETTLED_FILL

2. 明细表未结算行底色标注

_create_detail_sheet 中,为未结算记录的整行应用底色:

# 在写入数据行时
for row_idx, record in enumerate(records, 2):
    # ... 写入数据 ...
    
    # 如果是未结算记录,为整行应用底色
    if not record.is_settled:
        for col_idx in range(1, len(ExportService.DETAIL_HEADERS) + 1):
            ws.cell(row=row_idx, column=col_idx).fill = UNSETTLED_FILL

Data Models

无需修改数据模型。

Correctness Properties

A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.

Property 1: Settlement Filter Correctness

For any set of work records and any settlement filter value (true, false, or null), the filtered results SHALL contain only records matching the filter criteria: when filter is true, all returned records have is_settled=true; when filter is false, all returned records have is_settled=false; when filter is null, all records are returned.

Validates: Requirements 2.2, 2.3, 2.4, 2.5

Property 2: Unsettled Row Highlighting in Exports

For any exported report (monthly or yearly), all rows in the detail sheet where settlement status is "未结算" SHALL have the same distinct background color applied to all cells in that row.

Validates: Requirements 6.1, 6.2, 6.3

Property 3: Unsettled Column Highlighting in Yearly Summary

For any yearly report export, all cells in the "未结算" column (including header) in the yearly summary sheet SHALL have a distinct background color applied.

Validates: Requirements 5.1, 5.2

Error Handling

  1. 筛选参数处理

    • 如果 is_settled 参数值无效,忽略该参数并返回所有记录
    • 保持现有的错误处理模式
  2. 导出样式处理

    • 如果样式应用失败,继续导出但不应用样式
    • 记录错误日志但不中断导出流程

Testing Strategy

Unit Tests

  1. Backend Service Tests

    • 测试 get_all() 方法正确处理 is_settled 参数
    • 测试导出服务正确应用未结算行/列底色
  2. Frontend Component Tests

    • 测试各列表组件不显示ID列
    • 测试工作记录列表的结算状态筛选功能
    • 测试仪表盘年度汇总的结算状态列格式

Property-Based Tests

使用 Hypothesis 库进行属性测试:

  1. Settlement Filter Property Test

    • 生成随机工作记录集合
    • 验证筛选结果符合筛选条件
  2. Export Styling Property Test

    • 生成随机工作记录
    • 验证导出文件中未结算记录的样式正确应用