feat: UI 系统中心化 + 趋势图重构 + 法律文档 H5 上线

- UI 系统: 新增 design_tokens / module_visuals / app_buttons / app_status_badge / app_toast / ai_content 六个共享模块; 28 个页面接入, SnackBar 全部替换为 AppToast
- 趋势图: 直线折线 + 渐变填充 + 阴影; 去网格线; X 轴日+月份分隔; Y 轴整数刻度最多 4 个; 点击数据点/录入记录显示上方浮层, 选中点变实心
- 法律文档 H5: 后端 wwwroot 托管隐私政策/服务协议/关于/个人信息收集清单/第三方 SDK 清单 + 索引页; Program.cs 启用 UseDefaultFiles + UseStaticFiles
- 其他: auth_provider 登录流程调整; api_client IP 适配; 主页智能体栏间距优化
This commit is contained in:
MingNian
2026-07-08 21:25:07 +08:00
parent 7a93237069
commit 1c020b8ae5
45 changed files with 3480 additions and 1000 deletions

View File

@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.dart';
import '../../core/app_colors.dart';
import '../../core/app_module_visuals.dart';
import '../../core/app_theme.dart';
import '../../core/api_client.dart' show baseUrl;
import '../../core/navigation_provider.dart';
@@ -17,6 +18,13 @@ final reportProvider = NotifierProvider<ReportNotifier, ReportState>(
ReportNotifier.new,
);
Duration? reportAnalysisPollDelay(int attempt) {
if (attempt > 15) return null;
if (attempt <= 2) return const Duration(seconds: 4);
if (attempt <= 5) return const Duration(seconds: 8);
return const Duration(seconds: 12);
}
class ReportState {
final List<ReportItem> reports;
final String? uploadingImage;
@@ -132,6 +140,7 @@ class Indicator {
class ReportNotifier extends Notifier<ReportState> {
Timer? _pollTimer;
int _pollAttempt = 0;
@override
ReportState build() {
@@ -185,12 +194,16 @@ class ReportNotifier extends Notifier<ReportState> {
if (!hasAnalyzing) {
_pollTimer?.cancel();
_pollTimer = null;
_pollAttempt = 0;
return;
}
_pollTimer ??= Timer.periodic(
const Duration(seconds: 4),
(_) => loadReports(),
);
if (_pollTimer != null) return;
final delay = reportAnalysisPollDelay(++_pollAttempt);
if (delay == null) return;
_pollTimer = Timer(delay, () {
_pollTimer = null;
loadReports();
});
}
void fetchReportDetail(String reportId) async {
@@ -354,8 +367,9 @@ class ReportNotifier extends Notifier<ReportState> {
class ReportListPage extends ConsumerWidget {
const ReportListPage({super.key});
static const _reportBlue = Color(0xFF8B5CF6);
static const _reportCyan = Color(0xFF38BDF8);
static const _reportVisual = AppModuleVisuals.report;
static const _reportBlue = AppColors.report;
static const _reportCyan = Color(0xFF60A5FA);
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -407,7 +421,7 @@ class ReportListPage extends ConsumerWidget {
EnterpriseHeader(
title: '报告处理概览',
subtitle: '上传检查报告后自动进行 AI 结构化解读',
icon: Icons.description_outlined,
icon: _reportVisual.icon,
color: _reportBlue,
accent: _reportCyan,
showIcon: false,
@@ -564,11 +578,7 @@ class ReportListPage extends ConsumerWidget {
color: _reportBlue.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(50),
),
child: const Icon(
Icons.description_outlined,
size: 44,
color: _reportBlue,
),
child: Icon(_reportVisual.icon, size: 44, color: _reportBlue),
),
const SizedBox(height: 20),
const Text(
@@ -625,11 +635,7 @@ class ReportListPage extends ConsumerWidget {
color: _reportBlue.withValues(alpha: 0.10),
),
),
child: const Icon(
Icons.description_outlined,
size: 26,
color: _reportBlue,
),
child: Icon(_reportVisual.icon, size: 26, color: _reportBlue),
),
const SizedBox(width: 14),
Expanded(