536 lines
21 KiB
Dart
536 lines
21 KiB
Dart
import 'dart:convert';
|
||
|
||
import 'package:ar_tourism_flutter_unity/components/appbar.dart';
|
||
import 'package:dio/dio.dart';
|
||
import 'package:flutter/material.dart';
|
||
// 注释掉不需要的导入
|
||
// import 'package:http_parser/http_parser.dart';
|
||
// import 'package:image_picker/image_picker.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
import '../../apis/app.dart';
|
||
import '../../components/gradientButton.dart';
|
||
// 注释掉不需要的导入
|
||
// import 'dart:io';
|
||
//getRealNameAuth接口
|
||
|
||
class RealNamePage extends StatefulWidget {
|
||
const RealNamePage({super.key});
|
||
|
||
@override
|
||
State<RealNamePage> createState() => _RealNamePageState();
|
||
}
|
||
|
||
class _RealNamePageState extends State<RealNamePage> {
|
||
// 定义控制器来获取输入内容
|
||
final TextEditingController _nameController = TextEditingController();
|
||
final TextEditingController _idCardController = TextEditingController();
|
||
final TextEditingController _phoneController = TextEditingController();
|
||
|
||
// 注释掉不需要的照片相关变量和方法
|
||
// 用于存储选中的身份证正面和反面图片
|
||
// XFile? _frontImage;
|
||
// XFile? _backImage;
|
||
|
||
// final ImagePicker _picker = ImagePicker();
|
||
|
||
// 图片选择方法
|
||
// Future<void> _pickImage(bool isFront) async {
|
||
// print(isFront ? '开始选择身份证正面图片' : '开始选择身份证反面图片'); // 打印选择步骤
|
||
// final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
|
||
|
||
// if (image != null) {
|
||
// setState(() {
|
||
// if (isFront) {
|
||
// _frontImage = image; // 选择的是身份证正面
|
||
// print('身份证正面图片已选择: ${_frontImage!.path}'); // 打印图片路径
|
||
// } else {
|
||
// _backImage = image; // 选择的是身份证反面
|
||
// print('身份证反面图片已选择: ${_backImage!.path}'); // 打印图片路径
|
||
// }
|
||
// });
|
||
// } else {
|
||
// print('未选择图片');
|
||
// }
|
||
// }
|
||
|
||
// 添加验证方法
|
||
bool _validateIdCard(String idCard) {
|
||
// 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
|
||
RegExp idCardReg = RegExp(r'^(\d{15}$)|(\d{17}([0-9]|X|x)$)');
|
||
return idCardReg.hasMatch(idCard);
|
||
}
|
||
|
||
bool _validatePhone(String phone) {
|
||
// 手机号码验证:1开头的11位数字
|
||
RegExp phoneReg = RegExp(r'^1[3-9]\d{9}$');
|
||
return phoneReg.hasMatch(phone);
|
||
}
|
||
|
||
bool _validateName(String name) {
|
||
// 姓名验证:2-8个汉字
|
||
RegExp nameReg = RegExp(r'^[\u4e00-\u9fa5]{2,8}$');
|
||
return nameReg.hasMatch(name);
|
||
}
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_checkAuthStatus();
|
||
}
|
||
|
||
Future<void> _checkAuthStatus() async {
|
||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
bool isRealNameAuth = prefs.getBool('isRealNameAuth') ?? false;
|
||
|
||
if (isRealNameAuth && mounted) {
|
||
Navigator.pushReplacementNamed(context, '/tabs');
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
resizeToAvoidBottomInset: true,
|
||
appBar: const CustomAppBar(title: '实名认证'),
|
||
body: Stack(
|
||
children: [
|
||
// 背景图片
|
||
Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
height: MediaQuery.of(context).size.height,
|
||
decoration: const BoxDecoration(
|
||
image: DecorationImage(
|
||
image: AssetImage('images/pwd_bg.png'),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
),
|
||
// 使用 SingleChildScrollView 包裹所有内容,包括提交按钮
|
||
SingleChildScrollView(
|
||
physics: const ClampingScrollPhysics(),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(20),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
// 注释掉身份证照片上传部分
|
||
/*
|
||
const Text(
|
||
"身份证照片",
|
||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||
),
|
||
const SizedBox(height: 10),
|
||
const Text(
|
||
"证件需内容完整,图像清晰,真实且在有效期内",
|
||
style: TextStyle(color: Color.fromRGBO(255, 255, 255, 0.5)),
|
||
),
|
||
const SizedBox(height: 10),
|
||
const Text(
|
||
"信息安全提示:为确保信息安全,当前实名认证环节,直接且仅通过百度智能云身份管理服务进行实名身份认证,身份信息无其他用途.",
|
||
style: TextStyle(color: Color.fromRGBO(255, 255, 255, 0.5)),
|
||
),
|
||
const SizedBox(height: 20),
|
||
// 身份证上传部分
|
||
Row(
|
||
children: [
|
||
// 身份证正面上传
|
||
GestureDetector(
|
||
onTap: () => _pickImage(true),
|
||
child: Column(
|
||
children: [
|
||
_frontImage == null
|
||
? Image.asset(
|
||
'images/idCard_left.png',
|
||
width: 150,
|
||
height: 85,
|
||
)
|
||
: Image.file(
|
||
File(_frontImage!.path),
|
||
width: 150,
|
||
height: 85,
|
||
fit: BoxFit.cover,
|
||
),
|
||
const SizedBox(height: 10),
|
||
const Text(
|
||
"上传身份证人像面",
|
||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const SizedBox(width: 20),
|
||
// 身份证反面上传
|
||
GestureDetector(
|
||
onTap: () => _pickImage(false),
|
||
child: Column(
|
||
children: [
|
||
_backImage == null
|
||
? Image.asset(
|
||
'images/idCard_right.png',
|
||
width: 150,
|
||
height: 85,
|
||
)
|
||
: Image.file(
|
||
File(_backImage!.path),
|
||
width: 150,
|
||
height: 85,
|
||
fit: BoxFit.cover,
|
||
),
|
||
const SizedBox(height: 10),
|
||
const Text(
|
||
"上传身份证国徽面",
|
||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 30),
|
||
*/
|
||
const Text(
|
||
"身份信息",
|
||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||
),
|
||
const SizedBox(height: 10),
|
||
// 输入框部分
|
||
_buildInputField("真实姓名", "请输入姓名", _nameController),
|
||
const SizedBox(height: 10),
|
||
_buildInputField("身份证号", "请输入身份证号", _idCardController),
|
||
const SizedBox(height: 10),
|
||
_buildInputField("手机号码", "请输入手机号码", _phoneController),
|
||
|
||
// 添加一个固定的底部间距
|
||
const SizedBox(height: 40),
|
||
|
||
// 将提交按钮放在 Column 中,而不是 Positioned
|
||
Padding(
|
||
padding: EdgeInsets.only(
|
||
bottom: MediaQuery.of(context).padding.bottom + 20,
|
||
),
|
||
child: GradientButton(
|
||
text: '提交',
|
||
onPressed: () async {
|
||
String errorMessage = '';
|
||
|
||
// 注释掉照片验证
|
||
// if (_frontImage == null || _backImage == null) {
|
||
// errorMessage = '请上传身份证正反面照片';
|
||
// } else
|
||
if (_nameController.text.isEmpty) {
|
||
errorMessage = '请输入姓名';
|
||
} else if (!_validateName(_nameController.text)) {
|
||
errorMessage = '请输入2-8个汉字的真实姓名';
|
||
} else if (_idCardController.text.isEmpty) {
|
||
errorMessage = '请输入身份证号';
|
||
} else if (!_validateIdCard(_idCardController.text)) {
|
||
errorMessage = '请输入正确的身份证号码';
|
||
} else if (_phoneController.text.isEmpty) {
|
||
errorMessage = '请输入手机号';
|
||
} else if (!_validatePhone(_phoneController.text)) {
|
||
errorMessage = '请输入正确的手机号码';
|
||
}
|
||
|
||
if (errorMessage.isNotEmpty) {
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
backgroundColor: const Color(0xFF1F212E),
|
||
title: const Text(
|
||
'提示',
|
||
style: TextStyle(color: Colors.white),
|
||
),
|
||
content: Text(
|
||
errorMessage,
|
||
style: const TextStyle(color: Colors.white),
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
child: const Text(
|
||
'确定',
|
||
style: TextStyle(color: Color(0xFF7CDCCC)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
|
||
if (_nameController.text.isEmpty ||
|
||
_idCardController.text.isEmpty ||
|
||
_phoneController.text.isEmpty) {
|
||
// 显示错误提示
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
backgroundColor: const Color(0xFF1F212E),
|
||
title: const Text(
|
||
'提示',
|
||
style: TextStyle(color: Colors.white),
|
||
),
|
||
content: const Text(
|
||
'请填写完整信息',
|
||
style: TextStyle(color: Colors.white),
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
child: const Text(
|
||
'确定',
|
||
style: TextStyle(color: Color(0xFF7CDCCC)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 构建实名认证信息对象
|
||
var data = {
|
||
"realname": _nameController.text,
|
||
"idcard": _idCardController.text,
|
||
"mobile": _phoneController.text
|
||
};
|
||
|
||
// 显示加载指示器
|
||
showDialog(
|
||
context: context,
|
||
barrierDismissible: false,
|
||
builder: (BuildContext context) {
|
||
return const Center(
|
||
child: CircularProgressIndicator(
|
||
color: Color(0xFF7CDCCC),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
|
||
// 调用聚合认证API
|
||
final result = await userApi.getJuheAuthentication(data);
|
||
print('API响应: $result');
|
||
|
||
// 关闭加载指示器
|
||
if (mounted) {
|
||
Navigator.pop(context);
|
||
}
|
||
|
||
if (result['code'] == 200) {
|
||
// 保存实名认证状态
|
||
SharedPreferences prefs =
|
||
await SharedPreferences.getInstance();
|
||
await prefs.setBool('isRealNameAuth', true);
|
||
|
||
if (mounted) {
|
||
// 直接跳转到认证成功页面
|
||
Navigator.pushReplacement(
|
||
context,
|
||
MaterialPageRoute(
|
||
builder: (context) => const AuthSuccessPage(),
|
||
),
|
||
);
|
||
}
|
||
} else {
|
||
// 显示错误提示
|
||
if (mounted) {
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
backgroundColor: const Color(0xFF1F212E),
|
||
title: const Text(
|
||
'认证失败',
|
||
style: TextStyle(color: Colors.white),
|
||
),
|
||
content: Text(
|
||
result['msg'] ?? '请稍后重试',
|
||
style: const TextStyle(color: Colors.white),
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
child: const Text(
|
||
'确定',
|
||
style: TextStyle(color: Color(0xFF7CDCCC)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
// 关闭可能显示的加载指示器
|
||
if (mounted) {
|
||
Navigator.pop(context);
|
||
}
|
||
|
||
if (mounted) {
|
||
print('实名认证错误: $error'); // 添加错误日志
|
||
showDialog(
|
||
context: context,
|
||
builder: (context) => AlertDialog(
|
||
backgroundColor: const Color(0xFF1F212E),
|
||
title: const Text(
|
||
'错误',
|
||
style: TextStyle(color: Colors.white),
|
||
),
|
||
content: Text(
|
||
'提交失败: ${error.toString()}',
|
||
style: const TextStyle(color: Colors.white),
|
||
),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () => Navigator.pop(context),
|
||
child: const Text(
|
||
'确定',
|
||
style: TextStyle(color: Color(0xFF7CDCCC)),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
// 修改输入框构建方法,添加键盘类型
|
||
Widget _buildInputField(
|
||
String labelText,
|
||
String hintText,
|
||
TextEditingController controller,
|
||
) {
|
||
// 根据不同的输入框类型设置不同的键盘类型
|
||
TextInputType keyboardType;
|
||
if (labelText == "手机号码") {
|
||
keyboardType = TextInputType.phone;
|
||
} else if (labelText == "身份证号") {
|
||
keyboardType = TextInputType.number;
|
||
} else {
|
||
keyboardType = TextInputType.text;
|
||
}
|
||
|
||
return Row(
|
||
children: [
|
||
SizedBox(
|
||
width: 80,
|
||
child: Text(
|
||
labelText,
|
||
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||
),
|
||
),
|
||
Expanded(
|
||
child: TextField(
|
||
controller: controller,
|
||
keyboardType: keyboardType, // 设置键盘类型
|
||
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||
decoration: InputDecoration(
|
||
hintText: hintText,
|
||
hintStyle: const TextStyle(color: Color.fromRGBO(255, 255, 255, 0.5)),
|
||
enabledBorder: const UnderlineInputBorder(
|
||
borderSide: BorderSide(color: Color.fromRGBO(255, 255, 255, 0.2)),
|
||
),
|
||
focusedBorder: const UnderlineInputBorder(
|
||
borderSide: BorderSide(color: Colors.greenAccent),
|
||
),
|
||
),
|
||
textInputAction: TextInputAction.next,
|
||
onEditingComplete: () {
|
||
FocusScope.of(context).nextFocus();
|
||
},
|
||
),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
}
|
||
|
||
class AuthSuccessPage extends StatelessWidget {
|
||
const AuthSuccessPage({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
resizeToAvoidBottomInset: false,
|
||
appBar: const CustomAppBar(title: '实名认证'),
|
||
body: Stack(
|
||
children: [
|
||
Container(
|
||
width: MediaQuery.of(context).size.width,
|
||
height: MediaQuery.of(context).size.height,
|
||
decoration: const BoxDecoration(
|
||
image: DecorationImage(
|
||
image: AssetImage('images/pwd_bg.png'),
|
||
fit: BoxFit.fill,
|
||
),
|
||
),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(20),
|
||
child: Center(
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.start,
|
||
children: [
|
||
const SizedBox(height: 95),
|
||
Image.asset(
|
||
'images/ok.png',
|
||
width: 100,
|
||
height: 100,
|
||
),
|
||
const SizedBox(height: 20),
|
||
const Text(
|
||
'恭喜你,个人实名认证成功',
|
||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||
),
|
||
const SizedBox(height: 10),
|
||
const Text(
|
||
'你提交的认证资料已通过审核',
|
||
style: TextStyle(
|
||
color: Color.fromRGBO(255, 255, 255, 0.5),
|
||
fontSize: 12,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
Positioned(
|
||
bottom: 60,
|
||
left: 15,
|
||
child: GradientButton(
|
||
text: '返回主页',
|
||
onPressed: () async {
|
||
// 保存认证成功的状态
|
||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||
await prefs.setBool('isRealNameAuth', true);
|
||
|
||
// 返回主页
|
||
if (context.mounted) {
|
||
Navigator.pushNamedAndRemoveUntil(
|
||
context,
|
||
'/tabs',
|
||
(route) => false,
|
||
arguments: {'initialIndex': 0}, // 返回首页tab
|
||
);
|
||
}
|
||
},
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|