feat: 完成 Flutter 版智能电网 IoT 管理应用初始化搭建
This commit is contained in:
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user