feat: add Flutter schema-driven form cards
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:aioa_mobile/core/forms/presentation/dynamic_form_card.dart';
|
||||
import 'package:aioa_mobile/features/form/application/leave_draft_controller.dart';
|
||||
import 'package:aioa_mobile/features/form/domain/leave_form_definition.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class LeaveFormPage extends ConsumerWidget {
|
||||
const LeaveFormPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final formState = ref.watch(leaveDraftProvider);
|
||||
final controller = ref.read(leaveDraftProvider.notifier);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(leaveFormDefinition.dataSchema.title)),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 32),
|
||||
children: [
|
||||
_AiAssistCard(onApply: controller.applyAiSuggestion),
|
||||
const SizedBox(height: 14),
|
||||
DynamicFormCard(
|
||||
definition: leaveFormDefinition,
|
||||
state: formState,
|
||||
onChanged: controller.setValue,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
FilledButton.icon(
|
||||
onPressed: () {
|
||||
if (!controller.validate()) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('请检查表单中的必填项和时间范围')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
showModalBottomSheet<void>(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
builder: (context) => _ConfirmationSheet(
|
||||
values: ref.read(leaveDraftProvider).values,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.check_circle_outline),
|
||||
label: const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 14),
|
||||
child: Text('检查并确认'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AiAssistCard extends StatelessWidget {
|
||||
const _AiAssistCard({required this.onApply});
|
||||
|
||||
final VoidCallback onApply;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primaryContainer.withValues(alpha: 0.45),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
const CircleAvatar(child: Icon(Icons.auto_awesome)),
|
||||
const SizedBox(width: 12),
|
||||
const Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'AI 表单助手',
|
||||
style: TextStyle(fontWeight: FontWeight.w700),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text('示例:帮我填写明天下午的事假申请'),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(onPressed: onApply, child: const Text('自动填写')),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ConfirmationSheet extends StatelessWidget {
|
||||
const _ConfirmationSheet({required this.values});
|
||||
|
||||
final Map<String, Object?> values;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'提交前确认',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w700),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text('AI 或 Schema 只能生成草稿,实际业务写操作必须在用户确认后执行。'),
|
||||
const SizedBox(height: 16),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Text(const JsonEncoder.withIndent(' ').convert(values)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('演示模式:草稿已通过本地校验,尚未调用后端')),
|
||||
);
|
||||
},
|
||||
child: const Text('确认创建草稿'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user