重构记分数据模型,替换弓型和靶纸类型为 ID 及名称,更新相关页面以支持新配置。
This commit is contained in:
@@ -3,7 +3,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:arcx/app/app_theme.dart';
|
||||
import 'package:arcx/data/local/models/models.dart';
|
||||
import 'package:arcx/features/scoring/application/point_book_config_provider.dart';
|
||||
import 'package:arcx/features/scoring/application/scoring_service.dart';
|
||||
import 'package:arcx/features/scoring/domain/point_book_config.dart';
|
||||
import 'package:arcx/features/scoring/presentation/point_book_edit_page.dart';
|
||||
|
||||
class PointBookListPage extends ConsumerStatefulWidget {
|
||||
@@ -14,22 +16,31 @@ class PointBookListPage extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _PointBookListPageState extends ConsumerState<PointBookListPage> {
|
||||
BowType? _bowFilter;
|
||||
TargetFaceType? _targetFilter;
|
||||
int? _bowFilter;
|
||||
int? _targetFilter;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final recordsAsync = ref.watch(pointRecordsProvider);
|
||||
final configAsync = ref.watch(pointBookConfigProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('计分记录')),
|
||||
body: Column(
|
||||
children: [
|
||||
_FilterBar(
|
||||
bowFilter: _bowFilter,
|
||||
targetFilter: _targetFilter,
|
||||
onBowChanged: (v) => setState(() => _bowFilter = v),
|
||||
onTargetChanged: (v) => setState(() => _targetFilter = v),
|
||||
configAsync.when(
|
||||
loading: () => const SizedBox(height: 64),
|
||||
error: (e, _) => Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text('配置加载失败:$e'),
|
||||
),
|
||||
data: (config) => _FilterBar(
|
||||
config: config,
|
||||
bowFilter: _bowFilter,
|
||||
targetFilter: _targetFilter,
|
||||
onBowChanged: (v) => setState(() => _bowFilter = v),
|
||||
onTargetChanged: (v) => setState(() => _targetFilter = v),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: recordsAsync.when(
|
||||
@@ -64,10 +75,10 @@ class _PointBookListPageState extends ConsumerState<PointBookListPage> {
|
||||
List<PointRecord> _applyFilters(List<PointRecord> records) {
|
||||
var result = records;
|
||||
if (_bowFilter != null) {
|
||||
result = result.where((r) => r.bowType == _bowFilter).toList();
|
||||
result = result.where((r) => r.bowOptionId == _bowFilter).toList();
|
||||
}
|
||||
if (_targetFilter != null) {
|
||||
result = result.where((r) => r.targetFaceType == _targetFilter).toList();
|
||||
result = result.where((r) => r.targetOptionId == _targetFilter).toList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -107,16 +118,18 @@ class _PointBookListPageState extends ConsumerState<PointBookListPage> {
|
||||
|
||||
class _FilterBar extends StatelessWidget {
|
||||
const _FilterBar({
|
||||
required this.config,
|
||||
required this.bowFilter,
|
||||
required this.targetFilter,
|
||||
required this.onBowChanged,
|
||||
required this.onTargetChanged,
|
||||
});
|
||||
|
||||
final BowType? bowFilter;
|
||||
final TargetFaceType? targetFilter;
|
||||
final ValueChanged<BowType?> onBowChanged;
|
||||
final ValueChanged<TargetFaceType?> onTargetChanged;
|
||||
final PointBookConfig config;
|
||||
final int? bowFilter;
|
||||
final int? targetFilter;
|
||||
final ValueChanged<int?> onBowChanged;
|
||||
final ValueChanged<int?> onTargetChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -125,21 +138,23 @@ class _FilterBar extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _Dropdown<BowType>(
|
||||
child: _Dropdown<int>(
|
||||
label: '弓型',
|
||||
value: bowFilter,
|
||||
items: BowType.values,
|
||||
labelOf: _bowLabel,
|
||||
items: config.bowOption.map((e) => e.id).toList(),
|
||||
labelOf: (id) =>
|
||||
config.bowById(id)?.name ?? id.toString(),
|
||||
onChanged: onBowChanged,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _Dropdown<TargetFaceType>(
|
||||
child: _Dropdown<int>(
|
||||
label: '靶纸',
|
||||
value: targetFilter,
|
||||
items: TargetFaceType.values,
|
||||
labelOf: _targetLabel,
|
||||
items: config.targetOption.map((e) => e.id).toList(),
|
||||
labelOf: (id) =>
|
||||
config.targetById(id)?.name ?? id.toString(),
|
||||
onChanged: onTargetChanged,
|
||||
),
|
||||
),
|
||||
@@ -177,10 +192,12 @@ class _Dropdown<T> extends StatelessWidget {
|
||||
),
|
||||
items: [
|
||||
DropdownMenuItem<T>(value: null, child: Text('全部')),
|
||||
...items.map((e) => DropdownMenuItem<T>(
|
||||
value: e,
|
||||
child: Text(labelOf(e)),
|
||||
)),
|
||||
...items.map(
|
||||
(e) => DropdownMenuItem<T>(
|
||||
value: e,
|
||||
child: Text(labelOf(e), overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: onChanged,
|
||||
);
|
||||
@@ -232,7 +249,7 @@ class _RecordTile extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
subtitle: Text(
|
||||
'${_bowLabel(record.bowType)} · ${record.distanceMeters}m · ${_targetLabel(record.targetFaceType)}\n'
|
||||
'${record.bowName} · ${record.distanceMeters}m · ${record.targetName}\n'
|
||||
'${_formatDate(record.createdAt)} ${record.totalArrows}支 ${record.averageScore != null ? '均${record.averageScore!.toStringAsFixed(1)}环' : ''}',
|
||||
style: TextStyle(fontSize: 12, color: AppTheme.textSecondary),
|
||||
),
|
||||
@@ -272,42 +289,6 @@ class _EmptyState extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
String _bowLabel(BowType t) {
|
||||
switch (t) {
|
||||
case BowType.recurve:
|
||||
return '反曲弓';
|
||||
case BowType.compound:
|
||||
return '复合弓';
|
||||
case BowType.barebow:
|
||||
return '光弓';
|
||||
case BowType.traditional:
|
||||
return '传统弓';
|
||||
case BowType.longbow:
|
||||
return '长弓';
|
||||
case BowType.other:
|
||||
return '其他';
|
||||
}
|
||||
}
|
||||
|
||||
String _targetLabel(TargetFaceType t) {
|
||||
switch (t) {
|
||||
case TargetFaceType.cm40:
|
||||
return '40cm';
|
||||
case TargetFaceType.cm60:
|
||||
return '60cm';
|
||||
case TargetFaceType.cm80:
|
||||
return '80cm';
|
||||
case TargetFaceType.cm122:
|
||||
return '122cm';
|
||||
case TargetFaceType.vegas3Spot:
|
||||
return '维加斯三联';
|
||||
case TargetFaceType.vertical3Spot:
|
||||
return '垂直三联';
|
||||
case TargetFaceType.custom:
|
||||
return '自定义';
|
||||
}
|
||||
}
|
||||
|
||||
String _formatDate(DateTime dt) {
|
||||
return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} '
|
||||
'${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
Reference in New Issue
Block a user