import 'package:autosos_flutter/provider/providers.dart'; import 'package:autosos_flutter/util/toast.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; /// 认证页(对应 Android AuthenticationActivity) /// 三种:个人 / 企业 / 司机 class AuthenticationPage extends ConsumerStatefulWidget { const AuthenticationPage({super.key}); @override ConsumerState createState() => _AuthenticationPageState(); } class _AuthenticationPageState extends ConsumerState with SingleTickerProviderStateMixin { late final TabController _tab; @override void initState() { super.initState(); _tab = TabController(length: 3, vsync: this); } @override void dispose() { _tab.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('认证'), bottom: TabBar( controller: _tab, tabs: const [ Tab(text: '个人'), Tab(text: '企业'), Tab(text: '司机'), ], ), ), body: TabBarView( controller: _tab, children: const [ _PersonalForm(), _EnterpriseForm(), _DriverForm(), ], ), ); } } class _PersonalForm extends ConsumerStatefulWidget { const _PersonalForm(); @override ConsumerState<_PersonalForm> createState() => _PersonalFormState(); } class _PersonalFormState extends ConsumerState<_PersonalForm> { final _name = TextEditingController(); final _idCard = TextEditingController(); final _front = TextEditingController(); final _back = TextEditingController(); bool _loading = false; @override void dispose() { _name.dispose(); _idCard.dispose(); _front.dispose(); _back.dispose(); super.dispose(); } Future _submit() async { if (_name.text.isEmpty || _idCard.text.isEmpty) { Toast.error('请填写姓名和身份证号'); return; } if (_front.text.isEmpty || _back.text.isEmpty) { Toast.error('请上传身份证正反面'); return; } setState(() => _loading = true); EasyLoading.show(status: '提交中…'); try { final r = await ref.read(userApiProvider).authPersonal( name: _name.text.trim(), idCard: _idCard.text.trim(), idCardFront: _front.text.trim(), idCardBack: _back.text.trim(), ); EasyLoading.dismiss(); if (!r.isSuccess) { Toast.error(r.message ?? '提交失败'); return; } Toast.success('已提交,请等待审核'); if (mounted) Navigator.pop(context); } catch (e) { EasyLoading.dismiss(); Toast.error('提交失败:$e'); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) => _form(children: [ _tf(_name, '真实姓名'), _tf(_idCard, '身份证号'), _imgField(_front, '身份证正面 URL(七牛)'), _imgField(_back, '身份证反面 URL(七牛)'), _submitBtn('提交个人认证', _loading, _submit), ]); } class _EnterpriseForm extends ConsumerStatefulWidget { const _EnterpriseForm(); @override ConsumerState<_EnterpriseForm> createState() => _EnterpriseFormState(); } class _EnterpriseFormState extends ConsumerState<_EnterpriseForm> { final _company = TextEditingController(); final _license = TextEditingController(); final _licenseImg = TextEditingController(); final _legalName = TextEditingController(); final _legalId = TextEditingController(); final _legalFront = TextEditingController(); final _legalBack = TextEditingController(); bool _loading = false; @override void dispose() { _company.dispose(); _license.dispose(); _licenseImg.dispose(); _legalName.dispose(); _legalId.dispose(); _legalFront.dispose(); _legalBack.dispose(); super.dispose(); } Future _submit() async { if (_company.text.isEmpty || _license.text.isEmpty) { Toast.error('请填写公司名和营业执照号'); return; } setState(() => _loading = true); EasyLoading.show(status: '提交中…'); try { final r = await ref.read(userApiProvider).authEnterprise( companyName: _company.text.trim(), licenseNo: _license.text.trim(), licenseImg: _licenseImg.text.trim(), legalPerson: _legalName.text.trim(), legalIdCard: _legalId.text.trim(), legalIdFront: _legalFront.text.trim(), legalIdBack: _legalBack.text.trim(), ); EasyLoading.dismiss(); if (!r.isSuccess) { Toast.error(r.message ?? '提交失败'); return; } Toast.success('已提交,请等待审核'); if (mounted) Navigator.pop(context); } catch (e) { EasyLoading.dismiss(); Toast.error('提交失败:$e'); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) => _form(children: [ _tf(_company, '公司名称'), _tf(_license, '营业执照号'), _imgField(_licenseImg, '营业执照图片 URL'), const Divider(), _tf(_legalName, '法人姓名'), _tf(_legalId, '法人身份证号'), _imgField(_legalFront, '法人身份证正面 URL'), _imgField(_legalBack, '法人身份证反面 URL'), _submitBtn('提交企业认证', _loading, _submit), ]); } class _DriverForm extends ConsumerStatefulWidget { const _DriverForm(); @override ConsumerState<_DriverForm> createState() => _DriverFormState(); } class _DriverFormState extends ConsumerState<_DriverForm> { final _driverNo = TextEditingController(); final _driverLicense = TextEditingController(); final _front = TextEditingController(); final _back = TextEditingController(); bool _loading = false; @override void dispose() { _driverNo.dispose(); _driverLicense.dispose(); _front.dispose(); _back.dispose(); super.dispose(); } Future _submit() async { if (_driverNo.text.isEmpty || _driverLicense.text.isEmpty) { Toast.error('请填写驾驶证号和驾驶证'); return; } setState(() => _loading = true); EasyLoading.show(status: '提交中…'); try { final r = await ref.read(userApiProvider).authDriver( driverNo: _driverNo.text.trim(), driverLicense: _driverLicense.text.trim(), drivingLicenseFront: _front.text.trim(), drivingLicenseBack: _back.text.trim(), ); EasyLoading.dismiss(); if (!r.isSuccess) { Toast.error(r.message ?? '提交失败'); return; } Toast.success('已提交,请等待审核'); if (mounted) Navigator.pop(context); } catch (e) { EasyLoading.dismiss(); Toast.error('提交失败:$e'); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) => _form(children: [ _tf(_driverNo, '驾驶证号'), _tf(_driverLicense, '驾驶证档案编号'), _imgField(_front, '驾驶证正面 URL'), _imgField(_back, '驾驶证反面 URL'), _submitBtn('提交司机认证', _loading, _submit), ]); } Widget _form({required List children}) => SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: children), ); Widget _tf(TextEditingController c, String label) => Padding( padding: const EdgeInsets.only(bottom: 12), child: TextField( controller: c, decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), ), ), ); Widget _imgField(TextEditingController c, String label) => Padding( padding: const EdgeInsets.only(bottom: 12), child: TextField( controller: c, decoration: InputDecoration( labelText: label, hintText: '七牛上传后返回的 URL', border: const OutlineInputBorder(), ), ), ); Widget _submitBtn(String text, bool loading, VoidCallback onTap) => SizedBox( height: 48, child: ElevatedButton( onPressed: loading ? null : onTap, style: ElevatedButton.styleFrom( backgroundColor: Colors.red, ), child: Text(loading ? '提交中…' : text), ), );