From 6185a9275926547134311d3ecb4bdb3dbb120190 Mon Sep 17 00:00:00 2001 From: jyuesong <425698907@qq.com> Date: Wed, 19 Jan 2022 14:41:14 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=BA=8F=E5=8F=B7,=E8=AF=A6=E6=83=85=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/base/routes.dart | 7 + lib/module/env/env_detail_page.dart | 334 ++++++++++++++++++++++++++++ lib/module/env/env_page.dart | 271 ++++++++++++---------- lib/module/env/env_viewmodel.dart | 2 +- 4 files changed, 493 insertions(+), 121 deletions(-) create mode 100644 lib/module/env/env_detail_page.dart diff --git a/lib/base/routes.dart b/lib/base/routes.dart index 9491b9e..fabee77 100644 --- a/lib/base/routes.dart +++ b/lib/base/routes.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:qinglong_app/module/config/config_edit_page.dart'; import 'package:qinglong_app/module/env/add_env_page.dart'; import 'package:qinglong_app/module/env/env_bean.dart'; +import 'package:qinglong_app/module/env/env_detail_page.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'; @@ -21,6 +22,7 @@ class Routes { static const String routeLogin = "/login"; static const String routeAddTask = "/task/add"; static const String routeTaskDetail = "/task/detail"; + static const String routeEnvDetail = "/env/detail"; static const String routeAddDependency = "/task/dependency"; static const String routeAddEnv = "/env/add"; static const String routeConfigEdit = "/config/edit"; @@ -98,6 +100,11 @@ class Routes { builder: (context) => TaskDetailPage( settings.arguments as TaskBean, ), + ); case routeEnvDetail: + return CupertinoPageRoute( + builder: (context) => EnvDetailPage( + settings.arguments as EnvBean, + ), ); } diff --git a/lib/module/env/env_detail_page.dart b/lib/module/env/env_detail_page.dart new file mode 100644 index 0000000..5998614 --- /dev/null +++ b/lib/module/env/env_detail_page.dart @@ -0,0 +1,334 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.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/module/env/env_bean.dart'; +import 'package:qinglong_app/module/env/env_viewmodel.dart'; +import 'package:qinglong_app/utils/utils.dart'; + +class EnvDetailPage extends ConsumerStatefulWidget { + final EnvBean envBean; + + const EnvDetailPage(this.envBean, {Key? key}) : super(key: key); + + @override + _TaskDetailPageState createState() => _TaskDetailPageState(); +} + +class _TaskDetailPageState extends ConsumerState { + List actions = []; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + actions.clear(); + actions.addAll( + [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(); + Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: widget.envBean); + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 15, + ), + alignment: Alignment.center, + child: const Material( + color: Colors.transparent, + child: Text( + "编辑", + style: TextStyle( + fontSize: 16, + ), + ), + ), + ), + ), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.of(context).pop(); + enableTask(); + }, + child: Container( + padding: const EdgeInsets.symmetric( + vertical: 15, + ), + alignment: Alignment.center, + child: Material( + color: Colors.transparent, + child: Text( + widget.envBean.status! == 0 ? "禁用" : "启用", + style: const TextStyle( + color: Colors.red, + fontSize: 16, + ), + ), + ), + ), + ), + ], + ); + return Scaffold( + appBar: QlAppBar( + canBack: true, + backCall: () { + Navigator.of(context).pop(); + }, + title: widget.envBean.name ?? "", + actions: [ + InkWell( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (context) { + return CupertinoActionSheet( + title: Container( + alignment: Alignment.center, + child: const Material( + color: Colors.transparent, + child: Text( + "更多操作", + style: TextStyle( + fontSize: 16, + ), + ), + ), + ), + actions: actions, + cancelButton: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Navigator.pop(context); + }, + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric( + vertical: 10, + ), + child: const Material( + color: Colors.transparent, + child: Text( + "取消", + style: TextStyle( + color: Colors.red, + fontSize: 16, + ), + ), + ), + ), + ), + ); + }); + }, + child: const Padding( + padding: EdgeInsets.symmetric( + horizontal: 15, + ), + child: Center( + child: Icon( + Icons.more_horiz, + color: Colors.white, + size: 26, + ), + ), + ), + ) + ], + ), + body: SingleChildScrollView( + child: Column( + children: [ + Container( + margin: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 10, + ), + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + ), + decoration: BoxDecoration( + color: ref.watch(themeProvider).themeColor.settingBgColor(), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + EnvDetailCell( + title: "ID", + desc: widget.envBean.sId ?? "", + ), + EnvDetailCell( + title: "变量名称", + desc: widget.envBean.name ?? "", + ), + EnvDetailCell( + title: "创建时间", + desc: Utils.formatMessageTime(widget.envBean.created ?? 0), + ), + EnvDetailCell( + title: "更新时间", + desc: Utils.formatGMTTime(widget.envBean.timestamp ?? ""), + ), + EnvDetailCell( + title: "值", + desc: widget.envBean.value ?? "", + ), + EnvDetailCell( + title: "备注", + desc: widget.envBean.remarks ?? "", + ), + EnvDetailCell( + title: "变量状态", + desc: widget.envBean.status == 1 ? "已禁用" : "已启用", + hideDivide: true, + ), + ], + ), + ), + const SizedBox( + height: 30, + ), + SizedBox( + width: MediaQuery.of(context).size.width - 80, + child: CupertinoButton( + padding: const EdgeInsets.symmetric( + vertical: 5, + ), + color: Colors.red, + child: const Text( + "删 除", + style: TextStyle( + fontSize: 16, + ), + ), + onPressed: () { + delTask(context, ref); + }), + ), + const SizedBox( + height: 30, + ), + ], + ), + ), + ); + } + + void enableTask() async { + await ref.read(envProvider).enableEnv(widget.envBean.sId!, widget.envBean.status!); + setState(() {}); + } + + void delTask(BuildContext context, WidgetRef ref) { + showCupertinoDialog( + context: context, + builder: (context) => CupertinoAlertDialog( + title: const Text("确认删除"), + content: Text("确认删除环境变量 ${widget.envBean.name ?? ""} 吗"), + actions: [ + CupertinoDialogAction( + child: const Text("取消"), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + CupertinoDialogAction( + child: const Text("确定"), + onPressed: () async { + Navigator.of(context).pop(); + await ref.read(envProvider).delEnv(widget.envBean.sId!); + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + } +} + +class EnvDetailCell extends ConsumerWidget { + final String title; + final String? desc; + final Widget? icon; + final bool hideDivide; + final Function? taped; + + const EnvDetailCell({ + Key? key, + required this.title, + this.desc, + this.icon, + this.hideDivide = false, + this.taped, + }) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + left: 15, + right: 10, + bottom: 10, + ), + child: Row( + children: [ + Text( + title, + style: TextStyle( + color: ref.watch(themeProvider).themeColor.titleColor(), + fontSize: 16, + ), + ), + const SizedBox( + width: 30, + ), + desc != null + ? Expanded( + child: Align( + alignment: Alignment.centerRight, + child: SelectableText( + desc!, + textAlign: TextAlign.right, + onTap: () { + if (taped != null) { + taped!(); + } + }, + style: TextStyle( + color: ref.watch(themeProvider).themeColor.descColor(), + fontSize: 14, + ), + ), + ), + ) + : Expanded( + child: Align(alignment: Alignment.centerRight, child: icon!), + ), + ], + ), + ), + hideDivide + ? const SizedBox.shrink() + : const Divider( + indent: 15, + ), + ], + ); + } +} diff --git a/lib/module/env/env_page.dart b/lib/module/env/env_page.dart index 5ee7d9d..1ad1403 100644 --- a/lib/module/env/env_page.dart +++ b/lib/module/env/env_page.dart @@ -29,13 +29,15 @@ class _EnvPageState extends State { builder: (ref, model, child) { List list = []; - for (var value in model.list) { + for (int i = 0; i < model.list.length; i++) { + EnvBean value = model.list[i]; if (_searchController.text.isEmpty || (value.name?.contains(_searchController.text) ?? false) || (value.value?.contains(_searchController.text) ?? false) || (value.remarks?.contains(_searchController.text) ?? false)) { list.add(EnvItemCell( value, + i + 1, ref, key: ValueKey(value.sId), )); @@ -124,120 +126,164 @@ class _EnvPageState extends State { class EnvItemCell extends StatelessWidget { final EnvBean bean; + final int index; final WidgetRef ref; - const EnvItemCell(this.bean, this.ref, {Key? key}) : super(key: key); + const EnvItemCell(this.bean, this.index, this.ref, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return ColoredBox( - color: ref.watch(themeProvider).themeColor.settingBgColor(), - child: Slidable( - key: ValueKey(bean.sId), - endActionPane: ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.45, - children: [ - SlidableAction( - backgroundColor: Colors.grey, - flex: 1, - onPressed: (_) { - Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean); - }, - foregroundColor: Colors.white, - icon: CupertinoIcons.pencil, - ), - SlidableAction( - backgroundColor: Colors.orange, - flex: 1, - onPressed: (_) { - enableEnv(); - }, - foregroundColor: Colors.white, - icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp, - ), - SlidableAction( - backgroundColor: Colors.red, - flex: 1, - onPressed: (_) { - delEnv(context, ref); - }, - foregroundColor: Colors.white, - icon: CupertinoIcons.delete, - ), - ], - ), - child: SizedBox( - width: MediaQuery.of(context).size.width, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + return GestureDetector( + onTap: () { + Navigator.of(context).pushNamed(Routes.routeEnvDetail, arguments: bean); + }, + child: ColoredBox( + color: ref.watch(themeProvider).themeColor.settingBgColor(), + child: Slidable( + key: ValueKey(bean.sId), + endActionPane: ActionPane( + motion: const ScrollMotion(), + extentRatio: 0.45, children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 15, - vertical: 8, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Row( - children: [ - Material( + SlidableAction( + backgroundColor: Colors.grey, + flex: 1, + onPressed: (_) { + Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean); + }, + foregroundColor: Colors.white, + icon: CupertinoIcons.pencil, + ), + SlidableAction( + backgroundColor: Colors.orange, + flex: 1, + onPressed: (_) { + enableEnv(); + }, + foregroundColor: Colors.white, + icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp, + ), + SlidableAction( + backgroundColor: Colors.red, + flex: 1, + onPressed: (_) { + delEnv(context, ref); + }, + foregroundColor: Colors.white, + icon: CupertinoIcons.delete, + ), + ], + ), + 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: 8, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Row( + children: [ + Material( + color: Colors.transparent, + child: Text( + bean.name ?? "", + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + color: ref.watch(themeProvider).themeColor.titleColor(), + fontSize: 18, + ), + ), + ), + const SizedBox( + width: 5, + ), + bean.status == 1 + ? const Icon( + Icons.dnd_forwardslash, + size: 16, + color: Colors.red, + ) + : const SizedBox.shrink(), + const Spacer(), + ], + ), + ), + const SizedBox( + width: 5, + ), + Material( + color: Colors.transparent, + child: Text( + Utils.formatGMTTime(bean.timestamp ?? ""), + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + color: ref.watch(themeProvider).themeColor.descColor(), + fontSize: 12, + ), + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 5, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + border: Border.all(color: primaryColor, width: 1), + ), + child: Text( + "$index", + style: TextStyle(color: primaryColor, fontSize: 12), + ), + ), + const SizedBox( + width: 5, + ), + Expanded( + child: Material( color: Colors.transparent, child: Text( - bean.name ?? "", + bean.remarks ?? "-", maxLines: 1, style: TextStyle( + height: 1, overflow: TextOverflow.ellipsis, - color: ref.watch(themeProvider).themeColor.titleColor(), - fontSize: 18, + color: ref.watch(themeProvider).themeColor.descColor(), + fontSize: 12, ), ), ), - const SizedBox( - width: 5, - ), - bean.status == 1 - ? const Icon( - Icons.dnd_forwardslash, - size: 16, - color: Colors.red, - ) - : const SizedBox.shrink(), - const Spacer(), - ], - ), - ), - const SizedBox( - width: 5, - ), - Material( - color: Colors.transparent, - child: Text( - Utils.formatGMTTime(bean.timestamp ?? ""), - maxLines: 1, - style: TextStyle( - overflow: TextOverflow.ellipsis, - color: ref.watch(themeProvider).themeColor.descColor(), - fontSize: 12, ), - ), + ], ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Material( + ), + const SizedBox( + height: 8, + ), + Material( color: Colors.transparent, child: Text( - bean.remarks ?? "-", + bean.value ?? "", maxLines: 1, style: TextStyle( overflow: TextOverflow.ellipsis, @@ -246,30 +292,15 @@ class EnvItemCell extends StatelessWidget { ), ), ), - ), - const SizedBox( - height: 8, - ), - Material( - color: Colors.transparent, - child: Text( - bean.value ?? "", - maxLines: 1, - style: TextStyle( - overflow: TextOverflow.ellipsis, - color: ref.watch(themeProvider).themeColor.descColor(), - fontSize: 12, - ), - ), - ), - ], + ], + ), ), - ), - const Divider( - height: 1, - indent: 15, - ), - ], + const Divider( + height: 1, + indent: 15, + ), + ], + ), ), ), ), diff --git a/lib/module/env/env_viewmodel.dart b/lib/module/env/env_viewmodel.dart index 2673885..5f71d4b 100644 --- a/lib/module/env/env_viewmodel.dart +++ b/lib/module/env/env_viewmodel.dart @@ -48,7 +48,7 @@ class EnvViewModel extends BaseViewModel { notifyListeners(); } - void enableEnv(String sId, int status) async { + Future enableEnv(String sId, int status) async { if (status == 1) { HttpResponse response = await Api.enableEnv(sId);