feat: 完成 Flutter 版智能电网 IoT 管理应用初始化搭建

This commit is contained in:
andyesfly committed 2026-10-02 17:21:53 +08:00
commit f61b7bf90b
120 files changed
+15229

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,165 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_typography.dart';
import '../../../shared/widgets/app_feedback.dart';
import '../../../shared/widgets/x_card.dart';
import '../../../shared/widgets/x_chip.dart';
import '../../../shared/widgets/x_common.dart';
import '../../../shared/widgets/x_icon.dart';
import '../../../shared/widgets/x_top_bar.dart';
import '../data/survey_api.dart';
import '../data/survey_models.dart';
/// 勘测任务列表,对应 `pages/survey/list.vue`。
class SurveyListPage extends ConsumerStatefulWidget {
const SurveyListPage({super.key});
@override
ConsumerState<SurveyListPage> createState() => _SurveyListPageState();
}
class _SurveyListPageState extends ConsumerState<SurveyListPage> {
List<SurveyItem> _list = const [];
@override
void initState() {
super.initState();
_load();
}
Future<void> _load() async {
try {
final res = await ref.read(surveyApiProvider).list(pageSize: 100);
if (!mounted) return;
if (res.isOk && res.data != null) {
setState(() => _list = res.data!.list);
}
} catch (_) {
if (mounted) showAppToast('加载失败');
}
}
Future<void> _goForm(SurveyItem item) async {
await context.push('/survey/form?id=${item.id}');
if (mounted) _load();
}
@override
Widget build(BuildContext context) {
return XPageShell(
topBar: XTopBar.brand(title: '勘测任务'),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Padding(
padding: EdgeInsets.fromLTRB(16, 8, 16, 4),
child: Text(
'管理您的现场勘测与检查任务',
style: TextStyle(fontSize: 14, color: AppColors.textMuted),
),
),
Expanded(child: _buildContent()),
],
),
);
}
Widget _buildContent() {
if (_list.isEmpty) {
return ListView(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
children: const [XPlaceholder(text: '暂无勘测任务')],
);
}
return ListView.builder(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
itemCount: _list.length,
itemBuilder: (context, index) => _buildCard(_list[index]),
);
}
Widget _buildCard(SurveyItem item) {
return XCard(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
onTap: () => _goForm(item),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${item.customerName.isEmpty ? '未知客户' : item.customerName}的勘测',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.onSurface,
),
),
const SizedBox(height: 4),
Text(
'任务ID:${item.surveyNo}',
style: AppTypography.dataMono.copyWith(
color: AppColors.textMuted,
),
),
],
),
),
),
XChip(
surveyStatusText(item.status),
tone: surveyStatusTone(item.status),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 14),
child: Column(
children: [
_buildLine(
'location',
AppColors.primary,
item.siteLocation.isEmpty ? '地点未填' : item.siteLocation,
),
const SizedBox(height: 10),
_buildLine(
'schedule',
AppColors.statusWarn,
'计划时间:${item.planTimeText}',
),
],
),
),
],
),
);
}
Widget _buildLine(String icon, Color color, String text) {
return Row(
children: [
XIcon(icon, size: 18, color: color),
const SizedBox(width: 10),
Expanded(
child: Text(
text,
style: const TextStyle(fontSize: 14, color: AppColors.onSurfaceVariant),
),
),
],
);
}
}