mirror of
https://github.com/qinglong-app/qinglong_app.git
synced 2025-10-09 16:48:19 +08:00
add setting
This commit is contained in:
@@ -98,13 +98,13 @@ class Api {
|
||||
return await Http.delete<NullResponse>(Url.DEL_ENV, [id]);
|
||||
}
|
||||
|
||||
static Future<HttpResponse<EnvBean>> addEnv(String value, String name, String remarks, {String? id}) async {
|
||||
var data = {"value": name, "remarks": remarks, "name": name};
|
||||
static Future<HttpResponse<NullResponse>> addEnv(String name, String value, String remarks, {String? id}) async {
|
||||
var data = {"value": value, "remarks": remarks, "name": name};
|
||||
|
||||
if (id != null) {
|
||||
data["_id"] = id;
|
||||
return await Http.put<EnvBean>(Url.ADD_ENV, data);
|
||||
return await Http.put<NullResponse>(Url.ADD_ENV, data);
|
||||
}
|
||||
return await Http.post<EnvBean>(Url.ADD_ENV, data);
|
||||
return await Http.post<NullResponse>(Url.ADD_ENV, [data]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Http {
|
||||
if (e.response?.statusCode == 401) {
|
||||
exitLogin();
|
||||
}
|
||||
return HttpResponse(success: false, message: e.message, code: 0);
|
||||
return HttpResponse(success: false, message: e.response?.statusMessage ?? e.message, code: 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class Http {
|
||||
if (e.response?.statusCode == 401) {
|
||||
exitLogin();
|
||||
}
|
||||
return HttpResponse(success: false, message: e.message, code: 0);
|
||||
return HttpResponse(success: false, message: e.response?.statusMessage ?? e.message, code: 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class Http {
|
||||
if (e.response?.statusCode == 401) {
|
||||
exitLogin();
|
||||
}
|
||||
return HttpResponse(success: false, message: e.message, code: 0);
|
||||
return HttpResponse(success: false, message: e.response?.statusMessage ?? e.message, code: 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ class Http {
|
||||
if (e.response?.statusCode == 401) {
|
||||
exitLogin();
|
||||
}
|
||||
return HttpResponse(success: false, message: e.message, code: 0);
|
||||
return HttpResponse(success: false, message: e.response?.statusMessage ?? e.message, code: 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ class TokenInterceptor extends Interceptor {
|
||||
if (getIt<UserInfoViewModel>().token != null && getIt<UserInfoViewModel>().token!.isNotEmpty) {
|
||||
options.headers["Authorization"] = "Bearer " + getIt<UserInfoViewModel>().token!;
|
||||
}
|
||||
|
||||
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();
|
||||
return handler.next(options);
|
||||
}
|
||||
|
||||
@@ -42,9 +42,15 @@ class ThemeViewModel extends ChangeNotifier {
|
||||
}
|
||||
|
||||
ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||
brightness: Brightness.dark,
|
||||
primaryColor: const Color(0xffffffff),
|
||||
scaffoldBackgroundColor: Colors.black,
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Colors.black,
|
||||
titleTextStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
labelStyle: TextStyle(color: _primaryColor),
|
||||
@@ -70,6 +76,7 @@ ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||
),
|
||||
);
|
||||
ThemeData lightTheme = ThemeData.light().copyWith(
|
||||
brightness: Brightness.light,
|
||||
primaryColor: _primaryColor,
|
||||
colorScheme: const ColorScheme.light(
|
||||
secondary: _primaryColor,
|
||||
@@ -86,6 +93,10 @@ ThemeData lightTheme = ThemeData.light().copyWith(
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: _primaryColor,
|
||||
titleTextStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
selectedItemColor: _primaryColor,
|
||||
@@ -120,13 +131,15 @@ abstract class ThemeColors {
|
||||
|
||||
Color pinColor();
|
||||
|
||||
Color buttonBgColor();
|
||||
|
||||
Map<String, TextStyle> codeEditorTheme();
|
||||
}
|
||||
|
||||
class LightThemeColors extends ThemeColors {
|
||||
@override
|
||||
Color taskTitleColor() {
|
||||
return Color(0xff333333);
|
||||
return const Color(0xff333333);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -141,13 +154,18 @@ class LightThemeColors extends ThemeColors {
|
||||
|
||||
@override
|
||||
Color descColor() {
|
||||
return Color(0xff999999);
|
||||
return const Color(0xff999999);
|
||||
}
|
||||
|
||||
@override
|
||||
Color settingBgColor() {
|
||||
return Colors.white;
|
||||
}
|
||||
|
||||
@override
|
||||
Color buttonBgColor() {
|
||||
return _primaryColor;
|
||||
}
|
||||
}
|
||||
|
||||
class DartThemeColors extends ThemeColors {
|
||||
@@ -168,11 +186,16 @@ class DartThemeColors extends ThemeColors {
|
||||
|
||||
@override
|
||||
Color descColor() {
|
||||
return Color(0xff999999);
|
||||
return const Color(0xff999999);
|
||||
}
|
||||
|
||||
@override
|
||||
Color settingBgColor() {
|
||||
return Colors.black;
|
||||
}
|
||||
|
||||
@override
|
||||
Color buttonBgColor() {
|
||||
return const Color(0xff333333);
|
||||
}
|
||||
}
|
||||
|
||||
2
lib/module/env/add_env_page.dart
vendored
2
lib/module/env/add_env_page.dart
vendored
@@ -185,7 +185,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
|
||||
envBean.name = _nameController.text;
|
||||
envBean.value = _valueController.text;
|
||||
envBean.remarks = _remarkController.text;
|
||||
HttpResponse<EnvBean> 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) {
|
||||
successDialog(context, "操作成功").then((value) {
|
||||
|
||||
38
lib/module/env/env_page.dart
vendored
38
lib/module/env/env_page.dart
vendored
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drag_and_drop_lists/drag_and_drop_lists.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -48,10 +50,12 @@ class _EnvPageState extends State<EnvPage> {
|
||||
return model.loadData(false);
|
||||
},
|
||||
child: ReorderableListView(
|
||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
header: searchCell(ref),
|
||||
onReorder: (int oldIndex, int newIndex) {
|
||||
if (list.length != model.list.length) {
|
||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||
WidgetsBinding.instance
|
||||
?.addPostFrameCallback((timeStamp) {
|
||||
failDialog(context, "请先清空搜索关键词");
|
||||
});
|
||||
return;
|
||||
@@ -101,21 +105,19 @@ class _EnvPageState extends State<EnvPage> {
|
||||
vertical: 5,
|
||||
),
|
||||
suffixInsets: const EdgeInsets.only(
|
||||
top: 8,
|
||||
bottom: 8,
|
||||
right: 15,
|
||||
),
|
||||
prefixInsets: const EdgeInsets.only(
|
||||
top: 10,
|
||||
prefixInsets: EdgeInsets.only(
|
||||
top: Platform.isAndroid ? 10 : 6,
|
||||
bottom: 6,
|
||||
left: 15,
|
||||
),
|
||||
placeholderStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
color: context.watch(themeProvider).themeColor.descColor(),
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
),
|
||||
placeholder: "搜索",
|
||||
),
|
||||
@@ -143,7 +145,8 @@ class EnvItemCell extends StatelessWidget {
|
||||
backgroundColor: Colors.grey,
|
||||
flex: 1,
|
||||
onPressed: (_) {
|
||||
Navigator.of(context).pushNamed(Routes.route_AddEnv, arguments: bean);
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.route_AddEnv, arguments: bean);
|
||||
},
|
||||
foregroundColor: Colors.white,
|
||||
icon: CupertinoIcons.pencil,
|
||||
@@ -155,7 +158,9 @@ class EnvItemCell extends StatelessWidget {
|
||||
enableEnv();
|
||||
},
|
||||
foregroundColor: Colors.white,
|
||||
icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
||||
icon: bean.status == 0
|
||||
? Icons.dnd_forwardslash
|
||||
: Icons.check_circle_outline_sharp,
|
||||
),
|
||||
SlidableAction(
|
||||
backgroundColor: Colors.red,
|
||||
@@ -195,7 +200,12 @@ class EnvItemCell extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: bean.status == 1 ? const Color(0xffF85152) : ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: bean.status == 1
|
||||
? const Color(0xffF85152)
|
||||
: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
@@ -211,7 +221,10 @@ class EnvItemCell extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.descColor(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
@@ -228,7 +241,8 @@ class EnvItemCell extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||
color:
|
||||
ref.watch(themeProvider).themeColor.descColor(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/routes.dart';
|
||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||
@@ -9,6 +10,8 @@ import 'package:qinglong_app/main.dart';
|
||||
import 'package:qinglong_app/module/login/login_viewmodel.dart';
|
||||
import 'package:qinglong_app/utils/utils.dart';
|
||||
|
||||
import 'login_bean.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -17,7 +20,8 @@ class LoginPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<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();
|
||||
|
||||
@@ -30,189 +34,195 @@ class _LoginPageState extends State<LoginPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Consumer(builder: (context, ref, child) {
|
||||
var model = ref.watch<LoginViewModel>(loginProvider);
|
||||
|
||||
if (model.loginSuccess) {
|
||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||
Navigator.of(context).popAndPushNamed(Routes.route_HomePage);
|
||||
});
|
||||
}
|
||||
if (model.msg.isNotEmpty) {
|
||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||
failDialog(context, model.msg);
|
||||
model.msg = "";
|
||||
});
|
||||
}
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/login_bg.png",
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
body: SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/login_bg.png",
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 40,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 10,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/login_tip.png",
|
||||
height: 45,
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 40,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 10,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/login_tip.png",
|
||||
height: 45,
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
top: 10,
|
||||
left: 0,
|
||||
child: Text(
|
||||
"登录",
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
top: 10,
|
||||
left: 0,
|
||||
child: Text(
|
||||
"登录",
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/ql.png",
|
||||
height: 45,
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 0,
|
||||
child: Image.asset(
|
||||
"assets/images/ql.png",
|
||||
height: 45,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 10,
|
||||
),
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 10,
|
||||
),
|
||||
const Text(
|
||||
"域名:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
const Text(
|
||||
"域名:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _hostController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "http://1.1.1.1:5700",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
"用户名:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _hostController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "http://1.1.1.1:5700",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _userNameController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入用户名",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
"密码:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
const Text(
|
||||
"用户名:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入密码",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _userNameController,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入用户名",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const Text(
|
||||
"密码:",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||
hintText: "请输入密码",
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 80,
|
||||
child: IgnorePointer(
|
||||
ignoring: _hostController.text.isEmpty || _userNameController.text.isEmpty || _passwordController.text.isEmpty || model.isLoading,
|
||||
child: CupertinoButton(
|
||||
color: (_hostController.text.isNotEmpty &&
|
||||
_userNameController.text.isNotEmpty &&
|
||||
_passwordController.text.isNotEmpty &&
|
||||
!model.isLoading)
|
||||
? Theme.of(context).primaryColor
|
||||
: Theme.of(context).primaryColor.withOpacity(0.4),
|
||||
child: model.isLoading
|
||||
? const CupertinoActivityIndicator()
|
||||
: const Text(
|
||||
"登 录",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
autofocus: false,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 80,
|
||||
child: IgnorePointer(
|
||||
ignoring: _hostController.text.isEmpty ||
|
||||
_userNameController.text.isEmpty ||
|
||||
_passwordController.text.isEmpty ||
|
||||
isLoading,
|
||||
child: CupertinoButton(
|
||||
color: (_hostController.text.isNotEmpty &&
|
||||
_userNameController.text.isNotEmpty &&
|
||||
_passwordController.text.isNotEmpty &&
|
||||
!isLoading)
|
||||
? Theme.of(context).primaryColor
|
||||
: Theme.of(context)
|
||||
.primaryColor
|
||||
.withOpacity(0.4),
|
||||
child: isLoading
|
||||
? const CupertinoActivityIndicator()
|
||||
: const Text(
|
||||
"登 录",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
onPressed: () {
|
||||
Http.pushedLoginPage = false;
|
||||
Utils.hideKeyBoard(context);
|
||||
getIt<UserInfoViewModel>().updateHost(_hostController.text);
|
||||
model.login(_userNameController.text, _passwordController.text);
|
||||
}),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Http.pushedLoginPage = false;
|
||||
Utils.hideKeyBoard(context);
|
||||
getIt<UserInfoViewModel>()
|
||||
.updateHost(_hostController.text);
|
||||
login(_userNameController.text,
|
||||
_passwordController.text);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
Future<void> login(String userName, String password) async {
|
||||
isLoading = true;
|
||||
setState(() {});
|
||||
HttpResponse<LoginBean> response = await Api.login(userName, password);
|
||||
if (response.success) {
|
||||
getIt<UserInfoViewModel>().updateToken(response.bean?.token ?? "");
|
||||
Navigator.of(context).pushReplacementNamed(Routes.route_HomePage);
|
||||
} else {
|
||||
failDialog(context, response.message ?? "请检查网络情况");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,11 @@ import 'login_bean.dart';
|
||||
var loginProvider = ChangeNotifierProvider((ref) => LoginViewModel());
|
||||
|
||||
class LoginViewModel extends ViewModel {
|
||||
bool loginSuccess = false;
|
||||
bool isLoading = false;
|
||||
String msg = "";
|
||||
|
||||
Future<void> login(String userName, String password) async {
|
||||
isLoading = true;
|
||||
loginSuccess = false;
|
||||
msg = "";
|
||||
|
||||
notifyListeners();
|
||||
@@ -25,11 +23,9 @@ class LoginViewModel extends ViewModel {
|
||||
|
||||
if (response.success) {
|
||||
getIt<UserInfoViewModel>().updateToken(response.bean?.token ?? "");
|
||||
loginSuccess = true;
|
||||
isLoading = false;
|
||||
} else {
|
||||
isLoading = false;
|
||||
loginSuccess = false;
|
||||
msg = response.message ?? "";
|
||||
}
|
||||
notifyListeners();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:qinglong_app/base/routes.dart';
|
||||
import 'package:qinglong_app/base/theme.dart';
|
||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||
import 'package:qinglong_app/main.dart';
|
||||
|
||||
class OtherPage extends ConsumerStatefulWidget {
|
||||
const OtherPage({Key? key}) : super(key: key);
|
||||
@@ -36,16 +39,21 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 15,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 12,
|
||||
bottom: 8,
|
||||
left: 15,
|
||||
right: 15,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"查看日志",
|
||||
"脚本管理",
|
||||
style: TextStyle(
|
||||
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
@@ -57,7 +65,7 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
const Divider(
|
||||
indent: 15,
|
||||
),
|
||||
Padding(
|
||||
@@ -68,9 +76,12 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"查看日志",
|
||||
"依赖管理",
|
||||
style: TextStyle(
|
||||
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
@@ -82,7 +93,7 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
const Divider(
|
||||
indent: 15,
|
||||
),
|
||||
Padding(
|
||||
@@ -93,9 +104,40 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"查看日志",
|
||||
"任务日志",
|
||||
style: TextStyle(
|
||||
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
indent: 15,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10,
|
||||
horizontal: 15,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"登录日志",
|
||||
style: TextStyle(
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
@@ -128,7 +170,7 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5,
|
||||
bottom: 0,
|
||||
bottom: 5,
|
||||
left: 15,
|
||||
right: 15,
|
||||
),
|
||||
@@ -139,7 +181,10 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
||||
Text(
|
||||
"夜间模式",
|
||||
style: TextStyle(
|
||||
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
@@ -152,59 +197,26 @@ 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,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(
|
||||
CupertinoIcons.right_chevron,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 40,
|
||||
child: CupertinoButton(
|
||||
color: ref.watch(themeProvider).themeColor.buttonBgColor(),
|
||||
child: const Text(
|
||||
"退出登录",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
getIt<UserInfoViewModel>().updateToken("");
|
||||
Navigator.of(context).pushReplacementNamed(Routes.route_LOGIN);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_highlight/theme_map.dart';
|
||||
@@ -102,7 +104,8 @@ class _TaskPageState extends State<TaskPage> {
|
||||
if (_searchController.text.isEmpty ||
|
||||
(item.name?.contains(_searchController.text) ?? false) ||
|
||||
(item.command?.contains(_searchController.text) ?? false) ||
|
||||
(item.schedule?.contains(_searchController.text) ?? false)) {
|
||||
(item.schedule?.contains(_searchController.text) ??
|
||||
false)) {
|
||||
return TaskItemCell(item, ref);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
@@ -136,21 +139,19 @@ class _TaskPageState extends State<TaskPage> {
|
||||
vertical: 5,
|
||||
),
|
||||
suffixInsets: const EdgeInsets.only(
|
||||
top: 8,
|
||||
bottom: 8,
|
||||
right: 15,
|
||||
),
|
||||
prefixInsets: const EdgeInsets.only(
|
||||
top: 10,
|
||||
prefixInsets: EdgeInsets.only(
|
||||
top: Platform.isAndroid ? 10 : 6,
|
||||
bottom: 6,
|
||||
left: 15,
|
||||
),
|
||||
placeholderStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
color: context.watch(themeProvider).themeColor.descColor(),
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
),
|
||||
placeholder: "搜索",
|
||||
),
|
||||
@@ -174,7 +175,9 @@ class TaskItemCell extends StatelessWidget {
|
||||
child: Text(
|
||||
bean.status! == 1 ? "运行" : "停止运行",
|
||||
),
|
||||
trailingIcon: bean.status! == 1 ? CupertinoIcons.memories : CupertinoIcons.stop_circle,
|
||||
trailingIcon: bean.status! == 1
|
||||
? CupertinoIcons.memories
|
||||
: CupertinoIcons.stop_circle,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
startCron(context, ref);
|
||||
@@ -192,7 +195,8 @@ class TaskItemCell extends StatelessWidget {
|
||||
child: const Text("编辑"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed(Routes.route_AddTask, arguments: bean);
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.route_AddTask, arguments: bean);
|
||||
},
|
||||
trailingIcon: CupertinoIcons.pencil_outline,
|
||||
),
|
||||
@@ -202,7 +206,9 @@ class TaskItemCell extends StatelessWidget {
|
||||
Navigator.of(context).pop();
|
||||
pinTask();
|
||||
},
|
||||
trailingIcon: bean.isPinned! == 0 ? CupertinoIcons.pin : CupertinoIcons.pin_slash,
|
||||
trailingIcon: bean.isPinned! == 0
|
||||
? CupertinoIcons.pin
|
||||
: CupertinoIcons.pin_slash,
|
||||
),
|
||||
QLCupertinoContextMenuAction(
|
||||
child: Text(bean.isDisabled! == 0 ? "禁用" : "启用"),
|
||||
@@ -211,7 +217,9 @@ class TaskItemCell extends StatelessWidget {
|
||||
enableTask();
|
||||
},
|
||||
isDestructiveAction: true,
|
||||
trailingIcon: bean.isDisabled! == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
||||
trailingIcon: bean.isDisabled! == 0
|
||||
? Icons.dnd_forwardslash
|
||||
: Icons.check_circle_outline_sharp,
|
||||
),
|
||||
QLCupertinoContextMenuAction(
|
||||
child: const Text("删除"),
|
||||
@@ -232,7 +240,9 @@ class TaskItemCell extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: bean.isDisabled == 1 ? const Color(0xffF85152) : ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: bean.isDisabled == 1
|
||||
? const Color(0xffF85152)
|
||||
: ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
@@ -244,7 +254,9 @@ class TaskItemCell extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
color: bean.isPinned == 1 ? ref.watch(themeProvider).themeColor.pinColor() : Colors.transparent,
|
||||
color: bean.isPinned == 1
|
||||
? ref.watch(themeProvider).themeColor.pinColor()
|
||||
: Colors.transparent,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15,
|
||||
vertical: 8,
|
||||
@@ -264,7 +276,12 @@ class TaskItemCell extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: bean.isDisabled == 1 ? const Color(0xffF85152) : ref.watch(themeProvider).themeColor.taskTitleColor(),
|
||||
color: bean.isDisabled == 1
|
||||
? const Color(0xffF85152)
|
||||
: ref
|
||||
.watch(themeProvider)
|
||||
.themeColor
|
||||
.taskTitleColor(),
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
@@ -285,11 +302,16 @@ class TaskItemCell extends StatelessWidget {
|
||||
Material(
|
||||
color: Colors.transparent,
|
||||
child: Text(
|
||||
(bean.lastExecutionTime == null || bean.lastExecutionTime == 0) ? "-" : Utils.formatMessageTime(bean.lastExecutionTime!),
|
||||
(bean.lastExecutionTime == null ||
|
||||
bean.lastExecutionTime == 0)
|
||||
? "-"
|
||||
: Utils.formatMessageTime(
|
||||
bean.lastExecutionTime!),
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||
color:
|
||||
ref.watch(themeProvider).themeColor.descColor(),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
@@ -410,7 +432,8 @@ class TaskItemCell extends StatelessWidget {
|
||||
child: const Text('编辑'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.of(context).pushNamed(Routes.route_AddTask, arguments: bean);
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.route_AddTask, arguments: bean);
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
|
||||
@@ -40,7 +40,7 @@ const qinglongLightTheme = {
|
||||
|
||||
const qinglongDarkTheme = {
|
||||
'root':
|
||||
TextStyle(color: Color(0xff333333), backgroundColor: Color(0xff2E312E)),
|
||||
TextStyle(color: Color(0xff333333), backgroundColor: Colors.black),
|
||||
'comment': TextStyle(color: Color(0xff999988), fontStyle: FontStyle.italic),
|
||||
'quote': TextStyle(color: Color(0xff999988), fontStyle: FontStyle.italic),
|
||||
'keyword': TextStyle(color: Color(0xff333333), fontWeight: FontWeight.bold),
|
||||
|
||||
Reference in New Issue
Block a user