add
This commit is contained in:
@@ -54,14 +54,14 @@ func main() {
|
|||||||
zap.L().Info("✅ 配置跨域中间件完成")
|
zap.L().Info("✅ 配置跨域中间件完成")
|
||||||
|
|
||||||
// 注册品种接口
|
// 注册品种接口
|
||||||
variety := r.Group("/api/variety")
|
variety := r.Group("/variety")
|
||||||
{
|
{
|
||||||
variety.POST("/create", logic4variety.CreateVarietyHandler)
|
variety.POST("/create", logic4variety.CreateVarietyHandler)
|
||||||
}
|
}
|
||||||
zap.L().Info("✅ 品种接口注册完成")
|
zap.L().Info("✅ 品种接口注册完成")
|
||||||
|
|
||||||
// 注册交易所接口
|
// 注册交易所接口
|
||||||
exchangeGroup := r.Group("/api/exchange")
|
exchangeGroup := r.Group("/exchange")
|
||||||
{
|
{
|
||||||
exchangeGroup.POST("/create", logic4exchange.CreateExchangeHandler)
|
exchangeGroup.POST("/create", logic4exchange.CreateExchangeHandler)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,131 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class AddExchangePage extends StatelessWidget {
|
class AddExchangePage extends StatefulWidget {
|
||||||
// 功能列表数据
|
const AddExchangePage({super.key});
|
||||||
final List<Map<String, dynamic>> features = [
|
|
||||||
{'icon': Icons.bar_chart, 'title': '数据分析'},
|
|
||||||
{'icon': Icons.balance, 'title': '交易'},
|
|
||||||
{'icon': Icons.account_balance, 'title': '交易所'},
|
|
||||||
{'icon': Icons.branding_watermark, 'title': '品种'},
|
|
||||||
];
|
|
||||||
|
|
||||||
AddExchangePage({super.key});
|
@override
|
||||||
|
State<AddExchangePage> createState() => _AddExchangePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddExchangePageState extends State<AddExchangePage> {
|
||||||
|
// 输入控制器
|
||||||
|
final TextEditingController _nameController = TextEditingController();
|
||||||
|
final TextEditingController _codeController = TextEditingController();
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
// 表单验证键
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
|
// 创建交易所
|
||||||
|
Future<void> _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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -22,109 +138,70 @@ class AddExchangePage extends StatelessWidget {
|
|||||||
elevation: 4,
|
elevation: 4,
|
||||||
shadowColor: Colors.black12,
|
shadowColor: Colors.black12,
|
||||||
backgroundColor: theme.colorScheme.surfaceContainerHighest,
|
backgroundColor: theme.colorScheme.surfaceContainerHighest,
|
||||||
// 1. 左上角返回按钮及功能实现
|
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: const Icon(Icons.arrow_back),
|
icon: const Icon(Icons.arrow_back),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // 返回上一页
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// 2. 右上角添加按钮(展示功能)
|
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.save),
|
icon: const Icon(Icons.save),
|
||||||
onPressed: () {
|
onPressed: _isLoading ? null : _createExchange,
|
||||||
// 暂为展示功能,可后续添加具体逻辑
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// 使用SafeArea确保内容在安全区域内
|
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
// 移除不必要的Expanded,避免约束冲突
|
|
||||||
child: Container(
|
child: Container(
|
||||||
color: theme.colorScheme.surface,
|
color: theme.colorScheme.surface,
|
||||||
// 让容器占满整个可用空间
|
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: double.infinity,
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
child: ListView.builder(
|
child: Form(
|
||||||
// 修改为ListView.builder
|
key: _formKey,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
child: Column(
|
||||||
itemCount: features.length,
|
children: [
|
||||||
// 优化Web端滚动物理效果,同时支持触摸和鼠标滚动
|
// 交易所名称输入框
|
||||||
physics: const ScrollPhysics(parent: BouncingScrollPhysics()),
|
TextFormField(
|
||||||
itemBuilder: (context, index) {
|
controller: _nameController,
|
||||||
// 构建列表项
|
style: TextStyle(color: theme.colorScheme.onSurface),
|
||||||
Widget item = _buildFeatureItem(
|
decoration: InputDecoration(
|
||||||
context: context,
|
labelText: '交易所名称',
|
||||||
icon: features[index]['icon'],
|
hintText: '请输入交易所名称',
|
||||||
title: features[index]['title'],
|
prefixIcon: Icon(
|
||||||
);
|
Icons.account_balance,
|
||||||
|
color: theme.colorScheme.secondary,
|
||||||
// 在每个列表项下方添加分割线,包括最后一个
|
),
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
item,
|
|
||||||
Divider(
|
|
||||||
height: 1,
|
|
||||||
thickness: 1,
|
|
||||||
indent: 72,
|
|
||||||
endIndent: 16,
|
|
||||||
color: theme.dividerColor,
|
|
||||||
),
|
),
|
||||||
],
|
validator: (value) {
|
||||||
);
|
if (value == null || value.trim().isEmpty) {
|
||||||
},
|
return '请输入交易所名称';
|
||||||
),
|
}
|
||||||
),
|
return null;
|
||||||
),
|
},
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
),
|
),
|
||||||
child: Icon(icon, size: 24, color: theme.colorScheme.secondary),
|
const SizedBox(height: 24),
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
// 交易所代码输入框
|
||||||
Text(
|
TextFormField(
|
||||||
title,
|
controller: _codeController,
|
||||||
style: theme.textTheme.titleMedium?.copyWith(
|
style: TextStyle(color: theme.colorScheme.onSurface),
|
||||||
fontWeight: FontWeight.w500,
|
decoration: InputDecoration(
|
||||||
color: theme.colorScheme.onSurface,
|
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),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user