增加client_id登录方式

This commit is contained in:
NewTab
2022-01-19 19:39:25 +08:00
parent 6dbed6cf49
commit e8694643d8
14 changed files with 415 additions and 281 deletions

View File

@@ -6,6 +6,8 @@
* 部分页面进入卡顿优化
* 扩大任务的搜索范围
* 优化暗黑主题
* 支持client_id登录
* 修改bug
## 1.0.0

41
ios/Podfile.lock Normal file
View File

@@ -0,0 +1,41 @@
PODS:
- Flutter (1.0.0)
- fluttertoast (0.0.2):
- Flutter
- Toast
- move_to_background (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter
- Toast (4.0.0)
DEPENDENCIES:
- Flutter (from `Flutter`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- move_to_background (from `.symlinks/plugins/move_to_background/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
SPEC REPOS:
trunk:
- Toast
EXTERNAL SOURCES:
Flutter:
:path: Flutter
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
move_to_background:
:path: ".symlinks/plugins/move_to_background/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
fluttertoast: 6122fa75143e992b1d3470f61000f591a798cc58
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
shared_preferences_ios: aef470a42dc4675a1cdd50e3158b42e3d1232b32
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
PODFILE CHECKSUM: aea2ed8a4b05dec076f6f7cea39202b1133ed51c
COCOAPODS: 1.11.2

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1320"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -29,7 +29,7 @@ class Api {
String id,
String secret,
) async {
return await Http.post<LoginBean>(
return await Http.get<LoginBean>(
Url.loginByClientId,
{
"client_id": id,

View File

@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:qinglong_app/base/http/url.dart';
import 'package:qinglong_app/main.dart';
import '../userinfo_viewmodel.dart';
@@ -15,8 +16,10 @@ class TokenInterceptor extends Interceptor {
options.headers["User-Agent"] =
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
options.headers["Content-Type"] = "application/json;charset=UTF-8";
options.queryParameters["t"] =
(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
if (options.path != Url.loginByClientId) {
options.queryParameters["t"] =
(DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
}
return handler.next(options);
}
}

View File

@@ -6,7 +6,7 @@ class Url {
static const loginByClientId = "/open/auth/token";
static const user = "/api/user";
static get tasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/user/login" : "/api/crons";
static get tasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons" : "/api/crons";
static get runTasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/run" : "/api/crons/run";

View File

@@ -49,12 +49,12 @@ class Routes {
return CupertinoPageRoute(builder: (context) => const AddTaskPage());
}
case routeAddDependency:
return CupertinoPageRoute(builder: (context) => const AddDependenyPage());
return CupertinoPageRoute(builder: (context) => const AddDependencyPage());
case routeAddEnv:
if (settings.arguments != null) {
return CupertinoPageRoute(
builder: (context) => AddEnvPage(
taskBean: settings.arguments as EnvBean,
envBean: settings.arguments as EnvBean,
));
} else {
return CupertinoPageRoute(builder: (context) => const AddEnvPage());

View File

@@ -13,8 +13,10 @@ class UserInfoViewModel {
String userInfoJson = SpUtil.getString(spUserInfo);
_userName = SpUtil.getString(spUserName);
_passWord = SpUtil.getString(spPassWord);
_useSecertLogined = SpUtil.getBool(spSecretLogined, defValue: false);
_host = SpUtil.getString(spHost, defValue: 'http://49.234.59.95:5700');
_host = SpUtil.getString(spHost, defValue: 'http://1.1.1.1:5700');
if (userInfoJson.isNotEmpty) {
_token = userInfoJson;
}

View File

@@ -18,8 +18,6 @@ class ConfigEditPage extends ConsumerStatefulWidget {
}
class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
String? value;
late TextEditingController _controller;
FocusNode node = FocusNode();
@@ -46,12 +44,10 @@ class _ConfigEditPageState extends ConsumerState<ConfigEditPage> {
actions: [
InkWell(
onTap: () async {
if (value == null) {
"请先点击保存".toast();
return;
}
HttpResponse<NullResponse> response = await Api.saveFile(widget.title, _controller.text);
HttpResponse<NullResponse> response =
await Api.saveFile(widget.title, _controller.text);
if (response.success) {
"提交成功".toast();
ref.read(configProvider).loadContent(widget.title);
Navigator.of(context).pop();
} else {

View File

@@ -8,9 +8,9 @@ import 'package:qinglong_app/module/env/env_viewmodel.dart';
import 'package:qinglong_app/utils/extension.dart';
class AddEnvPage extends ConsumerStatefulWidget {
final EnvBean? taskBean;
final EnvBean? envBean;
const AddEnvPage({Key? key, this.taskBean}) : super(key: key);
const AddEnvPage({Key? key, this.envBean}) : super(key: key);
@override
ConsumerState<AddEnvPage> createState() => _AddEnvPageState();
@@ -27,8 +27,8 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
@override
void initState() {
super.initState();
if (widget.taskBean != null) {
envBean = widget.taskBean!;
if (widget.envBean != null) {
envBean = widget.envBean!;
_nameController.text = envBean.name ?? "";
_valueController.text = envBean.value ?? "";
_remarkController.text = envBean.remarks ?? "";
@@ -88,7 +88,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"名称:",
@@ -97,14 +97,10 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
focusNode: focusNode,
controller: _nameController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入名称",
),
autofocus: false,
@@ -121,7 +117,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"值:",
@@ -130,15 +126,11 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _valueController,
maxLines: 8,
minLines: 1,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入值",
),
autofocus: false,
@@ -155,7 +147,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"备注:",
@@ -164,13 +156,9 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _remarkController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入备注",
),
autofocus: false,
@@ -197,10 +185,12 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
envBean.name = _nameController.text;
envBean.value = _valueController.text;
envBean.remarks = _remarkController.text;
HttpResponse<NullResponse> response = await Api.addEnv(_nameController.text, _valueController.text, _remarkController.text, id: envBean.sId);
HttpResponse<NullResponse> response = await Api.addEnv(
_nameController.text, _valueController.text, _remarkController.text,
id: envBean.sId);
if (response.success) {
"操作成功".toast();
(envBean.sId == null) ? "新增成功" : "修改成功".toast();
ref.read(envProvider).updateEnv(envBean);
Navigator.of(context).pop();
} else {

View File

@@ -22,7 +22,8 @@ class LoginPage extends ConsumerStatefulWidget {
}
class _LoginPageState extends ConsumerState<LoginPage> {
final TextEditingController _hostController = TextEditingController(text: getIt<UserInfoViewModel>().host);
final TextEditingController _hostController =
TextEditingController(text: getIt<UserInfoViewModel>().host);
final TextEditingController _userNameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _cIdController = TextEditingController();
@@ -31,11 +32,15 @@ class _LoginPageState extends ConsumerState<LoginPage> {
bool rememberPassword = false;
bool useSecretLogin = false;
@override
void initState() {
super.initState();
useSecretLogin = getIt<UserInfoViewModel>().useSecretLogined;
if (getIt<UserInfoViewModel>().userName != null && getIt<UserInfoViewModel>().userName!.isNotEmpty) {
if (getIt<UserInfoViewModel>().userName != null &&
getIt<UserInfoViewModel>().userName!.isNotEmpty) {
if (getIt<UserInfoViewModel>().useSecretLogined) {
_cIdController.text = getIt<UserInfoViewModel>().userName!;
} else {
@@ -45,7 +50,8 @@ class _LoginPageState extends ConsumerState<LoginPage> {
} else {
rememberPassword = false;
}
if (getIt<UserInfoViewModel>().passWord != null && getIt<UserInfoViewModel>().passWord!.isNotEmpty) {
if (getIt<UserInfoViewModel>().passWord != null &&
getIt<UserInfoViewModel>().passWord!.isNotEmpty) {
if (getIt<UserInfoViewModel>().useSecretLogined) {
_cSecretController.text = getIt<UserInfoViewModel>().passWord!;
} else {
@@ -54,12 +60,8 @@ class _LoginPageState extends ConsumerState<LoginPage> {
}
getIt<UserInfoViewModel>().updateToken("");
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
if (getIt<UserInfoViewModel>().useSecretLogined) {
if (useSecretLogin) {
cardKey.currentState?.toggleCard();
getIt<UserInfoViewModel>().useSecretLogin(!(cardKey.currentState?.isFront ?? true));
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
setState(() {});
});
}
});
}
@@ -151,114 +153,126 @@ class _LoginPageState extends ConsumerState<LoginPage> {
),
FlipCard(
key: cardKey,
fill: Fill.fillBack,
// Fill the back side of the card to make in the same size as the front.
onFlipDone: (back) {
useSecretLogin = back;
setState(() {});
},
direction: FlipDirection.HORIZONTAL,
front: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 15,
),
const Text(
"用户名:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
front: SizedBox(
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 15,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _userNameController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入用户名",
const Text(
"用户名:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
autofocus: false,
),
const SizedBox(
height: 15,
),
const Text(
"密码:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
TextField(
onChanged: (_) {
setState(() {});
},
controller: _userNameController,
decoration: const InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入用户名",
),
autofocus: false,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入密码",
const SizedBox(
height: 15,
),
autofocus: false,
),
const SizedBox(
height: 10,
),
],
const Text(
"密码:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入密码",
),
autofocus: false,
),
const SizedBox(
height: 10,
),
],
),
),
back: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 15,
),
const Text(
"client_id:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
back: SizedBox(
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 15,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _cIdController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入client_id",
const Text(
"client_id:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
autofocus: false,
),
const SizedBox(
height: 15,
),
const Text(
"client_secret:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
TextField(
onChanged: (_) {
setState(() {});
},
controller: _cIdController,
decoration: const InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入client_id",
),
autofocus: false,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _cSecretController,
obscureText: true,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入client_secret",
const SizedBox(
height: 15,
),
autofocus: false,
),
const SizedBox(
height: 10,
),
],
const Text(
"client_secret:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
TextField(
onChanged: (_) {
setState(() {});
},
controller: _cSecretController,
obscureText: true,
decoration: const InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入client_secret",
),
autofocus: false,
),
const SizedBox(
height: 10,
),
],
),
),
),
Row(
@@ -280,12 +294,13 @@ class _LoginPageState extends ConsumerState<LoginPage> {
GestureDetector(
onTap: () {
cardKey.currentState?.toggleCard();
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
WidgetsBinding.instance
?.addPostFrameCallback((timeStamp) {
setState(() {});
});
},
child: Text(
(cardKey.currentState?.isFront ?? true) ? "client_id登录" : "用户名密码登录",
loginByUserName() ? "client_id登录" : "用户名密码登录",
style: const TextStyle(
fontSize: 14,
),
@@ -299,12 +314,19 @@ class _LoginPageState extends ConsumerState<LoginPage> {
SizedBox(
width: MediaQuery.of(context).size.width - 80,
child: IgnorePointer(
ignoring: _hostController.text.isEmpty || _userNameController.text.isEmpty || _passwordController.text.isEmpty || isLoading,
ignoring: !canClickLoginBtn(),
child: CupertinoButton(
padding: const EdgeInsets.symmetric(
vertical: 5,
),
color: canClickLoginBtn() ? ref.watch(themeProvider).themeColor.buttonBgColor() : Theme.of(context).primaryColor.withOpacity(0.4),
color: canClickLoginBtn()
? ref
.watch(themeProvider)
.themeColor
.buttonBgColor()
: Theme.of(context)
.primaryColor
.withOpacity(0.4),
child: isLoading
? const CupertinoActivityIndicator()
: const Text(
@@ -316,11 +338,14 @@ class _LoginPageState extends ConsumerState<LoginPage> {
onPressed: () {
Http.pushedLoginPage = false;
Utils.hideKeyBoard(context);
getIt<UserInfoViewModel>().updateHost(_hostController.text);
if (cardKey.currentState?.isFront ?? true) {
login(_userNameController.text, _passwordController.text);
getIt<UserInfoViewModel>()
.updateHost(_hostController.text);
if (loginByUserName()) {
login(_userNameController.text,
_passwordController.text);
} else {
login(_cIdController.text, _cSecretController.text);
login(_cIdController.text,
_cSecretController.text);
}
},
),
@@ -340,7 +365,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
bool isLoading = false;
bool loginByUserName() {
return !getIt<UserInfoViewModel>().useSecretLogined;
return !useSecretLogin;
}
Future<void> login(String userName, String password) async {
@@ -365,7 +390,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
} else {
HttpResponse<UserBean> userResponse = await Api.user();
if (userResponse.success) {
if (userResponse.bean != null && userResponse.bean!.twoFactorActivated != null && userResponse.bean!.twoFactorActivated!) {
if (userResponse.bean != null &&
userResponse.bean!.twoFactorActivated != null &&
userResponse.bean!.twoFactorActivated!) {
("你已开启两步验证,App暂不支持").toast();
isLoading = false;
setState(() {});
@@ -390,9 +417,11 @@ class _LoginPageState extends ConsumerState<LoginPage> {
if (_hostController.text.isEmpty) return false;
if (!loginByUserName()) {
return _cIdController.text.isNotEmpty && _cSecretController.text.isNotEmpty;
return _cIdController.text.isNotEmpty &&
_cSecretController.text.isNotEmpty;
} else {
return _userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty;
return _userNameController.text.isNotEmpty &&
_passwordController.text.isNotEmpty;
}
}
}

View File

@@ -6,16 +6,16 @@ import 'package:qinglong_app/base/ql_app_bar.dart';
import 'package:qinglong_app/module/others/dependencies/dependency_viewmodel.dart';
import 'package:qinglong_app/utils/extension.dart';
class AddDependenyPage extends ConsumerStatefulWidget {
const AddDependenyPage({
class AddDependencyPage extends ConsumerStatefulWidget {
const AddDependencyPage({
Key? key,
}) : super(key: key);
@override
ConsumerState<AddDependenyPage> createState() => _AddDependencyPageState();
ConsumerState<AddDependencyPage> createState() => _AddDependencyPageState();
}
class _AddDependencyPageState extends ConsumerState<AddDependenyPage> {
class _AddDependencyPageState extends ConsumerState<AddDependencyPage> {
final TextEditingController _nameController = TextEditingController();
DepedencyEnum depedencyType = DepedencyEnum.NodeJS;
@@ -83,7 +83,7 @@ class _AddDependencyPageState extends ConsumerState<AddDependenyPage> {
height: 10,
),
DropdownButtonFormField<DepedencyEnum>(
items: [
items: [
DropdownMenuItem(
value: DepedencyEnum.NodeJS,
child: Text(DepedencyEnum.NodeJS.name),
@@ -154,7 +154,7 @@ class _AddDependencyPageState extends ConsumerState<AddDependenyPage> {
);
if (response.success) {
"操作成功".toast();
"新增成功".toast();
ref.read(dependencyProvider).loadData(
depedencyType.name.toLowerCase(),
);

View File

@@ -88,7 +88,7 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"名称:",
@@ -97,9 +97,6 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
focusNode: focusNode,
controller: _nameController,
@@ -121,7 +118,7 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"命令:",
@@ -130,9 +127,6 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _commandController,
maxLines: 4,
@@ -155,7 +149,7 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
height: 15,
),
const Text(
"定时:",
@@ -164,9 +158,6 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _cronController,
decoration: const InputDecoration(
@@ -213,10 +204,12 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
taskBean.name = _nameController.text;
taskBean.command = _commandController.text;
taskBean.schedule = _cronController.text;
HttpResponse<NullResponse> response = await Api.addTask(_nameController.text, _commandController.text, _cronController.text, id: taskBean.sId);
HttpResponse<NullResponse> response = await Api.addTask(
_nameController.text, _commandController.text, _cronController.text,
id: taskBean.sId);
if (response.success) {
"操作成功".toast();
(widget.taskBean?.sId == null) ? "新增成功" : "修改成功".toast();
ref.read(taskProvider).updateBean(taskBean);
Navigator.of(context).pop();
} else {

View File

@@ -5,245 +5,245 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "22.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.2"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.8"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
back_button_interceptor:
dependency: "direct main"
description:
name: back_button_interceptor
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "5.0.2"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
build:
dependency: transitive
description:
name: build
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.7"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.3"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.4"
change_app_package_name:
dependency: "direct dev"
description:
name: change_app_package_name
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.4"
dio_log:
dependency: "direct main"
description:
name: dio_log
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
drag_and_drop_lists:
dependency: "direct main"
description:
name: drag_and_drop_lists
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.2+2"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
file:
dependency: transitive
description:
name: file
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flip_card:
dependency: "direct main"
description:
name: flip_card
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.0"
flutter:
@@ -255,49 +255,49 @@ packages:
dependency: "direct dev"
description:
name: flutter_app_name
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1"
flutter_highlight:
dependency: "direct main"
description:
name: flutter_highlight
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.0"
flutter_launcher_icons:
dependency: "direct dev"
description:
name: flutter_launcher_icons
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.2"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
flutter_native_splash:
dependency: "direct dev"
description:
name: flutter_native_splash
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.3"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
flutter_slidable:
dependency: "direct main"
description:
name: flutter_slidable
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
flutter_test:
@@ -314,322 +314,322 @@ packages:
dependency: "direct main"
description:
name: fluttertoast
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "8.0.8"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
get_it:
dependency: "direct main"
description:
name: get_it
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.0"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
highlight:
dependency: transitive
description:
name: highlight
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
intl:
dependency: "direct main"
description:
name: intl
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
io:
dependency: transitive
description:
name: io
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
js:
dependency: transitive
description:
name: js
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
json_conversion:
dependency: "direct dev"
description:
name: json_conversion
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4"
json_conversion_annotation:
dependency: "direct main"
description:
name: json_conversion_annotation
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logger:
dependency: "direct main"
description:
name: logger
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
move_to_background:
dependency: "direct main"
description:
name: move_to_background
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
pool:
dependency: transitive
description:
name: pool
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
process:
dependency: transitive
description:
name: process
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.4"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
riverpod:
dependency: transitive
description:
name: riverpod
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.12"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.10"
shared_preferences_ios:
dependency: transitive
description:
name: shared_preferences_ios
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
sky_engine:
@@ -641,140 +641,140 @@ packages:
dependency: transitive
description:
name: source_gen
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
state_notifier:
dependency: transitive
description:
name: state_notifier
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.2+1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
synchronized:
dependency: "direct main"
description:
name: synchronized
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.3"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
universal_io:
dependency: transitive
description:
name: universal_io
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.6"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "5.3.1"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
sdks: