import 'package:blog_app/utils/http_utils.dart'; import 'package:flutter/material.dart'; import 'package:markdown_widget/config/toc.dart'; import 'package:markdown_widget/widget/markdown.dart'; class MarkdownPage extends StatefulWidget { const MarkdownPage({super.key}); @override State createState() => _MarkdownPageState(); } class _MarkdownPageState extends State { final tocController = TocController(); bool _showToc = false; late String markdownData = ''; Widget _buildTocPanel() => AnimatedOpacity( opacity: _showToc ? 1.0 : 0.0, duration: const Duration(milliseconds: 300), child: Visibility( visible: _showToc, child: Align( alignment: Alignment.bottomRight, child: Container( width: 250, height: 400, margin: const EdgeInsets.only(bottom: 60, right: 60), // 调整位置在按钮左侧 decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 8, offset: const Offset(0, 4), ), ], border: Border.all(color: Colors.grey[300]!), ), child: Column( children: [ // 标题栏 Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[100], borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '目录', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), IconButton( icon: const Icon(Icons.close, size: 20), onPressed: () => setState(() => _showToc = false), ), ], ), ), Expanded(child: TocWidget(controller: tocController)), ], ), ), ), ), ); Widget buildMarkdown() => MarkdownWidget(data: markdownData, tocController: tocController); @override void initState() { super.initState(); // 初始加载数据 _loadData(); } Future _loadData() async { final result = await HttpUtil().get("/condition"); setState(() { markdownData = result[0]['content']; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('文档')), body: Padding( padding: EdgeInsets.all(16), child: Stack( children: [ // 主内容 buildMarkdown(), // 悬浮TOC面板 _buildTocPanel(), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () => setState(() => _showToc = !_showToc), child: Icon(_showToc ? Icons.close : Icons.list), mini: true, backgroundColor: _showToc ? Colors.grey : Theme.of(context).primaryColor, ), ); } }