本设计对现有系统进行多项UI增强和优化:
┌─────────────────────────────────────────────────────────────┐
│ 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 │ │
│ │ - 年度汇总: 未结算列底色标注 │ │
│ │ - 明细表: 未结算行底色标注 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
需要修改的组件:
PersonList.jsx - 移除 ID 列定义ItemList.jsx - 移除 ID 列定义SupplierList.jsx - 移除 ID 列定义WorkRecordList.jsx - 移除 ID 列定义AdminList.jsx - 移除 ID 列定义修改方式:从 columns 数组中删除 { title: 'ID', dataIndex: 'id', ... } 对象。
在筛选区域增加结算状态下拉框:
// 新增状态
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
}
将"已结算"和"未结算"两列合并为单一"结算状态"列,放在"人员"列后面:
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',
// ...
}
]
修改 supplierBreakdownColumns 中的结算状态列渲染:
{
title: '结算状态',
dataIndex: 'is_settled',
key: 'is_settled',
align: 'center',
render: (value) => value ? (
<span style={{ color: '#000000' }}>已结算</span> // 黑色
) : (
<span style={{ color: '#fa8c16' }}>未结算</span> // 保持橙色
)
}
修改 work_record_service.py 的 get_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'
使用浅橙色背景 (#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
在 _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
无需修改数据模型。
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.
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
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
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
筛选参数处理
is_settled 参数值无效,忽略该参数并返回所有记录导出样式处理
Backend Service Tests
get_all() 方法正确处理 is_settled 参数Frontend Component Tests
使用 Hypothesis 库进行属性测试:
Settlement Filter Property Test
Export Styling Property Test