mirror of
https://github.com/qinglong-app/qinglong_app.git
synced 2025-10-09 16:48:19 +08:00
add task
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:back_button_interceptor/back_button_interceptor.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// @author newtab on 2021/7/16
|
||||
@@ -13,6 +14,22 @@ class CommonDialog extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget loading;
|
||||
|
||||
if (commonDialogState == CommonDialogState.FAILED) {
|
||||
loading = const Icon(
|
||||
CupertinoIcons.clear_circled,
|
||||
size: 50,
|
||||
);
|
||||
} else if (commonDialogState == CommonDialogState.SUCCESS) {
|
||||
loading = const Icon(
|
||||
CupertinoIcons.checkmark_alt,
|
||||
size: 50,
|
||||
);
|
||||
} else {
|
||||
loading = LoadingIcon();
|
||||
}
|
||||
|
||||
Widget result = Material(
|
||||
color: Colors.transparent,
|
||||
child: Align(
|
||||
@@ -36,7 +53,7 @@ class CommonDialog extends StatelessWidget {
|
||||
color: Colors.white,
|
||||
size: 40.0,
|
||||
),
|
||||
child: LoadingIcon()),
|
||||
child: loading),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
@@ -132,7 +149,7 @@ HideCallback showCommonDialog(
|
||||
}, zIndex: backButtonIndex, name: backButtonName);
|
||||
backButtonIndex++;
|
||||
|
||||
if (overlay != null) {
|
||||
if (overlay != null && overlay!.mounted) {
|
||||
overlay?.remove();
|
||||
overlay = null;
|
||||
}
|
||||
@@ -146,11 +163,13 @@ HideCallback showCommonDialog(
|
||||
},
|
||||
child: CommonDialog(
|
||||
text: text,
|
||||
commonDialogState: commonDialogState,
|
||||
),
|
||||
),
|
||||
);
|
||||
result.complete(() {
|
||||
overlay?.remove();
|
||||
overlay = null;
|
||||
BackButtonInterceptor.removeByName(backButtonName);
|
||||
});
|
||||
if (overlay != null) {
|
||||
|
||||
@@ -34,8 +34,11 @@ class Api {
|
||||
return await Http.get<String>(Url.INTIME_LOG(cron), null);
|
||||
}
|
||||
|
||||
|
||||
static Future<HttpResponse<TaskDetailBean>> taskDetail(String cron) async {
|
||||
return await Http.get<TaskDetailBean>(Url.TASK_DETAIL+cron, null);
|
||||
return await Http.get<TaskDetailBean>(Url.TASK_DETAIL + cron, null);
|
||||
}
|
||||
|
||||
static Future<HttpResponse<TaskDetailBean>> addTask(String name, String command, String cron, {String? id}) async {
|
||||
return await Http.put<TaskDetailBean>(Url.ADD_TASK, {"name": name, "command": command, "schedule": cron, "_id": id});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ class Url {
|
||||
static const RUN_TASKS = "/api/crons/run";
|
||||
static const STOP_TASKS = "/api/crons/stop";
|
||||
static const TASK_DETAIL = "/api/crons/";
|
||||
static const ADD_TASK = "/api/crons";
|
||||
|
||||
static INTIME_LOG(String cronId) {
|
||||
return "/api/crons/$cronId/log";
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qinglong_app/module/home/home_page.dart';
|
||||
import 'package:qinglong_app/module/task/add_task_page.dart';
|
||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||
|
||||
class Routes {
|
||||
static const String route_HomePage = "/home/homepage";
|
||||
static const String route_AddTask = "/task/add";
|
||||
|
||||
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case route_HomePage:
|
||||
return MaterialPageRoute(builder: (context) => const HomePage());
|
||||
case route_AddTask:
|
||||
if (settings.arguments != null) {
|
||||
return CupertinoPageRoute(
|
||||
builder: (context) => AddTaskPage(
|
||||
taskBean: settings.arguments as TaskBean,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import 'package:qinglong_app/module/login/login_bean.dart';
|
||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||
import 'package:qinglong_app/module/task/task_detail/task_detail_bean.dart';
|
||||
|
||||
|
||||
class JsonConversion$Json {
|
||||
@@ -26,6 +27,10 @@ class JsonConversion$Json {
|
||||
return TaskBean.jsonConversion(json) as M;
|
||||
}
|
||||
|
||||
if(type == (TaskDetailBean).toString()){
|
||||
return TaskDetailBean.jsonConversion(json) as M;
|
||||
}
|
||||
|
||||
throw Exception("not found");
|
||||
}
|
||||
|
||||
@@ -38,6 +43,10 @@ class JsonConversion$Json {
|
||||
return data.map<TaskBean>((e) => TaskBean.jsonConversion(e)).toList() as M;
|
||||
}
|
||||
|
||||
if(<TaskDetailBean>[] is M){
|
||||
return data.map<TaskDetailBean>((e) => TaskDetailBean.jsonConversion(e)).toList() as M;
|
||||
}
|
||||
|
||||
throw Exception("not found");
|
||||
}
|
||||
}
|
||||
|
||||
201
lib/module/task/add_task_page.dart
Normal file
201
lib/module/task/add_task_page.dart
Normal file
@@ -0,0 +1,201 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:qinglong_app/base/common_dialog.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/task/task_bean.dart';
|
||||
import 'package:qinglong_app/module/task/task_detail/task_detail_bean.dart';
|
||||
|
||||
class AddTaskPage extends StatefulWidget {
|
||||
final TaskBean? taskBean;
|
||||
|
||||
const AddTaskPage({Key? key, this.taskBean}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AddTaskPage> createState() => _AddTaskPageState();
|
||||
}
|
||||
|
||||
class _AddTaskPageState extends State<AddTaskPage> {
|
||||
late TaskBean taskBean;
|
||||
|
||||
final TextEditingController _nameController = TextEditingController();
|
||||
final TextEditingController _commandController = TextEditingController();
|
||||
final TextEditingController _cronController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.taskBean != null) {
|
||||
taskBean = widget.taskBean!;
|
||||
_nameController.text = taskBean.name ?? "";
|
||||
_commandController.text = taskBean.command ?? "";
|
||||
_cronController.text = taskBean.schedule ?? "";
|
||||
} else {
|
||||
taskBean = TaskBean();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: QlAppBar(
|
||||
canBack: true,
|
||||
backCall: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: taskBean.name == null ? "新增任务" : "编辑任务",
|
||||
actions: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
submit();
|
||||
},
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 15,
|
||||
),
|
||||
child: Center(
|
||||
child: Text("提交"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
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.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller: _nameController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入任务名称",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller: _commandController,
|
||||
maxLines: 4,
|
||||
minLines: 1,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入命令",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller: _cronController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入定时",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void submit() async {
|
||||
if (_nameController.text.isEmpty) {
|
||||
failDialog(context, "任务名称不能为空");
|
||||
return;
|
||||
}
|
||||
if (_commandController.text.isEmpty) {
|
||||
failDialog(context, "命令不能为空");
|
||||
return;
|
||||
}
|
||||
if (_cronController.text.isEmpty) {
|
||||
failDialog(context, "定时不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
taskBean.name = _nameController.text;
|
||||
taskBean.command = _commandController.text;
|
||||
taskBean.schedule = _cronController.text;
|
||||
HttpResponse<TaskDetailBean> response = await Api.addTask(_nameController.text, _commandController.text, _cronController.text, id: taskBean.sId);
|
||||
|
||||
if (response.success) {
|
||||
successDialog(context, "操作成功").then((value) {
|
||||
Navigator.of(context).pop(response.bean);
|
||||
});
|
||||
} else {
|
||||
failDialog(context, response.message ??"");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,4 +60,8 @@ class TaskDetailBean {
|
||||
data['isPinned'] = this.isPinned;
|
||||
return data;
|
||||
}
|
||||
|
||||
static TaskDetailBean jsonConversion(Map<String, dynamic> json) {
|
||||
return TaskDetailBean.fromJson(json);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||
import 'package:qinglong_app/base/base_state_widget.dart';
|
||||
import 'package:qinglong_app/base/routes.dart';
|
||||
import 'package:qinglong_app/base/theme.dart';
|
||||
import 'package:qinglong_app/module/task/intime_log/intime_log_page.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/utils.dart';
|
||||
|
||||
@@ -97,13 +99,26 @@ class _TaskPageState extends State<TaskPage> {
|
||||
}
|
||||
}
|
||||
|
||||
class TaskItemCell extends ConsumerWidget {
|
||||
class TaskItemCell extends ConsumerStatefulWidget {
|
||||
final TaskBean bean;
|
||||
|
||||
const TaskItemCell(this.bean, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
_TaskItemCellState createState() => _TaskItemCellState();
|
||||
}
|
||||
|
||||
class _TaskItemCellState extends ConsumerState<TaskItemCell> {
|
||||
late TaskBean bean;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
bean = widget.bean;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Slidable(
|
||||
key: const ValueKey(0),
|
||||
startActionPane: ActionPane(
|
||||
@@ -299,6 +314,15 @@ class TaskItemCell extends ConsumerWidget {
|
||||
child: const Text('编辑'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).pushNamed(Routes.route_AddTask, arguments: bean).then((value) {
|
||||
if (value != null) {
|
||||
var result = value as TaskDetailBean;
|
||||
bean.name = result.name;
|
||||
bean.schedule = result.schedule;
|
||||
bean.command = result.command;
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
|
||||
Reference in New Issue
Block a user