From b9767339ecc4aa16e27ec91f2df65e40ec780a90 Mon Sep 17 00:00:00 2001 From: jyuesong <425698907@qq.com> Date: Tue, 18 Jan 2022 14:26:56 +0800 Subject: [PATCH] add dependency --- lib/base/http/api.dart | 2 +- lib/base/http/url.dart | 2 +- lib/base/routes.dart | 10 + lib/main.dart | 1 + .../dependencies/add_dependency_page.dart | 171 +++++++++ .../others/dependencies/dependency_page.dart | 351 ++++++++++++++++++ .../dependencies/dependency_viewmodel.dart | 54 +++ .../others/login_log/login_log_page.dart | 31 +- lib/module/others/other_page.dart | 72 ++-- .../others/scripts/script_detail_page.dart | 11 +- lib/module/others/scripts/script_page.dart | 141 ++++--- .../others/task_log/task_log_detail_page.dart | 35 +- lib/module/others/task_log/task_log_page.dart | 121 +++--- lib/module/task/task_page.dart | 1 - lib/module/task/task_viewmodel.dart | 3 - 15 files changed, 790 insertions(+), 216 deletions(-) create mode 100644 lib/module/others/dependencies/add_dependency_page.dart create mode 100644 lib/module/others/dependencies/dependency_page.dart create mode 100644 lib/module/others/dependencies/dependency_viewmodel.dart diff --git a/lib/base/http/api.dart b/lib/base/http/api.dart index a36587a..4956fbd 100644 --- a/lib/base/http/api.dart +++ b/lib/base/http/api.dart @@ -234,7 +234,7 @@ class Api { return await Http.get>( Url.dependencies, { - "type": type, + "type": type.toString(), }, ); } diff --git a/lib/base/http/url.dart b/lib/base/http/url.dart index 661d2b8..0fd55cd 100644 --- a/lib/base/http/url.dart +++ b/lib/base/http/url.dart @@ -19,7 +19,7 @@ class Url { static const enableEnvs = "/api/envs/enable"; static const loginLog = "/api/user/login-log"; static const taskLog = "/api/logs"; - static const taskLogDetail = "/api/logs/code/"; + static const taskLogDetail = "/api/logs/"; static const scripts = "/api/scripts/files"; static const scriptDetail = "/api/scripts/"; static const dependencies = "/api/dependencies"; diff --git a/lib/base/routes.dart b/lib/base/routes.dart index 66df6ca..7ffdb89 100644 --- a/lib/base/routes.dart +++ b/lib/base/routes.dart @@ -5,6 +5,8 @@ import 'package:qinglong_app/module/env/add_env_page.dart'; import 'package:qinglong_app/module/env/env_bean.dart'; import 'package:qinglong_app/module/home/home_page.dart'; import 'package:qinglong_app/module/login/login_page.dart'; +import 'package:qinglong_app/module/others/dependencies/add_dependency_page.dart'; +import 'package:qinglong_app/module/others/dependencies/dependency_page.dart'; import 'package:qinglong_app/module/others/login_log/login_log_page.dart'; import 'package:qinglong_app/module/others/scripts/script_detail_page.dart'; import 'package:qinglong_app/module/others/scripts/script_page.dart'; @@ -17,6 +19,7 @@ class Routes { static const String routeHomePage = "/home/homepage"; static const String routeLogin = "/login"; static const String routeAddTask = "/task/add"; + static const String routeAddDependency = "/task/dependency"; static const String routeAddEnv = "/env/add"; static const String routeConfigEdit = "/config/edit"; static const String routeLoginLog = "/log/login"; @@ -24,6 +27,7 @@ class Routes { static const String routeTaskLogDetail = "/log/taskDetail"; static const String routeScript = "/script"; static const String routeScriptDetail = "/script/detail"; + static const String routeDependency = "/Dependency"; static Route? generateRoute(RouteSettings settings) { switch (settings.name) { @@ -40,6 +44,8 @@ class Routes { } else { return CupertinoPageRoute(builder: (context) => const AddTaskPage()); } + case routeAddDependency: + return CupertinoPageRoute(builder: (context) => const AddDependenyPage()); case routeAddEnv: if (settings.arguments != null) { return CupertinoPageRoute( @@ -68,6 +74,10 @@ class Routes { return CupertinoPageRoute( builder: (context) => const ScriptPage(), ); + case routeDependency: + return CupertinoPageRoute( + builder: (context) => const DependencyPage(), + ); case routeTaskLogDetail: return CupertinoPageRoute( builder: (context) => TaskLogDetailPage( diff --git a/lib/main.dart b/lib/main.dart index 20633dd..845af1e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -52,6 +52,7 @@ class MyApp extends ConsumerWidget { FocusScope.of(context).requestFocus(FocusNode()); }, child: MaterialApp( + locale: const Locale('zh','cn'), navigatorObservers: [getIt()], navigatorKey: navigatorState, theme: ref.watch(themeProvider).currentTheme, diff --git a/lib/module/others/dependencies/add_dependency_page.dart b/lib/module/others/dependencies/add_dependency_page.dart new file mode 100644 index 0000000..40b8508 --- /dev/null +++ b/lib/module/others/dependencies/add_dependency_page.dart @@ -0,0 +1,171 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:qinglong_app/base/http/api.dart'; +import 'package:qinglong_app/base/http/http.dart'; +import 'package:qinglong_app/base/ql_app_bar.dart'; +import 'package:qinglong_app/module/others/dependencies/dependency_viewmodel.dart'; +import 'package:qinglong_app/module/task/task_bean.dart'; +import 'package:qinglong_app/module/task/task_detail/task_detail_bean.dart'; +import 'package:qinglong_app/module/task/task_viewmodel.dart'; +import 'package:qinglong_app/utils/extension.dart'; + +class AddDependenyPage extends ConsumerStatefulWidget { + const AddDependenyPage({ + Key? key, + }) : super(key: key); + + @override + ConsumerState createState() => _AddDependencyPageState(); +} + +class _AddDependencyPageState extends ConsumerState { + final TextEditingController _nameController = TextEditingController(); + + DepedencyEnum depedencyType = DepedencyEnum.NodeJS; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: QlAppBar( + canBack: true, + backCall: () { + Navigator.of(context).pop(); + }, + title: "新增依赖", + actions: [ + InkWell( + onTap: () { + submit(); + }, + child: const Padding( + padding: EdgeInsets.symmetric( + horizontal: 15, + ), + child: Center( + child: Text( + "提交", + style: TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + ), + ), + ) + ], + ), + body: Container( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 10, + ), + const Text( + "依赖类型:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox( + height: 10, + ), + DropdownButtonFormField( + items: [ + DropdownMenuItem( + value: DepedencyEnum.NodeJS, + child: Text(DepedencyEnum.NodeJS.name), + ), + DropdownMenuItem( + value: DepedencyEnum.Python3, + child: Text(DepedencyEnum.Python3.name), + ), + DropdownMenuItem( + value: DepedencyEnum.Linux, + child: Text(DepedencyEnum.Linux.name), + ), + ], + value: DepedencyEnum.NodeJS, + onChanged: (value) { + depedencyType = value!; + }, + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 10, + ), + const Text( + "名称:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox( + height: 10, + ), + TextField( + controller: _nameController, + decoration: const InputDecoration( + contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5), + hintText: "请输入名称", + ), + autofocus: false, + ), + ], + ), + ), + ], + ), + ), + ); + } + + void submit() async { + if (_nameController.text.isEmpty) { + "依赖名称不能为空".toast(); + return; + } + + HttpResponse response = await Api.addDependency( + _nameController.text, + depedencyType.index, + ); + + if (response.success) { + "操作成功".toast(); + ref.read(dependencyProvider).loadData( + depedencyType.name.toLowerCase(), + ); + Navigator.of(context).pop(); + } else { + response.message.toast(); + } + } +} diff --git a/lib/module/others/dependencies/dependency_page.dart b/lib/module/others/dependencies/dependency_page.dart new file mode 100644 index 0000000..a54b145 --- /dev/null +++ b/lib/module/others/dependencies/dependency_page.dart @@ -0,0 +1,351 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:qinglong_app/base/base_state_widget.dart'; +import 'package:qinglong_app/base/ql_app_bar.dart'; +import 'package:qinglong_app/base/routes.dart'; +import 'package:qinglong_app/base/theme.dart'; +import 'package:qinglong_app/base/ui/abs_underline_tabindicator.dart'; +import 'package:qinglong_app/base/ui/menu.dart'; +import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart'; +import 'package:qinglong_app/module/others/dependencies/dependency_viewmodel.dart'; +import 'package:qinglong_app/utils/utils.dart'; + +/// @author NewTab +class DependencyPage extends StatefulWidget { + const DependencyPage({Key? key}) : super(key: key); + + @override + _DependcyPageState createState() => _DependcyPageState(); +} + +class _DependcyPageState extends State with TickerProviderStateMixin { + List types = []; + + TabController? _tabController; + + @override + void initState() { + super.initState(); + + types.add( + DepedencyEnum.NodeJS, + ); + types.add( + DepedencyEnum.Python3, + ); + types.add( + DepedencyEnum.Linux, + ); + _tabController = TabController(length: types.length, vsync: this); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: QlAppBar( + canBack: true, + backCall: () { + Navigator.of(context).pop(); + }, + title: "依赖管理", + actions: [ + InkWell( + onTap: () { + Navigator.of(context).pushNamed( + Routes.routeAddDependency, + ); + }, + child: const Padding( + padding: EdgeInsets.symmetric( + horizontal: 15, + ), + child: Center( + child: Icon( + CupertinoIcons.add, + size: 20, + color: Colors.white, + ), + ), + ), + ), + ], + ), + body: SizedBox( + width: MediaQuery.of(context).size.width, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + TabBar( + controller: _tabController, + tabs: types + .map((e) => Tab( + text: e.name, + )) + .toList(), + isScrollable: true, + indicator: AbsUnderlineTabIndicator( + wantWidth: 20, + borderSide: BorderSide( + color: Theme.of(context).primaryColor, + width: 2, + ), + ), + ), + Expanded( + child: BaseStateWidget( + onReady: (model) { + model.loadData(types[_tabController!.index].name.toLowerCase()); + }, + model: dependencyProvider, + builder: (context, model, child) { + return TabBarView( + controller: _tabController, + children: types.map( + (e) { + List list; + if (e.index == 0) { + list = model.nodeJsList; + } else if (e.index == 1) { + list = model.python3List; + } else { + list = model.linuxList; + } + + return RefreshIndicator( + child: ListView.builder( + itemBuilder: (context, index) { + return DependencyCell(e, list[index]); + }, + itemCount: list.length, + ), + onRefresh: () { + return model.loadData(types[_tabController!.index].name.toLowerCase(), false); + }, + ); + }, + ).toList(), + ); + }, + ), + ), + ], + ), + ), + ); + } +} + +class DependencyCell extends ConsumerWidget { + final DepedencyEnum type; + final DependencyBean bean; + + const DependencyCell(this.type, this.bean, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return ColoredBox( + color: ref.watch(themeProvider).themeColor.settingBgColor(), + child: CupertinoContextMenu( + actions: [ + QLCupertinoContextMenuAction( + child: Text( + bean.status! == 0 ? "安装" : "重新安装", + ), + trailingIcon: CupertinoIcons.ant, + onPressed: () { + Navigator.of(context).pop(); + reInstall(ref, bean.sId); + }, + ), + QLCupertinoContextMenuAction( + child: const Text("查看日志"), + onPressed: () { + Navigator.of(context).pop(); + showLog(ref, bean.sId); + }, + trailingIcon: CupertinoIcons.clock, + ), + QLCupertinoContextMenuAction( + child: const Text("删除"), + onPressed: () { + Navigator.of(context).pop(); + del(ref, bean.sId); + }, + isDestructiveAction: true, + trailingIcon: CupertinoIcons.delete, + ), + ], + previewBuilder: (context, anima, child) { + return IntrinsicWidth( + child: Material( + color: Colors.transparent, + child: Text( + bean.name ?? "", + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 18, + ), + ), + ), + ); + }, + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Material( + color: Colors.transparent, + child: Text( + bean.name ?? "", + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 18, + ), + ), + ), + const SizedBox( + width: 5, + ), + bean.status == 1 + ? Icon( + CupertinoIcons.checkmark_circle, + color: primaryColor, + size: 16, + ) + : (bean.status == 2 + ? const Icon( + CupertinoIcons.clear_circled, + color: Colors.red, + size: 16, + ) + : const SizedBox( + width: 12, + height: 12, + child: CircularProgressIndicator( + strokeWidth: 2, + ), + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Material( + color: Colors.transparent, + child: Text( + (bean.created == null || bean.created == 0) ? "-" : Utils.formatMessageTime(bean.created!), + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + color: ref.watch(themeProvider).themeColor.descColor(), + fontSize: 12, + ), + ), + ), + ), + ), + ], + ), + ], + ), + ), + const Divider( + height: 1, + indent: 15, + ), + ], + ), + ), + ), + ); + } + + void showLog(WidgetRef ref, String? sId) { + WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { + showCupertinoDialog( + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text( + "${bean.name}运行日志", + maxLines: 1, + style: const TextStyle(overflow: TextOverflow.ellipsis), + ), + content: Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), + child: bean.log == null + ? const Center( + child: Text("暂无日志"), + ) + : CupertinoScrollbar( + child: SelectableText( + bean.log!.join("\n"), + ), + ), + ), + actions: [ + CupertinoDialogAction( + child: Text( + "知道了", + style: TextStyle(color: Theme.of(context).primaryColor), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + context: ref as BuildContext); + }); + } + + void reInstall(WidgetRef ref, String? sId) { + ref.read(dependencyProvider).reInstall(type.name.toLowerCase(), sId ?? ""); + } + + void del(WidgetRef ref, String? sId) { + showCupertinoDialog( + context: ref as BuildContext, + builder: (context) => CupertinoAlertDialog( + title: const Text("确认删除"), + content: Text("确认删除依赖 ${bean.name ?? ""} 吗"), + actions: [ + CupertinoDialogAction( + child: const Text("取消"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + CupertinoDialogAction( + child: const Text("确定"), + onPressed: () { + Navigator.of(context).pop(); + ref.read(dependencyProvider).del(type.name.toLowerCase(), sId ?? ""); + }, + ), + ], + ), + ); + } +} diff --git a/lib/module/others/dependencies/dependency_viewmodel.dart b/lib/module/others/dependencies/dependency_viewmodel.dart new file mode 100644 index 0000000..2cb02b7 --- /dev/null +++ b/lib/module/others/dependencies/dependency_viewmodel.dart @@ -0,0 +1,54 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:qinglong_app/base/base_viewmodel.dart'; +import 'package:qinglong_app/base/http/api.dart'; +import 'package:qinglong_app/base/http/http.dart'; +import 'package:qinglong_app/module/others/dependencies/dependency_bean.dart'; +import 'package:qinglong_app/utils/extension.dart'; + +/// @author NewTab + +var dependencyProvider = ChangeNotifierProvider((ref) => DependencyViewModel()); + +class DependencyViewModel extends BaseViewModel { + List nodeJsList = []; + List python3List = []; + List linuxList = []; + + Future loadData(String type, [bool showLoading = true]) async { + if (showLoading) { + loading(notify: true); + } + + HttpResponse> response = await Api.dependencies(type); + if (response.success) { + if (type == "nodejs") { + nodeJsList.clear(); + nodeJsList.addAll(response.bean!); + } + if (type == "python3") { + python3List.clear(); + python3List.addAll(response.bean!); + } + if (type == "linux") { + linuxList.clear(); + linuxList.addAll(response.bean!); + } + success(); + } else { + response.message?.toast(); + } + } + + void reInstall(String type, String sId) async { + await Api.dependencyReinstall(sId); + loadData(type); + } + + void del(String type, String sId) async { + "删除中...".toast(); + await Api.delDependency(sId); + loadData(type); + } +} + +enum DepedencyEnum { NodeJS, Python3, Linux } diff --git a/lib/module/others/login_log/login_log_page.dart b/lib/module/others/login_log/login_log_page.dart index ade2b66..eea594a 100644 --- a/lib/module/others/login_log/login_log_page.dart +++ b/lib/module/others/login_log/login_log_page.dart @@ -1,11 +1,13 @@ +import 'dart:ui'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/http/api.dart'; import 'package:qinglong_app/base/http/http.dart'; import 'package:qinglong_app/base/ql_app_bar.dart'; import 'package:qinglong_app/base/theme.dart'; +import 'package:qinglong_app/base/ui/lazy_load_state.dart'; import 'package:qinglong_app/utils/extension.dart'; import 'package:qinglong_app/utils/utils.dart'; @@ -19,15 +21,9 @@ class LoginLogPage extends ConsumerStatefulWidget { _LoginLogPageState createState() => _LoginLogPageState(); } -class _LoginLogPageState extends ConsumerState { +class _LoginLogPageState extends ConsumerState with LazyLoadState { List list = []; - @override - void initState() { - super.initState(); - loadData(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -38,7 +34,11 @@ class _LoginLogPageState extends ConsumerState { }, title: "任务日志", ), - body: ListView.builder( + body: list.isEmpty + ? const Center( + child: CupertinoActivityIndicator(), + ) + : ListView.builder( itemBuilder: (context, index) { LoginLogBean item = list[index]; @@ -60,8 +60,10 @@ class _LoginLogPageState extends ConsumerState { const SizedBox( height: 5, ), - Text( + SelectableText( "${item.address}", + selectionWidthStyle: BoxWidthStyle.max, + selectionHeightStyle: BoxHeightStyle.max, style: TextStyle( color: ref.watch(themeProvider).themeColor.descColor(), fontSize: 14, @@ -70,8 +72,10 @@ class _LoginLogPageState extends ConsumerState { const SizedBox( height: 5, ), - Text( + SelectableText( "${item.ip}", + selectionWidthStyle: BoxWidthStyle.max, + selectionHeightStyle: BoxHeightStyle.max, style: TextStyle( color: ref.watch(themeProvider).themeColor.descColor(), fontSize: 14, @@ -109,4 +113,9 @@ class _LoginLogPageState extends ConsumerState { response.message?.toast(); } } + + @override + void onLazyLoad() { + loadData(); + } } diff --git a/lib/module/others/other_page.dart b/lib/module/others/other_page.dart index 454eb95..830b00d 100644 --- a/lib/module/others/other_page.dart +++ b/lib/module/others/other_page.dart @@ -57,10 +57,7 @@ class _OtherPageState extends ConsumerState { Text( "脚本管理", style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), + color: ref.watch(themeProvider).themeColor.taskTitleColor(), fontSize: 16, ), ), @@ -76,29 +73,34 @@ class _OtherPageState extends ConsumerState { const Divider( indent: 15, ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 15, - ), - child: Row( - children: [ - Text( - "依赖管理", - style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 16, + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pushNamed( + Routes.routeDependency, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 15, + ), + child: Row( + children: [ + Text( + "依赖管理", + style: TextStyle( + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 16, + ), ), - ), - const Spacer(), - const Icon( - CupertinoIcons.right_chevron, - size: 16, - ), - ], + const Spacer(), + const Icon( + CupertinoIcons.right_chevron, + size: 16, + ), + ], + ), ), ), const Divider( @@ -121,10 +123,7 @@ class _OtherPageState extends ConsumerState { Text( "任务日志", style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), + color: ref.watch(themeProvider).themeColor.taskTitleColor(), fontSize: 16, ), ), @@ -158,10 +157,7 @@ class _OtherPageState extends ConsumerState { Text( "登录日志", style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), + color: ref.watch(themeProvider).themeColor.taskTitleColor(), fontSize: 16, ), ), @@ -206,10 +202,7 @@ class _OtherPageState extends ConsumerState { Text( "夜间模式", style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), + color: ref.watch(themeProvider).themeColor.taskTitleColor(), fontSize: 16, ), ), @@ -241,8 +234,7 @@ class _OtherPageState extends ConsumerState { ), onPressed: () { getIt().updateToken(""); - Navigator.of(context) - .pushReplacementNamed(Routes.routeLogin); + Navigator.of(context).pushReplacementNamed(Routes.routeLogin); }), ), ), diff --git a/lib/module/others/scripts/script_detail_page.dart b/lib/module/others/scripts/script_detail_page.dart index 0c6e8f4..aa5a0b8 100644 --- a/lib/module/others/scripts/script_detail_page.dart +++ b/lib/module/others/scripts/script_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_highlight/flutter_highlight.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -6,7 +7,6 @@ import 'package:qinglong_app/base/http/http.dart'; import 'package:qinglong_app/base/ql_app_bar.dart'; import 'package:qinglong_app/base/theme.dart'; import 'package:qinglong_app/base/ui/lazy_load_state.dart'; -import 'package:qinglong_app/module/others/task_log/task_log_bean.dart'; import 'package:qinglong_app/utils/extension.dart'; /// @author NewTab @@ -24,8 +24,7 @@ class ScriptDetailPage extends ConsumerStatefulWidget { _ScriptDetailPageState createState() => _ScriptDetailPageState(); } -class _ScriptDetailPageState extends ConsumerState - with LazyLoadState { +class _ScriptDetailPageState extends ConsumerState with LazyLoadState { String? content; @override @@ -38,7 +37,11 @@ class _ScriptDetailPageState extends ConsumerState }, title: "脚本详情", ), - body: SingleChildScrollView( + body:content == null + ? const Center( + child: CupertinoActivityIndicator(), + ) + : SingleChildScrollView( child: HighlightView( content ?? "", language: getLanguageType(widget.title), diff --git a/lib/module/others/scripts/script_page.dart b/lib/module/others/scripts/script_page.dart index da78035..f7c3bbe 100644 --- a/lib/module/others/scripts/script_page.dart +++ b/lib/module/others/scripts/script_page.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/http/api.dart'; @@ -35,82 +36,74 @@ class _ScriptPageState extends ConsumerState { }, title: "脚本管理", ), - body: ListView.builder( - itemBuilder: (context, index) { - ScriptBean item = list[index]; + body: list.isEmpty + ? const Center( + child: CupertinoActivityIndicator(), + ) + : ListView.builder( + itemBuilder: (context, index) { + ScriptBean item = list[index]; - return ColoredBox( - color: ref.watch(themeProvider).themeColor.settingBgColor(), - child: (item.children != null && item.children!.isNotEmpty) - ? ExpansionTile( - title: Text( - item.title ?? "", - style: TextStyle( - color: (item.disabled ?? false) - ? ref.watch(themeProvider).themeColor.descColor() - : ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 16, - ), - ), - children: item.children! - .map((e) => ListTile( - onTap: () { - Navigator.of(context).pushNamed( - Routes.routeScriptDetail, - arguments: { - "title": e.title, - "path": e.parent, - }, - ); + return ColoredBox( + color: ref.watch(themeProvider).themeColor.settingBgColor(), + child: (item.children != null && item.children!.isNotEmpty) + ? ExpansionTile( + title: Text( + item.title ?? "", + style: TextStyle( + color: (item.disabled ?? false) + ? ref.watch(themeProvider).themeColor.descColor() + : ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 16, + ), + ), + children: item.children! + .map((e) => ListTile( + onTap: () { + Navigator.of(context).pushNamed( + Routes.routeScriptDetail, + arguments: { + "title": e.title, + "path": e.parent, + }, + ); + }, + title: Text( + e.title ?? "", + style: TextStyle( + color: (item.disabled ?? false) + ? ref.watch(themeProvider).themeColor.descColor() + : ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 14, + ), + ), + )) + .toList(), + ) + : ListTile( + onTap: () { + Navigator.of(context).pushNamed( + Routes.routeScriptDetail, + arguments: { + "title": item.title, + "path": "", }, - title: Text( - e.title ?? "", - style: TextStyle( - color: (item.disabled ?? false) - ? ref - .watch(themeProvider) - .themeColor - .descColor() - : ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 14, - ), - ), - )) - .toList(), - ) - : ListTile( - onTap: () { - Navigator.of(context).pushNamed( - Routes.routeScriptDetail, - arguments: { - "title": item.title, - "path": "", - }, - ); - }, - title: Text( - item.title ?? "", - style: TextStyle( - color: (item.disabled ?? false) - ? ref.watch(themeProvider).themeColor.descColor() - : ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 16, - ), - ), - ), - ); - }, - itemCount: list.length, - ), + ); + }, + title: Text( + item.title ?? "", + style: TextStyle( + color: (item.disabled ?? false) + ? ref.watch(themeProvider).themeColor.descColor() + : ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 16, + ), + ), + ), + ); + }, + itemCount: list.length, + ), ); } diff --git a/lib/module/others/task_log/task_log_detail_page.dart b/lib/module/others/task_log/task_log_detail_page.dart index 6e074dd..2cacc4c 100644 --- a/lib/module/others/task_log/task_log_detail_page.dart +++ b/lib/module/others/task_log/task_log_detail_page.dart @@ -1,10 +1,10 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/http/api.dart'; import 'package:qinglong_app/base/http/http.dart'; import 'package:qinglong_app/base/ql_app_bar.dart'; -import 'package:qinglong_app/base/theme.dart'; -import 'package:qinglong_app/module/others/task_log/task_log_bean.dart'; +import 'package:qinglong_app/base/ui/lazy_load_state.dart'; import 'package:qinglong_app/utils/extension.dart'; /// @author NewTab @@ -20,15 +20,9 @@ class TaskLogDetailPage extends ConsumerStatefulWidget { _TaskLogDetailPageState createState() => _TaskLogDetailPageState(); } -class _TaskLogDetailPageState extends ConsumerState { +class _TaskLogDetailPageState extends ConsumerState with LazyLoadState { String? content; - @override - void initState() { - super.initState(); - loadData(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -39,14 +33,16 @@ class _TaskLogDetailPageState extends ConsumerState { }, title: "任务日志详情", ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 15, - ), - child: SelectableText( - (content == null || content!.isEmpty) ? "暂无数据" : content!, - ), - ), + body: content == null + ? const Center(child: CupertinoActivityIndicator()) + : Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: SelectableText( + (content == null || content!.isEmpty) ? "暂无数据" : content!, + ), + ), ); } @@ -62,4 +58,9 @@ class _TaskLogDetailPageState extends ConsumerState { response.message?.toast(); } } + + @override + void onLazyLoad() { + loadData(); + } } diff --git a/lib/module/others/task_log/task_log_page.dart b/lib/module/others/task_log/task_log_page.dart index fd10e2f..7f3cfeb 100644 --- a/lib/module/others/task_log/task_log_page.dart +++ b/lib/module/others/task_log/task_log_page.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/http/api.dart'; @@ -5,6 +6,7 @@ import 'package:qinglong_app/base/http/http.dart'; import 'package:qinglong_app/base/ql_app_bar.dart'; import 'package:qinglong_app/base/routes.dart'; import 'package:qinglong_app/base/theme.dart'; +import 'package:qinglong_app/base/ui/lazy_load_state.dart'; import 'package:qinglong_app/module/others/task_log/task_log_bean.dart'; import 'package:qinglong_app/utils/extension.dart'; @@ -16,15 +18,9 @@ class TaskLogPage extends ConsumerStatefulWidget { _TaskLogPageState createState() => _TaskLogPageState(); } -class _TaskLogPageState extends ConsumerState { +class _TaskLogPageState extends ConsumerState with LazyLoadState { List list = []; - @override - void initState() { - super.initState(); - loadData(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -35,64 +31,56 @@ class _TaskLogPageState extends ConsumerState { }, title: "任务日志", ), - body: ListView.builder( - itemBuilder: (context, index) { - TaskLogBean item = list[index]; + body: list.isEmpty + ? const Center( + child: CupertinoActivityIndicator(), + ) + : ListView.builder( + itemBuilder: (context, index) { + TaskLogBean item = list[index]; - return ColoredBox( - color: ref.watch(themeProvider).themeColor.settingBgColor(), - child: (item.isDir ?? false) - ? ExpansionTile( - title: Text( - item.name ?? "", - style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 16, - ), - ), - children: item.files! - .map((e) => ListTile( - onTap: () { - Navigator.of(context).pushNamed( - Routes.routeTaskLogDetail, - arguments: e); - }, - title: Text( - e, - style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 14, - ), - ), - )) - .toList(), - ) - : ListTile( - onTap: () { - Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, - arguments: item.name); - }, - title: Text( - item.name ?? "", - style: TextStyle( - color: ref - .watch(themeProvider) - .themeColor - .taskTitleColor(), - fontSize: 16, - ), - ), - ), - ); - }, - itemCount: list.length, - ), + return ColoredBox( + color: ref.watch(themeProvider).themeColor.settingBgColor(), + child: (item.isDir ?? false) + ? ExpansionTile( + title: Text( + item.name ?? "", + style: TextStyle( + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 16, + ), + ), + children: item.files! + .map((e) => ListTile( + onTap: () { + Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: item.name! + "/" + e); + }, + title: Text( + e, + style: TextStyle( + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 14, + ), + ), + )) + .toList(), + ) + : ListTile( + onTap: () { + Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: item.name); + }, + title: Text( + item.name ?? "", + style: TextStyle( + color: ref.watch(themeProvider).themeColor.taskTitleColor(), + fontSize: 16, + ), + ), + ), + ); + }, + itemCount: list.length, + ), ); } @@ -107,4 +95,9 @@ class _TaskLogPageState extends ConsumerState { response.message?.toast(); } } + + @override + void onLazyLoad() { + loadData(); + } } diff --git a/lib/module/task/task_page.dart b/lib/module/task/task_page.dart index bfbb022..d3b93c7 100644 --- a/lib/module/task/task_page.dart +++ b/lib/module/task/task_page.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_highlight/theme_map.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/base_state_widget.dart'; import 'package:qinglong_app/base/routes.dart'; diff --git a/lib/module/task/task_viewmodel.dart b/lib/module/task/task_viewmodel.dart index 90c05c5..7069c47 100644 --- a/lib/module/task/task_viewmodel.dart +++ b/lib/module/task/task_viewmodel.dart @@ -33,9 +33,6 @@ class TaskViewModel extends BaseViewModel { list.sort((a, b) { return b.created!.compareTo(a.created!); }); - // list.sort((a, b) { - // return b.isPinned!.compareTo(a.isPinned!); - // }); for (int i = 0; i < list.length; i++) { if (list[i].isPinned == 1) {