add checkbox

This commit is contained in:
jyuesong
2022-01-18 10:10:03 +08:00
parent 074580952f
commit a6208ea5f2
8 changed files with 273 additions and 233 deletions

View File

@@ -1,3 +1,5 @@
String sp_UserINfo = "userinfo";
String sp_Host = "host";
String sp_Theme = "dart_mode";
String spUserInfo = "userinfo";
String spHost = "host";
String spUserName = "username";
String spPassWord = "password";
String spTheme = "dart_mode";

View File

@@ -21,11 +21,11 @@ class ThemeViewModel extends ChangeNotifier {
}
bool isInDartMode() {
return SpUtil.getBool(sp_Theme, defValue: false);
return SpUtil.getBool(spTheme, defValue: false);
}
void changeThemeReal(bool dark, [bool notify = true]) {
SpUtil.putBool(sp_Theme, dark);
SpUtil.putBool(spTheme, dark);
if (!dark) {
currentTheme = lightTheme;
themeColor = LightThemeColors();
@@ -39,7 +39,7 @@ class ThemeViewModel extends ChangeNotifier {
}
void changeTheme() {
changeThemeReal(!SpUtil.getBool(sp_Theme, defValue: false), true);
changeThemeReal(!SpUtil.getBool(spTheme, defValue: false), true);
}
}
@@ -76,6 +76,20 @@ ThemeData darkTheme = ThemeData.dark().copyWith(
secondary: _primaryColor,
primary: _primaryColor,
),
toggleableActiveColor: _primaryColor,
checkboxTheme: CheckboxThemeData(
checkColor: MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return Colors.transparent;
}
if (states.contains(MaterialState.selected)) {
return Colors.white;
}
return Colors.white;
},
),
),
);
ThemeData lightTheme = ThemeData.light().copyWith(
brightness: Brightness.light,
@@ -122,6 +136,20 @@ ThemeData lightTheme = ThemeData.light().copyWith(
borderSide: BorderSide(color: _primaryColor),
),
),
toggleableActiveColor: _primaryColor,
checkboxTheme: CheckboxThemeData(
checkColor: MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return Colors.transparent;
}
if (states.contains(MaterialState.selected)) {
return Colors.white;
}
return Colors.black;
},
),
),
);
abstract class ThemeColors {

View File

@@ -5,10 +5,14 @@ import 'sp_const.dart';
class UserInfoViewModel {
String? _token;
String? _host = "";
String? _userName;
String? _passWord;
UserInfoViewModel() {
String userInfoJson = SpUtil.getString(sp_UserINfo);
_host = SpUtil.getString(sp_Host, defValue: "http://49.234.59.95:5700");
String userInfoJson = SpUtil.getString(spUserInfo);
_userName = SpUtil.getString(spUserName);
_passWord = SpUtil.getString(spPassWord);
_host = SpUtil.getString(spHost, defValue: "http://49.234.59.95:5700");
if (userInfoJson.isNotEmpty) {
_token = userInfoJson;
}
@@ -16,18 +20,29 @@ class UserInfoViewModel {
void updateToken(String token) {
_token = token;
SpUtil.putString(sp_UserINfo, token);
SpUtil.putString(spUserInfo, token);
}
void updateUserName(String userName, String password) {
_userName = userName;
_passWord = password;
SpUtil.putString(spUserName, userName);
SpUtil.putString(spPassWord, password);
}
void updateHost(String host) {
_host = host;
SpUtil.putString(sp_Host, host);
SpUtil.putString(spHost, host);
}
String? get token => _token;
String? get host => _host;
String? get userName => _userName;
String? get passWord => _passWord;
bool isLogined() {
return token != null && token!.isNotEmpty;
}

View File

@@ -67,110 +67,112 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
)
],
),
body: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
const Text(
"名称:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
body: SingleChildScrollView(
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 SizedBox(
height: 10,
),
TextField(
controller: _nameController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入名称",
const Text(
"名称:",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
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.w600,
const SizedBox(
height: 10,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _valueController,
maxLines: 8,
minLines: 1,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入值",
TextField(
controller: _nameController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入名称",
),
autofocus: false,
),
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.w600,
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _remarkController,
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: 10,
),
TextField(
controller: _valueController,
maxLines: 8,
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.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
controller: _remarkController,
decoration: const InputDecoration(
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
hintText: "请输入备注",
),
autofocus: false,
),
],
),
),
],
),
),
);
}

