add dependency

This commit is contained in:
jyuesong
2022-01-18 14:26:56 +08:00
parent 8aa41e577b
commit b9767339ec
15 changed files with 790 additions and 216 deletions

View File

@@ -234,7 +234,7 @@ class Api {
return await Http.get<List<DependencyBean>>(
Url.dependencies,
{
"type": type,
"type": type.toString(),
},
);
}

View File

@@ -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";

View File

@@ -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<dynamic>? 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(

View File

@@ -52,6 +52,7 @@ class MyApp extends ConsumerWidget {
FocusScope.of(context).requestFocus(FocusNode());
},
child: MaterialApp(
locale: const Locale('zh','cn'),
navigatorObservers: [getIt<QlNavigatorObserver>()],
navigatorKey: navigatorState,
theme: ref.watch<ThemeViewModel>(themeProvider).currentTheme,

View File

@@ -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<AddDependenyPage> createState() => _AddDependencyPageState();
}
class _AddDependencyPageState extends ConsumerState<AddDependenyPage> {
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<DepedencyEnum>(
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<NullResponse> 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();
}
}
}

View File

@@ -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<DependencyPage> with TickerProviderStateMixin {
List<DepedencyEnum> 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<DependencyViewModel>(
onReady: (model) {
model.loadData(types[_tabController!.index].name.toLowerCase());
},
model: dependencyProvider,
builder: (context, model, child) {
return TabBarView(
controller: _tabController,
children: types.map(
(e) {
List<DependencyBean> 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 ?? "");
},
),
],
),
);
}
}

View File

@@ -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<DependencyBean> nodeJsList = [];
List<DependencyBean> python3List = [];
List<DependencyBean> linuxList = [];
Future<void> loadData(String type, [bool showLoading = true]) async {
if (showLoading) {
loading(notify: true);
}
HttpResponse<List<DependencyBean>> 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 }

View File

@@ -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<LoginLogPage> {
class _LoginLogPageState extends ConsumerState<LoginLogPage> with LazyLoadState<LoginLogPage> {
List<LoginLogBean> list = [];
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -38,7 +34,11 @@ class _LoginLogPageState extends ConsumerState<LoginLogPage> {
},
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<LoginLogPage> {
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<LoginLogPage> {
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<LoginLogPage> {
response.message?.toast();
}
}
@override
void onLazyLoad() {
loadData();
}
}

View File

@@ -57,10 +57,7 @@ class _OtherPageState extends ConsumerState<OtherPage> {
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<OtherPage> {
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<OtherPage> {
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<OtherPage> {
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<OtherPage> {
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<OtherPage> {
),
onPressed: () {
getIt<UserInfoViewModel>().updateToken("");
Navigator.of(context)
.pushReplacementNamed(Routes.routeLogin);
Navigator.of(context).pushReplacementNamed(Routes.routeLogin);
}),
),
),

View File

@@ -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<ScriptDetailPage>
with LazyLoadState<ScriptDetailPage> {
class _ScriptDetailPageState extends ConsumerState<ScriptDetailPage> with LazyLoadState<ScriptDetailPage> {
String? content;
@override
@@ -38,7 +37,11 @@ class _ScriptDetailPageState extends ConsumerState<ScriptDetailPage>
},
title: "脚本详情",
),
body: SingleChildScrollView(
body:content == null
? const Center(
child: CupertinoActivityIndicator(),
)
: SingleChildScrollView(
child: HighlightView(
content ?? "",
language: getLanguageType(widget.title),

View File

@@ -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<ScriptPage> {
},
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,
),
);
}

View File

@@ -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<TaskLogDetailPage> {
class _TaskLogDetailPageState extends ConsumerState<TaskLogDetailPage> with LazyLoadState<TaskLogDetailPage> {
String? content;
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -39,14 +33,16 @@ class _TaskLogDetailPageState extends ConsumerState<TaskLogDetailPage> {
},
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<TaskLogDetailPage> {
response.message?.toast();
}
}
@override
void onLazyLoad() {
loadData();
}
}

View File

@@ -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<TaskLogPage> {
class _TaskLogPageState extends ConsumerState<TaskLogPage> with LazyLoadState<TaskLogPage> {
List<TaskLogBean> list = [];
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -35,64 +31,56 @@ class _TaskLogPageState extends ConsumerState<TaskLogPage> {
},
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<TaskLogPage> {
response.message?.toast();
}
}
@override
void onLazyLoad() {
loadData();
}
}

View File

@@ -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';

View File

@@ -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) {