From 4c10dce1a8bf49fc8aa2160e30f0318b82efbc27 Mon Sep 17 00:00:00 2001 From: xufei <727302827@qq.com> Date: Wed, 9 Jul 2025 14:27:53 +0800 Subject: [PATCH] =?UTF-8?q?2025.7.9=20=E6=88=91=E7=9A=84=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E9=83=BD=E5=AE=8C=E6=88=90=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/home/danger_page.dart | 394 ------------------------------ lib/home/home_page.dart | 45 +++- lib/mine/change_pass_page.dart | 232 ++++++++++++++++++ lib/mine/message_detail_page.dart | 115 +++++++++ lib/mine/message_page.dart | 252 +++++++++++++++++++ lib/mine/mine_page.dart | 116 +++++---- lib/tools/SmallWidget.dart | 25 ++ lib/tools/h_colors.dart | 11 + lib/tools/my_appbar.dart | 87 +++++++ lib/tools/tools.dart | 134 ++++++++++ 10 files changed, 953 insertions(+), 458 deletions(-) delete mode 100644 lib/home/danger_page.dart create mode 100644 lib/mine/change_pass_page.dart create mode 100644 lib/mine/message_detail_page.dart create mode 100644 lib/mine/message_page.dart create mode 100644 lib/tools/SmallWidget.dart create mode 100644 lib/tools/h_colors.dart create mode 100644 lib/tools/my_appbar.dart create mode 100644 lib/tools/tools.dart diff --git a/lib/home/danger_page.dart b/lib/home/danger_page.dart deleted file mode 100644 index 6aba5af..0000000 --- a/lib/home/danger_page.dart +++ /dev/null @@ -1,394 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter/material.dart'; - - -class DangerPage extends StatefulWidget { - const DangerPage({super.key}); - - @override - _DangerPageState createState() => _DangerPageState(); -} - -class _DangerPageState extends State { - String _selectedOption = '全部'; - final TextEditingController _searchController = TextEditingController(); - final List> enterprises = [ - { - 'name': '泰安安全', - 'type': '冶金行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '秦皇岛杰瑞科技有限公司', - 'type': '轻工行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '秦皇岛异特机械设备有限公司', - 'type': '机械行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '秦皇岛利华德科技有限公司', - 'type': '机械行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '广东胜捷消防科技有限公司秦皇岛分公司', - 'type': '机械行业', - 'unit': '执法一中队', - 'status': '未划分' - }, - { - 'name': '河北联技安全系统有限公司', - 'type': '轻工行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '秦皇岛市万天科技有限公司', - 'type': '轻工行业', - 'unit': '执法一中队', - 'status': '未划分' - }, - { - 'name': '秦皇岛市非晶科技有限公司', - 'type': '轻工行业', - 'unit': '执法一中队', - 'status': '已划分' - }, - { - 'name': '海湾安全技术有限公司', - 'type': '轻工行业', - 'unit': '执法一中队,西区消防大队', - 'status': '已划分' - }, - { - 'name': '秦皇岛海湾塑胶金属制品有限公司', - 'type': '轻工行业', - 'unit': '执法一中队', - 'status': '未划分' - }, - ]; - - List> get filteredEnterprises { - if (_searchController.text.isNotEmpty) { - return enterprises - .where((e) => e['name']!.contains(_searchController.text)) - .toList(); - } - - if (_selectedOption == '全部') { - return enterprises; - } else { - return enterprises - .where((e) => e['status'] == _selectedOption) - .toList(); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('企业信息'), - centerTitle: true, - actions: [ - IconButton( - icon: const Icon(Icons.filter_alt), - onPressed: () { - // 筛选功能 - }, - ), - ], - ), - body: Column( - children: [ - _buildFunctionButtons(), - _buildSearchSection(), - _buildFilterSection(), - _buildEnterpriseList(), - ], - ), - ); - } - - Widget _buildFunctionButtons() { - return Container( - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), - color: Colors.white, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildFunctionButton('监管划分', Icons.assignment), - _buildFunctionButton('信息审核', Icons.verified), - _buildFunctionButton('持证人员', Icons.badge), - ], - ), - ); - } - - Widget _buildFunctionButton(String label, IconData icon) { - return Column( - children: [ - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFF0D47A1).withOpacity(0.1), - borderRadius: BorderRadius.circular(12), - ), - child: Icon(icon, size: 30, color: const Color(0xFF0D47A1)), - ), - const SizedBox(height: 8), - Text(label, style: const TextStyle(fontSize: 14)), - ], - ); - } - - Widget _buildSearchSection() { - return Container( - padding: const EdgeInsets.all(16), - color: Colors.white, - child: Row( - children: [ - Expanded( - child: TextField( - controller: _searchController, - decoration: InputDecoration( - hintText: '请输入关键字', - prefixIcon: const Icon(Icons.search), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(30), - borderSide: BorderSide.none, - ), - filled: true, - fillColor: Colors.grey[100], - contentPadding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 20), - ), - onChanged: (value) { - setState(() {}); - }, - ), - ), - const SizedBox(width: 8), - Container( - decoration: BoxDecoration( - color: const Color(0xFF0D47A1), - borderRadius: BorderRadius.circular(30), - ), - child: IconButton( - icon: const Icon(Icons.search, color: Colors.white), - onPressed: () { - setState(() {}); - }, - ), - ), - ], - ), - ); - } - - Widget _buildFilterSection() { - return Container( - padding: const EdgeInsets.all(16), - color: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('请选择部门', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _buildFilterOption('全部'), - _buildFilterOption('已划分'), - _buildFilterOption('未划分'), - ], - ), - ], - ), - ); - } - - Widget _buildFilterOption(String text) { - final isSelected = _selectedOption == text; - - return GestureDetector( - onTap: () { - setState(() { - _selectedOption = text; - }); - }, - child: Row( - children: [ - Container( - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: isSelected ? const Color(0xFF0D47A1) : Colors.grey, - width: 2, - ), - ), - child: isSelected - ? Center( - child: Container( - width: 12, - height: 12, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: Color(0xFF0D47A1), - ), - ), - ) - : null, - ), - const SizedBox(width: 8), - Text(text, style: TextStyle( - fontSize: 16, - color: isSelected ? const Color(0xFF0D47A1) : Colors.grey, - fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, - )), - ], - ), - ); - } - - Widget _buildEnterpriseList() { - return Expanded( - child: ListView.builder( - padding: const EdgeInsets.only(top: 8), - itemCount: filteredEnterprises.length, - itemBuilder: (context, index) { - final enterprise = filteredEnterprises[index]; - return _buildEnterpriseCard(enterprise); - }, - ), - ); - } - - Widget _buildEnterpriseCard(Map enterprise) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.1), - blurRadius: 8, - offset: const Offset(0, 4), - ) - ], - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - enterprise['name']!, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: enterprise['status'] == '已划分' - ? const Color(0xFF4CAF50).withOpacity(0.1) - : const Color(0xFFF44336).withOpacity(0.1), - borderRadius: BorderRadius.circular(4), - border: Border.all( - color: enterprise['status'] == '已划分' - ? const Color(0xFF4CAF50) - : const Color(0xFFF44336), - width: 1, - ), - ), - child: Text( - enterprise['status']!, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: enterprise['status'] == '已划分' - ? const Color(0xFF4CAF50) - : const Color(0xFFF44336), - ), - ), - ), - ], - ), - const SizedBox(height: 12), - Row( - children: [ - const Icon(Icons.business, size: 16, color: Colors.grey), - const SizedBox(width: 8), - Text( - '安全监管类型: ${enterprise['type']}', - style: const TextStyle(fontSize: 14, color: Colors.grey), - ), - ], - ), - const SizedBox(height: 8), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(Icons.people, size: 16, color: Colors.grey), - const SizedBox(width: 8), - Expanded( - child: Text( - '管理单位: ${enterprise['unit']}', - style: const TextStyle(fontSize: 14, color: Colors.grey), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - // 查看详情 - }, - style: TextButton.styleFrom( - foregroundColor: const Color(0xFF0D47A1), - ), - child: const Text('查看详情'), - ), - const SizedBox(width: 8), - ElevatedButton( - onPressed: () { - // 处理操作 - }, - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0D47A1), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - ), - child: const Text('处理', style: TextStyle(color: Colors.white)), - ), - ], - ), - ], - ), - ), - ); - } -} - diff --git a/lib/home/home_page.dart b/lib/home/home_page.dart index 6896961..b0044a4 100644 --- a/lib/home/home_page.dart +++ b/lib/home/home_page.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; + class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @@ -98,7 +99,8 @@ class _HomePageState extends State { alignment: const FractionalOffset(0.5, 1), children: [ Padding( - padding: EdgeInsetsGeometry.fromLTRB(0, 0, 0, 150), + // padding: EdgeInsetsGeometry.fromLTRB(0, 0, 0, 150), + padding: EdgeInsets.only(bottom: 150), child: Image.asset( "assets/images/banner.png", width: MediaQuery.of(context).size.width, // 获取屏幕宽度 @@ -137,12 +139,12 @@ class _HomePageState extends State { mainAxisSpacing: 16, // childAspectRatio: 1.5, children: [ - _buildStatCard('企业信息', "assets/images/ico1.png"), - _buildStatCard('双重预防', "assets/images/ico2.png"), - _buildStatCard('重点安全', "assets/images/ico4.png"), - _buildStatCard('监管帮扶', "assets/images/ico9.png"), - _buildStatCard('专项检查', "assets/images/ico8.png"), - _buildStatCard('防灾减灾', "assets/images/ico10.png"), + _buildStatCard(1,'企业信息', "assets/images/ico1.png"), + _buildStatCard(2,'双重预防', "assets/images/ico2.png"), + _buildStatCard(3,'重点安全', "assets/images/ico4.png"), + _buildStatCard(4,'监管帮扶', "assets/images/ico9.png"), + _buildStatCard(5,'专项检查', "assets/images/ico8.png"), + _buildStatCard(6,'防灾减灾', "assets/images/ico10.png"), ], @@ -150,8 +152,28 @@ class _HomePageState extends State { ); } - Widget _buildStatCard(String title, String icon ){ - return Column( + Widget _buildStatCard(int id,String title, String icon ){ + return GestureDetector( + onTap: () { + if(1==id){ + // Navigator.pushReplacement( + // context, + // MaterialPageRoute(builder: (context) => const DangerPage()), + // ); + }else if(2==id){ + + }else if(3==id){ + + }else if(4==id){ + + }else if(5==id){ + + }else if(6==id){ + + } + + }, + child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Container( @@ -165,13 +187,14 @@ class _HomePageState extends State { // ), // const SizedBox(height: 12), Padding( - padding: EdgeInsetsGeometry.fromLTRB(0,5,0,0), + // padding: EdgeInsetsGeometry.fromLTRB(0,5,0,0), + padding: EdgeInsets.only(top: 5), child: Text(title, style: const TextStyle(fontSize: 16)) ) ], - + ), ); } diff --git a/lib/mine/change_pass_page.dart b/lib/mine/change_pass_page.dart new file mode 100644 index 0000000..ac0f9bf --- /dev/null +++ b/lib/mine/change_pass_page.dart @@ -0,0 +1,232 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:qhdkfq_regulatory_flutter/tools/my_appbar.dart'; + +class ChangePassPage extends StatefulWidget { + const ChangePassPage({super.key}); + + @override + _ChangePassPageState createState() => _ChangePassPageState(); +} + +class _ChangePassPageState extends State + with SingleTickerProviderStateMixin { + + + final _formKey = GlobalKey(); + bool _obscureCurrentPassword = true; + bool _obscureNewPassword = true; + bool _obscureConfirmPassword = true; + + final TextEditingController _currentPasswordController = TextEditingController(); + final TextEditingController _newPasswordController = TextEditingController(); + final TextEditingController _confirmPasswordController = TextEditingController(); + + @override + void dispose() { + _currentPasswordController.dispose(); + _newPasswordController.dispose(); + _confirmPasswordController.dispose(); + super.dispose(); + } + + void _submitForm() { + if (_formKey.currentState!.validate()) { + // 表单验证通过,处理密码修改逻辑 + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('密码修改成功!'), + backgroundColor: Colors.green, + ), + ); + // 模拟处理延迟 + Future.delayed(const Duration(seconds: 1), () { + Navigator.pop(context); + }); + } + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "修改密码"), + body: Padding( + padding: const EdgeInsets.all(10.0), + + child: SingleChildScrollView( + padding: const EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + + // 表单区域 + Form( + key: _formKey, + child: Column( + children: [ + // 原密码 + _buildPasswordField( + label: '原密码', + controller: _currentPasswordController, + obscureText: _obscureCurrentPassword, + onToggleVisibility: () { + setState(() { + _obscureCurrentPassword = !_obscureCurrentPassword; + }); + }, + validator: (value) { + if (value == null || value.isEmpty) { + return '请输入原密码'; + } + if (value.length < 6) { + return '密码长度至少为6位'; + } + return null; + }, + ), + + const SizedBox(height: 35), + + + // 新密码 + _buildPasswordField( + label: '新密码', + controller: _newPasswordController, + obscureText: _obscureNewPassword, + onToggleVisibility: () { + setState(() { + _obscureNewPassword = !_obscureNewPassword; + }); + }, + validator: (value) { + if (value == null || value.isEmpty) { + return '请输入新密码'; + } + if (value.length < 6) { + return '密码长度至少为6位'; + } + if (!RegExp(r'[A-Z]').hasMatch(value)) { + return '需包含大写字母'; + } + if (!RegExp(r'[0-9]').hasMatch(value)) { + return '需包含数字'; + } + return null; + }, + ), + const SizedBox(height: 35), + + // 确认新密码 + _buildPasswordField( + label: '确认新密码', + controller: _confirmPasswordController, + obscureText: _obscureConfirmPassword, + onToggleVisibility: () { + setState(() { + _obscureConfirmPassword = !_obscureConfirmPassword; + }); + }, + validator: (value) { + if (value == null || value.isEmpty) { + return '请确认新密码'; + } + if (value != _newPasswordController.text) { + return '两次输入的密码不一致'; + } + return null; + }, + ), + const SizedBox(height: 40), + + // 确定按钮 + SizedBox( + width: double.infinity, + height: 54, + child: ElevatedButton( + onPressed: _submitForm, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF2196F3), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 0, + ), + child: const Text( + '确定', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white), + ), + ), + ), + ], + ), + ), + ], + ), + ), + + + ), + ); + } + + Widget _buildPasswordField({ + required String label, + required TextEditingController controller, + required bool obscureText, + required VoidCallback onToggleVisibility, + required String? Function(String?)? validator, + }) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标签和星号 + Row( + children: [ + const Text( + '*', + style: TextStyle( + fontSize: 16, + color: Colors.red, + ), + ), + const SizedBox(width: 4), + Text( + label, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Color(0xFF333333)), + ), + ], + ), + // const SizedBox(height: 8), + + // 密码输入框 + TextFormField( + controller: controller, + obscureText: obscureText, + validator: validator, + decoration: InputDecoration( + hintText: '请输入$label', + hintStyle: const TextStyle(color: Color(0xFF999999)), + contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 12), + // suffixIcon: IconButton( + // icon: Icon( + // obscureText ? Icons.visibility_off : Icons.visibility, + // color: const Color(0xFF999999), + // ), + // onPressed: onToggleVisibility, + // ), + ), + ), + ], + ); + } +} + diff --git a/lib/mine/message_detail_page.dart b/lib/mine/message_detail_page.dart new file mode 100644 index 0000000..c61b21d --- /dev/null +++ b/lib/mine/message_detail_page.dart @@ -0,0 +1,115 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:qhdkfq_regulatory_flutter/tools/my_appbar.dart'; + +class MessageDetailPage extends StatefulWidget { + const MessageDetailPage({super.key}); + + @override + _MessageDetailPageState createState() => _MessageDetailPageState(); +} + +class _MessageDetailPageState extends State + with SingleTickerProviderStateMixin { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "通知详情"), + body: Padding( + padding: const EdgeInsets.all(16.0), + // child: Center( + child: NotificationDetailCard(), + // ), + ), + ); + } +} + +class NotificationDetailCard extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Card( + elevation: 4, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + + // 通知类型 + const Text( + '会议任务下发提醒', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Color(0xFF333333), + ), + ), + const SizedBox(height: 16), + + // 提醒时间 + _buildInfoRow('提醒时间:', '2025-05-30 10:07:42'), + const SizedBox(height: 12), + + // 提醒人 + _buildInfoRow('提醒人:', '王朋'), + const SizedBox(height: 12), + + // // 分隔线 + // const Divider(height: 1, color: Color(0xFFEEEEEE)), + // const SizedBox(height: 24), + + // 提醒内容 + const Text( + '提醒内容:', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Color(0xFF333333), + ), + ), + const SizedBox(height: 12), + + // 详细内容 + const Text( + '温馨提示,任务名称为阿斯顿,行动周期2025-05-01至2025-05-31的会议任务已下发,请及时进行会议反馈。', + style: TextStyle( + fontSize: 16, + height: 1.5, + color: Color(0xFF666666), + ), + ), + const SizedBox(height: 32), + ], + ), + ), + ); + } + + Widget _buildInfoRow(String label, String value) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: const TextStyle(fontSize: 16, color: Color(0xFF666666)), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + value, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Color(0xFF333333), + ), + ), + ), + ], + ); + } +} diff --git a/lib/mine/message_page.dart b/lib/mine/message_page.dart new file mode 100644 index 0000000..479bc9a --- /dev/null +++ b/lib/mine/message_page.dart @@ -0,0 +1,252 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:qhdkfq_regulatory_flutter/mine/message_detail_page.dart'; +import 'package:qhdkfq_regulatory_flutter/tools/my_appbar.dart'; +import 'package:qhdkfq_regulatory_flutter/tools/tools.dart'; + + +class MessagePage extends StatefulWidget { + const MessagePage({super.key}); + + @override + _MessagePageState createState() => _MessagePageState(); +} + +class _MessagePageState extends State + with SingleTickerProviderStateMixin { + + final List notifications = [ + NotificationItem( + type: '会议任务下发提醒', + isRead: false, + time: '2025-05-30 10:07:42', + title: '阿斯顿', + period: '行动周期2025-05-...', + ), + NotificationItem( + type: '学习任务下发提醒', + isRead: false, + time: '2025-05-30 10:05:30', + title: '测试附件', + period: '行动周期2025-0-...', + ), + NotificationItem( + type: '学习任务下发提醒', + isRead: false, + time: '2025-05-26 14:07:46', + title: '0526-1', + period: '行动周期2025-05-...', + ), + NotificationItem( + type: '会议任务下发提醒', + isRead: false, + time: '2025-04-23 17:43:35', + title: '测试423', + period: '行动周期2025-0-...', + ), + NotificationItem( + type: '学习任务下发提醒', + isRead: false, + time: '2025-04-23 17:40:44', + title: '测试4.23', + period: '行动周期2025-0-...', + ), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "通知提醒"), + body: + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 10,), + Container( + width: MediaQuery.of(context).size.width, // 获取屏幕宽度 + margin: EdgeInsets.only(left: 15,right: 15), + decoration: BoxDecoration( + color: Colors.green, + borderRadius: BorderRadius.circular(6), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 2, + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + padding: EdgeInsets.all(10), + child: + GestureDetector( + onTap: () { + setState(() { + for (int i = 0; i < notifications.length; i++) { + notifications[i].isRead = true; + } + }); + }, + + child: Text( + "一键已读", + textAlign:TextAlign.center, + style: TextStyle( + fontSize: 13, + + color: Colors.white, + + ) , + ), + ) + + ), + + + Expanded( + child: ListView.builder( + itemCount: notifications.length, + itemBuilder: (context, index) { + final notification = notifications[index]; + return NotificationCard(item: notification); + }, + ), + ) + + ], + ), + + + + ); + } +} + +class NotificationItem { + String type; + bool isRead; + String time; + String title; + String period; + + NotificationItem({ + required this.type, + required this.isRead, + required this.time, + required this.title, + required this.period, + }); +} + +class NotificationCard extends StatelessWidget { + final NotificationItem item; + + const NotificationCard({super.key, required this.item}); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: const BorderSide(color: Color(0xFFEEEEEE), width: 1), + ), + child: Padding( + padding: const EdgeInsets.only(left: 16,top: 16,right: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + item.type, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: item.isRead ? const Color(0xFFF5F5F5) : Colors.blue[50], + borderRadius: BorderRadius.circular(10), + ), + child: Text( + item.isRead ? '已读' : '未读', + style: TextStyle( + color: item.isRead ? Colors.grey : Colors.blue, + fontSize: 12, + ), + ), + ), + ], + ), + const SizedBox(height: 8), + Text( + '提醒时间: ${item.time}', + style: const TextStyle(color: Colors.grey, fontSize: 14), + ), + const SizedBox(height: 12), + RichText( + text: TextSpan( + style: DefaultTextStyle.of(context).style, + children: [ + const TextSpan( + text: '温馨提示,任务名称为', + style: TextStyle(fontSize: 14), + ), + TextSpan( + text: item.title, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: Colors.black + ), + ), + TextSpan( + text: item.period, + style: const TextStyle(fontSize: 14), + ), + ], + ), + ), + // const SizedBox(height: 8), + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: () { + pushPage(MessageDetailPage(), context); + }, + style: TextButton.styleFrom( + // padding: EdgeInsets.only(bottom: 0), + minimumSize: Size.zero, + ), + child: const Text( + '查看详情', + style: TextStyle(color: Colors.blue), + ), + ), + ), + ], + ), + ), + ); + } +} + + + + + + + + + + + + + diff --git a/lib/mine/mine_page.dart b/lib/mine/mine_page.dart index 3d8145c..dae0ae1 100644 --- a/lib/mine/mine_page.dart +++ b/lib/mine/mine_page.dart @@ -1,4 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:qhdkfq_regulatory_flutter/mine/change_pass_page.dart'; +import 'package:qhdkfq_regulatory_flutter/mine/message_page.dart'; +import 'package:qhdkfq_regulatory_flutter/tools/tools.dart'; + class MinePage extends StatefulWidget { const MinePage({super.key}); @@ -7,31 +11,7 @@ class MinePage extends StatefulWidget { State createState() => _MinePageState(); } - class _MinePageState extends State { - - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - title: '安全设置', - theme: ThemeData( - primarySwatch: Colors.blue, - scaffoldBackgroundColor: const Color(0xFFF5F7FA), - ), - home: const SafetySettingsPage(), - ); - } -} - -class SafetySettingsPage extends StatefulWidget { - const SafetySettingsPage({super.key}); - - @override - State createState() => _SafetySettingsPageState(); -} - -class _SafetySettingsPageState extends State { // 设置项状态 bool notificationsEnabled = false; bool passwordChanged = false; @@ -186,6 +166,7 @@ class _SafetySettingsPageState extends State { title: "通知提醒", icon: "assets/images/i2.png", value: notificationsEnabled, + num:1, onChanged: (value) => setState(() => notificationsEnabled = value!), ), // const Divider(height: 1, indent: 60), @@ -195,6 +176,7 @@ class _SafetySettingsPageState extends State { title: "修改密码", icon: "assets/images/i3.png", value: passwordChanged, + num:2, onChanged: (value) => setState(() => passwordChanged = value!), ), // const Divider(height: 1, indent: 60), @@ -204,6 +186,7 @@ class _SafetySettingsPageState extends State { title: "版本更新", icon: "assets/images/i5.png", value: updateAvailable, + num:3, onChanged: (value) => setState(() => updateAvailable = value!), ), // const Divider(height: 1, indent: 60), @@ -213,11 +196,12 @@ class _SafetySettingsPageState extends State { title: "退出登录", icon: "assets/images/i4.png", value: logoutSelected, + num:4, onChanged: (value) { setState(() => logoutSelected = value!); - if (value == true) { - _showLogoutConfirmation(); - } + // if (value == true) { + // _showLogoutConfirmation(); + // } }, ), ], @@ -229,33 +213,55 @@ class _SafetySettingsPageState extends State { required String title, required String icon, required bool value, + required int num, required ValueChanged onChanged, }) { - return ListTile( - leading: Container( - width: 20, - height: 20, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - ), - child: Image.asset(icon ,fit: BoxFit.cover, ), - ), - title: Text( - title, - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), - ), + return + GestureDetector( + onTap: () { + switch(num){ + case 1: + pushPage(MessagePage(), context); + break; + case 2: + pushPage(ChangePassPage(), context); + break; + case 3: - trailing: Transform.scale( - scale: 1.2, - child: Image.asset( - "assets/images/right.png", - fit: BoxFit.cover, - width: 15, - height: 15, + break; + case 4: + _showLogoutConfirmation(); + break; + + } + }, + child: ListTile( + leading: Container( + width: 20, + height: 20, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + ), + child: Image.asset(icon ,fit: BoxFit.cover, ), + ), + title: Text( + title, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), + ), + + trailing: Transform.scale( + scale: 1.2, + child: Image.asset( + "assets/images/right.png", + fit: BoxFit.cover, + width: 15, + height: 15, + ), + ), ), - ), - ); + ); + } Widget _buildActionButton() { @@ -301,15 +307,19 @@ class _SafetySettingsPageState extends State { context: context, builder: (context) => AlertDialog( title: const Text("退出登录"), - content: const Text("确定要退出当前账号吗?"), + content: const Text("确定要退出登录吗?"), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), actions: [ - TextButton( + ElevatedButton( onPressed: () { setState(() => logoutSelected = false); Navigator.pop(context); }, - child: const Text("取消"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.grey[400], + foregroundColor: Colors.white, + ), + child: const Text(" 取消 "), ), ElevatedButton( onPressed: () { diff --git a/lib/tools/SmallWidget.dart b/lib/tools/SmallWidget.dart new file mode 100644 index 0000000..73df7b0 --- /dev/null +++ b/lib/tools/SmallWidget.dart @@ -0,0 +1,25 @@ +import 'dart:ffi'; + +import 'package:flutter/material.dart'; + +import 'h_colors.dart'; +/// 标签(eg:风险等级) +Widget riskTagText(int level, String title) { + + final List colors = riskLevelTextColors(); + if (colors.length <= (level - 1)) { + return SizedBox(); + } + return Container( + padding: EdgeInsets.symmetric(vertical: 3, horizontal: 5), + decoration: BoxDecoration( + color: colors[level-1], + borderRadius: const BorderRadius.all(Radius.circular(5)), + ), + // color: Colors., + child: Text( + title, + style: TextStyle(color: Colors.white, fontSize: 14), + ), + ); +} \ No newline at end of file diff --git a/lib/tools/h_colors.dart b/lib/tools/h_colors.dart new file mode 100644 index 0000000..a612ddb --- /dev/null +++ b/lib/tools/h_colors.dart @@ -0,0 +1,11 @@ +import 'dart:ffi'; +import 'dart:ui'; + +Color h_backGroundColor() => Color(0xFFFAFAFA); +List riskLevelTextColors() { + return [Color(0xFFE54D42),Color(0xFFF37B1D),Color(0xFFF9BD08),Color(0xFF3281FF)]; +} + +List riskLevelBgColors() { + return [Color(0xFFFADBD9),Color(0xFFFCE6D2),Color(0xFFFDF2CE),Color(0xFFCCE6FF)]; +} diff --git a/lib/tools/my_appbar.dart b/lib/tools/my_appbar.dart new file mode 100644 index 0000000..579e9d0 --- /dev/null +++ b/lib/tools/my_appbar.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'dart:io' show Platform; + +class MyAppbar extends StatelessWidget implements PreferredSizeWidget { + final String title; + final VoidCallback? onBackPressed; + final Color backgroundColor; + final Color textColor; + final List? actions; + final bool isBack; + final bool centerTitle; // 新增:控制标题是否居中 + + const MyAppbar({ + Key? key, + required this.title, + this.onBackPressed, + this.backgroundColor = Colors.blue, + this.textColor = Colors.white, + this.actions, + this.isBack = true, + this.centerTitle = true, // 默认居中 + }) : super(key: key); + + // 根据平台设置不同高度 + @override + Size get preferredSize { + // iOS使用更紧凑的高度(44点),Android保持默认(56点) + return Size.fromHeight(Platform.isIOS ? 44.0 : kToolbarHeight); + } + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: backgroundColor, + automaticallyImplyLeading: false, + centerTitle: centerTitle, + toolbarHeight: preferredSize.height, // 使用计算的高度 + title: Text( + title, + style: TextStyle( + color: textColor, + fontSize: Platform.isIOS ? 17.0 : 18.0, // iOS使用更小字号 + fontWeight: FontWeight.w600, // iOS使用中等字重 + ), + ), + leading: isBack ? _buildBackButton(context) : null, + actions: _buildActions(), + elevation: Platform.isIOS ? 0 : 4, // iOS无阴影 + // iOS添加底部边框 + shape: Platform.isIOS + ? const Border(bottom: BorderSide(color: Colors.black12, width: 0.5)) + : null, + ); + } + + // 返回按钮 + Widget _buildBackButton(BuildContext context) { + return Padding( + padding: EdgeInsets.only(left: Platform.isIOS ? 8.0 : 16.0), + child: IconButton( + icon: Icon( + Platform.isIOS ? Icons.arrow_back_ios : Icons.arrow_back, + color: textColor, + size: Platform.isIOS ? 20.0 : 24.0, // iOS使用更小图标 + ), + padding: EdgeInsets.zero, // 移除默认内边距 + constraints: const BoxConstraints(), // 移除默认约束 + onPressed: onBackPressed ?? () => Navigator.of(context).pop(), + ), + ); + } + + // 右侧按钮间距 + List? _buildActions() { + if (actions == null) return null; + + return [ + Padding( + padding: EdgeInsets.only(right: Platform.isIOS ? 8.0 : 16.0), + child: Row( + mainAxisSize: MainAxisSize.min, + children: actions!, + ), + ) + ]; + } +} \ No newline at end of file diff --git a/lib/tools/tools.dart b/lib/tools/tools.dart new file mode 100644 index 0000000..75d69b6 --- /dev/null +++ b/lib/tools/tools.dart @@ -0,0 +1,134 @@ +import 'dart:ui'; +import 'dart:math'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +int getRandomWithNum(int min, int max) { + final random = Random(); + return random.nextInt(max) + min; // 生成随机数 +} + +double screenWidth(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return screenWidth; +} + +void pushPage(Widget page, BuildContext context) { + Navigator.push(context, MaterialPageRoute(builder: (context) => page)); +} +void present(Widget page, BuildContext context) { + Navigator.push( + context, + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => page, + ), + ); +} +/// 文本样式工具类 +/// 文本样式工具类 +/// 文本样式工具类,返回 Text Widget +class HhTextStyleUtils { + /// 主要标题,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认黑色 + /// [fontSize]: 字体大小,默认16.0 + /// [bold]: 是否加粗,默认true + static Text mainTitle( + String text, { + Color color = Colors.black, + double fontSize = 16.0, + bool bold = true, + }) { + return Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } + static TextStyle secondaryTitleStyle = TextStyle(color:Colors.black54, fontSize: 15.0); + + /// 次要标题,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认深灰 + /// [fontSize]: 字体大小,默认14.0 + /// [bold]: 是否加粗,默认false + static Text secondaryTitle( + String text, { + Color color = Colors.black54, + double fontSize = 14.0, + bool bold = false, + }) { + return Text( + text, + style: TextStyle( + + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } + + /// 小文字,返回 Text + /// [text]: 文本内容 + /// [color]: 文本颜色,默认灰色 + /// [fontSize]: 字体大小,默认12.0 + /// [bold]: 是否加粗,默认false + static Text smallText( + String text, { + Color color = Colors.black54, + double fontSize = 12.0, + bool bold = false, + }) { + return Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); + } +} + +/// 版本信息模型类 +class AppVersionInfo { + final String versionName; // 版本名称(如 1.0.0) + final String buildNumber; // 构建号(如 1) + final String fullVersion; // 完整版本(如 1.0.0+1) + + AppVersionInfo({ + required this.versionName, + required this.buildNumber, + required this.fullVersion, + }); + + @override + String toString() { + return fullVersion; + } +} + +// 获取应用版本信息的方法 +Future getAppVersion() async { + try { + final packageInfo = await PackageInfo.fromPlatform(); + return AppVersionInfo( + versionName: packageInfo.version, + buildNumber: packageInfo.buildNumber, + fullVersion: '${packageInfo.version}+${packageInfo.buildNumber}', + ); + } catch (e) { + // 获取失败时返回默认值 + return AppVersionInfo( + versionName: '1.0.0', + buildNumber: '1', + fullVersion: '1.0.0+0', + ); + } +} \ No newline at end of file