111
This commit is contained in:
@@ -41,6 +41,12 @@ class ApiEndpoints {
|
||||
/// 搜索幣種
|
||||
static const String coinSearch = '/api/market/search';
|
||||
|
||||
/// 訂單簿深度
|
||||
static const String marketDepth = '/api/market/depth';
|
||||
|
||||
/// 客服联系
|
||||
static const String customerService = '/api/market/customer-service';
|
||||
|
||||
// ==================== 交易模塊 ====================
|
||||
|
||||
/// 買入
|
||||
@@ -55,6 +61,9 @@ class ApiEndpoints {
|
||||
/// 獲取訂單詳情
|
||||
static const String tradeOrderDetail = '/api/trade/order/detail';
|
||||
|
||||
/// 撤销限价委托
|
||||
static const String tradeCancel = '/api/trade/cancel';
|
||||
|
||||
// ==================== 資產模塊 ====================
|
||||
|
||||
/// 獲取資產總覽
|
||||
|
||||
@@ -23,7 +23,6 @@ class DioClient {
|
||||
DioClient() {
|
||||
_dio = _createDio();
|
||||
_setupInterceptors();
|
||||
debugPrint('DioClient initialized with baseUrl: ${NetworkConfig.baseUrl}');
|
||||
}
|
||||
|
||||
Dio _createDio() {
|
||||
@@ -100,7 +99,6 @@ class DioClient {
|
||||
// 注意:不再自動清除用戶數據,避免誤判
|
||||
// 只有在 HTTP 401 時才清除用戶數據
|
||||
if (apiResponse.isUnauthorized) {
|
||||
debugPrint('業務層未授權響應: ${apiResponse.message}');
|
||||
// 不再自動調用 onUnauthorized,避免刷新時誤判
|
||||
// onUnauthorized?.call();
|
||||
}
|
||||
@@ -110,15 +108,6 @@ class DioClient {
|
||||
}
|
||||
|
||||
ApiResponse<T> _handleError<T>(DioException e) {
|
||||
// 詳細錯誤日誌
|
||||
debugPrint('=== Network Error ===');
|
||||
debugPrint('Type: ${e.type}');
|
||||
debugPrint('Message: ${e.message}');
|
||||
debugPrint('URL: ${e.requestOptions.uri}');
|
||||
debugPrint('StatusCode: ${e.response?.statusCode}');
|
||||
debugPrint('ResponseData: ${e.response?.data}');
|
||||
debugPrint('====================');
|
||||
|
||||
if (_isUnauthorized(e)) {
|
||||
_clearUserData();
|
||||
onUnauthorized?.call();
|
||||
@@ -165,32 +154,16 @@ class DioClient {
|
||||
class _LoggingInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ REQUEST: ${options.method} ${options.uri}');
|
||||
debugPrint('│ Headers: ${options.headers}');
|
||||
if (options.data != null) {
|
||||
debugPrint('│ Data: ${options.data}');
|
||||
}
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onRequest(options, handler);
|
||||
}
|
||||
|
||||
@override
|
||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ RESPONSE: ${response.statusCode} ${response.requestOptions.uri}');
|
||||
debugPrint('│ Data: ${response.data}');
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onResponse(response, handler);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ ERROR: ${err.type} ${err.requestOptions.uri}');
|
||||
debugPrint('│ Message: ${err.message}');
|
||||
debugPrint('│ StatusCode: ${err.response?.statusCode}');
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onError(err, handler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class DomainNavigator {
|
||||
static Future<String> init() async {
|
||||
if (kDebugMode) {
|
||||
_activeUrl = _debugUrl;
|
||||
debugPrint('[DomainNavigator] Debug mode, use: $_activeUrl');
|
||||
return _activeUrl;
|
||||
}
|
||||
|
||||
@@ -47,11 +46,9 @@ class DomainNavigator {
|
||||
final ok = await _quickCheck(cached);
|
||||
if (ok) {
|
||||
_activeUrl = cached;
|
||||
debugPrint('[DomainNavigator] Cache hit: $_activeUrl');
|
||||
return _activeUrl;
|
||||
}
|
||||
// 缓存验证失败但不删除,作为后续兜底
|
||||
debugPrint('[DomainNavigator] Cache check failed, keeping as fallback: $cached');
|
||||
}
|
||||
|
||||
// 竞速请求导航地址
|
||||
@@ -61,7 +58,6 @@ class DomainNavigator {
|
||||
// 缓存到本地
|
||||
await LocalStorage.setString(_cachedDomainKey, _activeUrl);
|
||||
|
||||
debugPrint('[DomainNavigator] Resolved: $_activeUrl');
|
||||
return _activeUrl;
|
||||
}
|
||||
|
||||
@@ -75,18 +71,15 @@ class DomainNavigator {
|
||||
|
||||
if (result.isNotEmpty) return result;
|
||||
} catch (_) {
|
||||
debugPrint('[DomainNavigator] Race resolve timeout or failed');
|
||||
}
|
||||
|
||||
// 所有导航失败,尝试使用上次缓存
|
||||
final cached = LocalStorage.getString(_cachedDomainKey);
|
||||
if (cached != null && cached.isNotEmpty) {
|
||||
debugPrint('[DomainNavigator] All nav failed, use cache: $cached');
|
||||
return cached;
|
||||
}
|
||||
|
||||
// 没有缓存,返回空字符串(应用会显示网络错误)
|
||||
debugPrint('[DomainNavigator] All nav failed, no cache available');
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -113,7 +106,7 @@ class DomainNavigator {
|
||||
if (url.startsWith('http')) return url;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return 'https://admin.doskrleti.com';
|
||||
}
|
||||
|
||||
/// 快速检查域名是否可达(3s 超时)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'app_color_scheme.dart';
|
||||
import 'app_spacing.dart';
|
||||
import 'app_theme_extension.dart';
|
||||
|
||||
const String _kFontFamily = 'Inter';
|
||||
|
||||
/// "The Kinetic Vault" & "The Ethereal Terminal" 主題配置
|
||||
class AppTheme {
|
||||
AppTheme._();
|
||||
@@ -19,6 +20,7 @@ class AppTheme {
|
||||
scaffoldBackgroundColor: AppColorScheme.darkBackground,
|
||||
primaryColor: AppColorScheme.darkPrimary,
|
||||
colorScheme: AppColorScheme.darkMaterial,
|
||||
fontFamily: _kFontFamily,
|
||||
extensions: <ThemeExtension<dynamic>>[
|
||||
AppThemeColors.dark(),
|
||||
],
|
||||
@@ -30,7 +32,7 @@ class AppTheme {
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
titleTextStyle: GoogleFonts.inter(
|
||||
titleTextStyle: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.darkOnSurface,
|
||||
@@ -84,7 +86,7 @@ class AppTheme {
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
elevation: 0,
|
||||
textStyle: GoogleFonts.inter(
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@@ -125,6 +127,7 @@ class AppTheme {
|
||||
scaffoldBackgroundColor: AppColorScheme.lightBackground,
|
||||
primaryColor: AppColorScheme.lightPrimary,
|
||||
colorScheme: AppColorScheme.lightMaterial,
|
||||
fontFamily: _kFontFamily,
|
||||
extensions: <ThemeExtension<dynamic>>[
|
||||
AppThemeColors.light(),
|
||||
],
|
||||
@@ -136,7 +139,7 @@ class AppTheme {
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
centerTitle: true,
|
||||
titleTextStyle: GoogleFonts.inter(
|
||||
titleTextStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColorScheme.lightOnSurface,
|
||||
@@ -190,7 +193,7 @@ class AppTheme {
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
elevation: 0,
|
||||
textStyle: GoogleFonts.inter(
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@@ -234,7 +237,8 @@ class AppTextStyles {
|
||||
// ============================================
|
||||
|
||||
/// D1 - 總資產/餘額 (28px w700) — Pencil $hero-value
|
||||
static TextStyle displayLarge(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle displayLarge(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -243,7 +247,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// D2 - 精選價格 (24px w700) — Pencil 行情卡片價格
|
||||
static TextStyle displayMedium(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle displayMedium(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -251,7 +256,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// D3 - 頁面標題 (22px w700) — Pencil 頁面大標題
|
||||
static TextStyle displaySmall(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle displaySmall(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -263,7 +269,8 @@ class AppTextStyles {
|
||||
// ============================================
|
||||
|
||||
/// 區塊/導航標題 (16px w600) — Pencil $section-title
|
||||
static TextStyle headlineLarge(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle headlineLarge(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -271,7 +278,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 卡片標題/價格/標籤頁 (14px w600) — Pencil $card-title
|
||||
static TextStyle headlineMedium(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle headlineMedium(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -279,7 +287,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 副標題/持倉價值 (13px w500)
|
||||
static TextStyle headlineSmall(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle headlineSmall(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -291,7 +300,8 @@ class AppTextStyles {
|
||||
// ============================================
|
||||
|
||||
/// 主要正文 (13px w400)
|
||||
static TextStyle bodyLarge(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle bodyLarge(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -299,7 +309,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 次要正文/副標題 (12px w400) — Pencil $subtitle
|
||||
static TextStyle bodyMedium(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle bodyMedium(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -307,7 +318,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 輔助文字/幣種全名 (11px w400) — Pencil $small-text
|
||||
static TextStyle bodySmall(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle bodySmall(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
@@ -319,7 +331,8 @@ class AppTextStyles {
|
||||
// ============================================
|
||||
|
||||
/// 按鈕/標籤頁標籤 (12px w500) — Pencil $tab-label
|
||||
static TextStyle labelLarge(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle labelLarge(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -327,7 +340,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 漲跌幅標籤 (11px w500) — Pencil $change-badge
|
||||
static TextStyle labelMedium(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle labelMedium(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
@@ -335,7 +349,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 漲跌幅標籤-粗 (11px w600) — Pencil $change-badge-bold
|
||||
static TextStyle labelSmall(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle labelSmall(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
@@ -347,7 +362,8 @@ class AppTextStyles {
|
||||
// ============================================
|
||||
|
||||
/// 大號數字 (22px w700) - 總資產、餘額
|
||||
static TextStyle numberLarge(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle numberLarge(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -357,7 +373,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 中號數字 (14px w600) - 價格、金額
|
||||
static TextStyle numberMedium(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle numberMedium(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
@@ -366,7 +383,8 @@ class AppTextStyles {
|
||||
);
|
||||
|
||||
/// 小號數字 (12px w500) - 漲跌幅、數量
|
||||
static TextStyle numberSmall(BuildContext context) => GoogleFonts.inter(
|
||||
static TextStyle numberSmall(BuildContext context) => TextStyle(
|
||||
fontFamily: _kFontFamily,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
|
||||
Reference in New Issue
Block a user