View File

@@ -20,14 +20,25 @@ 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();
bool rememberPassword = false;
@override
void initState() {
super.initState();
if (getIt<UserInfoViewModel>().userName != null && getIt<UserInfoViewModel>().userName!.isNotEmpty) {
_userNameController.text = getIt<UserInfoViewModel>().userName!;
rememberPassword = true;
} else {
rememberPassword = false;
}
if (getIt<UserInfoViewModel>().passWord != null && getIt<UserInfoViewModel>().passWord!.isNotEmpty) {
_passwordController.text = getIt<UserInfoViewModel>().passWord!;
}
getIt<UserInfoViewModel>().updateToken("");
}
@@ -96,7 +107,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 10,
height: MediaQuery.of(context).size.height / 15,
),
const Text(
"域名:",
@@ -105,9 +116,6 @@ class _LoginPageState extends ConsumerState<LoginPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
onChanged: (_) {
setState(() {});
@@ -120,7 +128,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
autofocus: false,
),
const SizedBox(
height: 20,
height: 15,
),
const Text(
"用户名:",
@@ -129,9 +137,6 @@ class _LoginPageState extends ConsumerState<LoginPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
onChanged: (_) {
setState(() {});
@@ -144,7 +149,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
autofocus: false,
),
const SizedBox(
height: 20,
height: 15,
),
const Text(
"密码:",
@@ -153,9 +158,6 @@ class _LoginPageState extends ConsumerState<LoginPage> {
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
TextField(
onChanged: (_) {
setState(() {});
@@ -168,28 +170,41 @@ class _LoginPageState extends ConsumerState<LoginPage> {
),
autofocus: false,
),
const SizedBox(
height: 10,
),
Row(
children: [
Checkbox(
value: rememberPassword,
onChanged: (checked) {
rememberPassword = checked ?? false;
setState(() {});
},
),
const Text(
"记住密码",
style: TextStyle(
fontSize: 14,
),
),
],
),
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,
ignoring: _hostController.text.isEmpty || _userNameController.text.isEmpty || _passwordController.text.isEmpty || isLoading,
child: CupertinoButton(
color: (_hostController.text.isNotEmpty &&
_userNameController.text.isNotEmpty &&
_passwordController.text.isNotEmpty &&
!isLoading)
? ref
.watch(themeProvider)
.themeColor
.buttonBgColor()
: Theme.of(context)
.primaryColor
.withOpacity(0.4),
padding: const EdgeInsets.symmetric(
vertical: 5,
),
color:
(_hostController.text.isNotEmpty && _userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty && !isLoading)
? ref.watch(themeProvider).themeColor.buttonBgColor()
: Theme.of(context).primaryColor.withOpacity(0.4),
child: isLoading
? const CupertinoActivityIndicator()
: const Text(
@@ -199,12 +214,14 @@ class _LoginPageState extends ConsumerState<LoginPage> {
),
),
onPressed: () {
if (rememberPassword) {
getIt<UserInfoViewModel>().updateUserName(_userNameController.text, _passwordController.text);
}
Http.pushedLoginPage = false;
Utils.hideKeyBoard(context);
getIt<UserInfoViewModel>()
.updateHost(_hostController.text);
login(_userNameController.text,
_passwordController.text);
getIt<UserInfoViewModel>().updateHost(_hostController.text);
login(_userNameController.text, _passwordController.text);
}),
),
),

View File

@@ -204,6 +204,7 @@ class _OtherPageState extends ConsumerState<OtherPage> {
child: SizedBox(
width: MediaQuery.of(context).size.width - 40,
child: CupertinoButton(
padding: const EdgeInsets.symmetric(vertical: 5,),
color: ref.watch(themeProvider).themeColor.buttonBgColor(),
child: const Text(
"退出登录",

View File

@@ -104,8 +104,7 @@ 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();
@@ -175,9 +174,7 @@ 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);
@@ -195,8 +192,7 @@ class TaskItemCell extends StatelessWidget {
child: const Text("编辑"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context)
.pushNamed(Routes.routeAddTask, arguments: bean);
Navigator.of(context).pushNamed(Routes.routeAddTask, arguments: bean);
},
trailingIcon: CupertinoIcons.pencil_outline,
),
@@ -206,9 +202,7 @@ 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 ? "禁用" : "启用"),
@@ -217,9 +211,7 @@ 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("删除"),
@@ -233,19 +225,32 @@ class TaskItemCell extends StatelessWidget {
],
previewBuilder: (context, anima, child) {
return IntrinsicWidth(
child: Material(
color: Colors.transparent,
child: Text(
bean.name ?? "",
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: bean.isDisabled == 1
? const Color(0xffF85152)
: ref.watch(themeProvider).themeColor.taskTitleColor(),
fontSize: 18,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Material(
color: Colors.transparent,
child: Text(
bean.name ?? "",
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
fontSize: 18,
),
),
),
),
const SizedBox(
width: 5,
),
bean.isDisabled == 1
? const Icon(
Icons.dnd_forwardslash,
size: 16,
color: Colors.red,
)
: const SizedBox.shrink(),
],
),
);
},
@@ -254,9 +259,7 @@ 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,
@@ -276,12 +279,7 @@ class TaskItemCell extends StatelessWidget {
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: bean.isDisabled == 1
? const Color(0xffF85152)
: ref
.watch(themeProvider)
.themeColor
.taskTitleColor(),
color: ref.watch(themeProvider).themeColor.taskTitleColor(),
fontSize: 18,
),
),
@@ -302,16 +300,11 @@ 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,
),
),
@@ -321,17 +314,31 @@ class TaskItemCell extends StatelessWidget {
const SizedBox(
height: 8,
),
Material(
color: Colors.transparent,
child: Text(
bean.schedule ?? "",
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: ref.watch(themeProvider).themeColor.descColor(),
fontSize: 12,
Row(
children: [
Material(
color: Colors.transparent,
child: Text(
bean.schedule ?? "",
maxLines: 1,
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: ref.watch(themeProvider).themeColor.descColor(),
fontSize: 12,
),
),
),
),
const SizedBox(
width: 5,
),
bean.isDisabled == 1
? const Icon(
Icons.dnd_forwardslash,
size: 12,
color: Colors.red,
)
: const SizedBox.shrink(),
],
),
],
),
@@ -424,46 +431,6 @@ class TaskItemCell extends StatelessWidget {
});
}
more(BuildContext context, WidgetRef ref) {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) => CupertinoActionSheet(
title: const Text('更多操作'),
actions: <CupertinoActionSheetAction>[
CupertinoActionSheetAction(
child: const Text('编辑'),
onPressed: () {
Navigator.pop(context);
Navigator.of(context)
.pushNamed(Routes.routeAddTask, arguments: bean);
},
),
CupertinoActionSheetAction(
child: Text(bean.isDisabled! == 1 ? "启用" : "禁用"),
onPressed: () {
Navigator.pop(context);
enableTask();
},
),
CupertinoActionSheetAction(
child: const Text('删除'),
onPressed: () {
Navigator.pop(context);
delTask(context, ref);
},
),
CupertinoActionSheetAction(
child: Text(bean.isPinned! == 0 ? "置顶" : "取消置顶"),
onPressed: () {
Navigator.pop(context);
pinTask();
},
),
],
),
);
}
void enableTask() {
ref.read(taskProvider).enableTask(bean.sId!, bean.isDisabled!);
}

View File

@@ -33,9 +33,17 @@ class TaskViewModel extends BaseViewModel {
list.sort((a, b) {
return b.created!.compareTo(a.created!);
});
list.sort((a, b) {
return b.isPinned!.compareTo(a.isPinned!);
});
// list.sort((a, b) {
// return b.isPinned!.compareTo(a.isPinned!);
// });
for (int i = 0; i < list.length; i++) {
if (list[i].isPinned == 1) {
final TaskBean item = list.removeAt(i);
list.insert(0, item);
}
}
running.clear();
running.addAll(list.where((element) => element.status == 0));
disabled.clear();