diff --git a/backend/futures_trade_record/src/main.go b/backend/futures_trade_record/src/main.go index 7b9684b..e4c4050 100644 --- a/backend/futures_trade_record/src/main.go +++ b/backend/futures_trade_record/src/main.go @@ -54,14 +54,14 @@ func main() { zap.L().Info("✅ 配置跨域中间件完成") // 注册品种接口 - variety := r.Group("/api/variety") + variety := r.Group("/variety") { variety.POST("/create", logic4variety.CreateVarietyHandler) } zap.L().Info("✅ 品种接口注册完成") // 注册交易所接口 - exchangeGroup := r.Group("/api/exchange") + exchangeGroup := r.Group("/exchange") { exchangeGroup.POST("/create", logic4exchange.CreateExchangeHandler) } diff --git a/frontend/asset_assistant/lib/pages/exchange_add_page.dart b/frontend/asset_assistant/lib/pages/exchange_add_page.dart index 9bf491f..1fc6300 100644 --- a/frontend/asset_assistant/lib/pages/exchange_add_page.dart +++ b/frontend/asset_assistant/lib/pages/exchange_add_page.dart @@ -1,15 +1,131 @@ import 'package:flutter/material.dart'; +import 'package:dio/dio.dart'; +import 'package:shared_preferences/shared_preferences.dart'; -class AddExchangePage extends StatelessWidget { - // 功能列表数据 - final List> features = [ - {'icon': Icons.bar_chart, 'title': '数据分析'}, - {'icon': Icons.balance, 'title': '交易'}, - {'icon': Icons.account_balance, 'title': '交易所'}, - {'icon': Icons.branding_watermark, 'title': '品种'}, - ]; +class AddExchangePage extends StatefulWidget { + const AddExchangePage({super.key}); - AddExchangePage({super.key}); + @override + State createState() => _AddExchangePageState(); +} + +class _AddExchangePageState extends State { + // 输入控制器 + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _codeController = TextEditingController(); + + // 加载状态 + bool _isLoading = false; + + // 表单验证键 + final _formKey = GlobalKey(); + + // 创建交易所 + Future _createExchange() async { + if (!_formKey.currentState!.validate()) { + return; + } + + setState(() { + _isLoading = true; + }); + + try { + // 获取用户ID + final prefs = await SharedPreferences.getInstance(); + final userId = prefs.getString('user_id'); + if (userId == null) { + if (mounted) { + _showDialog('错误', '请先登录'); + Navigator.pushReplacementNamed(context, '/login'); + } + return; + } + + // 准备请求数据 + const baseUrl = 'https://api.fishestlife.com'; + const path = '/exchange/create'; + final url = '$baseUrl$path'; + + final requestData = { + 'name': _nameController.text.trim(), + 'code': _codeController.text.trim(), + }; + + // 发送请求 + final dio = Dio(); + final response = await dio.post( + url, + data: requestData, + options: Options( + headers: {'Content-Type': 'application/json', 'X-User-ID': userId}, + ), + ); + + // 处理响应 + if (response.statusCode == 200) { + final result = response.data; + if (result['success'] == true) { + if (mounted) { + _showDialog('成功', '交易所创建成功', () { + Navigator.pop(context, true); // 返回并通知上一页刷新 + }); + } + } else { + if (mounted) { + _showDialog('失败', result['message'] ?? '创建失败,请重试'); + } + } + } else { + if (mounted) { + _showDialog('错误', '服务器响应异常: ${response.statusCode}'); + } + } + } on DioException catch (e) { + String errorMessage = '网络请求失败'; + if (e.response != null) { + errorMessage = '请求失败: ${e.response?.statusCode}'; + } else if (e.type == DioExceptionType.connectionTimeout) { + errorMessage = '连接超时,请检查网络'; + } else if (e.type == DioExceptionType.connectionError) { + errorMessage = '网络连接错误'; + } + + if (mounted) { + _showDialog('错误', errorMessage); + } + } catch (e) { + if (mounted) { + _showDialog('错误', '发生未知错误: $e'); + } + } finally { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } + } + + // 显示对话框 + void _showDialog(String title, String content, [VoidCallback? onConfirm]) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(title), + content: Text(content), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + onConfirm?.call(); + }, + child: const Text('确定'), + ), + ], + ), + ); + } @override Widget build(BuildContext context) { @@ -22,109 +138,70 @@ class AddExchangePage extends StatelessWidget { elevation: 4, shadowColor: Colors.black12, backgroundColor: theme.colorScheme.surfaceContainerHighest, - // 1. 左上角返回按钮及功能实现 leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { - Navigator.of(context).pop(); // 返回上一页 + Navigator.of(context).pop(); }, ), - // 2. 右上角添加按钮(展示功能) actions: [ IconButton( icon: const Icon(Icons.save), - onPressed: () { - // 暂为展示功能,可后续添加具体逻辑 - }, + onPressed: _isLoading ? null : _createExchange, ), ], ), - // 使用SafeArea确保内容在安全区域内 body: SafeArea( - // 移除不必要的Expanded,避免约束冲突 child: Container( color: theme.colorScheme.surface, - // 让容器占满整个可用空间 width: double.infinity, - height: double.infinity, - child: ListView.builder( - // 修改为ListView.builder - padding: const EdgeInsets.symmetric(vertical: 8), - itemCount: features.length, - // 优化Web端滚动物理效果,同时支持触摸和鼠标滚动 - physics: const ScrollPhysics(parent: BouncingScrollPhysics()), - itemBuilder: (context, index) { - // 构建列表项 - Widget item = _buildFeatureItem( - context: context, - icon: features[index]['icon'], - title: features[index]['title'], - ); - - // 在每个列表项下方添加分割线,包括最后一个 - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - item, - Divider( - height: 1, - thickness: 1, - indent: 72, - endIndent: 16, - color: theme.dividerColor, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Form( + key: _formKey, + child: Column( + children: [ + // 交易所名称输入框 + TextFormField( + controller: _nameController, + style: TextStyle(color: theme.colorScheme.onSurface), + decoration: InputDecoration( + labelText: '交易所名称', + hintText: '请输入交易所名称', + prefixIcon: Icon( + Icons.account_balance, + color: theme.colorScheme.secondary, + ), ), - ], - ); - }, - ), - ), - ), - ); - } - - Widget _buildFeatureItem({ - required BuildContext context, - required IconData icon, - required String title, - }) { - final theme = Theme.of(context); - - return Material( - color: Colors.transparent, - child: InkWell( - onTap: () { - // 点击事件可以在这里添加 - }, - borderRadius: BorderRadius.circular(8), - splashColor: theme.colorScheme.primary.withAlpha(26), // 0.1透明度的alpha值 - highlightColor: theme.colorScheme.primary.withAlpha( - 13, - ), // 0.05透明度的alpha值 - child: Container( - height: 64, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - children: [ - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainerHighest, - borderRadius: BorderRadius.circular(8), + validator: (value) { + if (value == null || value.trim().isEmpty) { + return '请输入交易所名称'; + } + return null; + }, ), - child: Icon(icon, size: 24, color: theme.colorScheme.secondary), - ), - const SizedBox(width: 16), - Text( - title, - style: theme.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w500, - color: theme.colorScheme.onSurface, + const SizedBox(height: 24), + + // 交易所代码输入框 + TextFormField( + controller: _codeController, + style: TextStyle(color: theme.colorScheme.onSurface), + decoration: InputDecoration( + labelText: '交易所代码', + hintText: '请输入交易所代码', + prefixIcon: Icon( + Icons.code, + color: theme.colorScheme.secondary, + ), + ), + validator: (value) { + if (value == null || value.trim().isEmpty) { + return '请输入交易所代码'; + } + return null; + }, ), - ), - const Spacer(), - Icon(Icons.arrow_forward_ios, size: 18, color: theme.hintColor), - ], + ], + ), ), ), ),