登录页面样式

This commit is contained in:
GYJ 2024-11-25 14:11:57 +08:00
parent b84d8477c0
commit 2f1eb7abc4
9 changed files with 401 additions and 88 deletions

View File

@ -1,3 +1,4 @@
import 'package:cashier_reserve/common/push/push.dart';
import 'package:cashier_reserve/login/login_view.dart';
import '../base/ui.dart';
@ -38,13 +39,15 @@ class AppManager {
Navigator.of(globalContext!).pop();
}
showDialog(
context: globalContext!,
barrierDismissible: false,
builder: (BuildContext context) {
return WillPopScope(
onWillPop: () => Future.value(false), child: const LoginView());
});
YJPush.presentWidget(globalContext!, const LoginView());
// showDialog(
// context: globalContext!,
// barrierDismissible: false,
// builder: (BuildContext context) {
// return WillPopScope(
// onWillPop: () => Future.value(false), child: const LoginView());
// });
}
static void disposeLoginWidget() {
@ -54,4 +57,8 @@ class AppManager {
static bool isShowLoginView() {
return _isAlertLogin;
}
static String getUserToken() {
return HiveManager.getUserToken();
}
}

View File

@ -1,6 +1,8 @@
import 'package:flutter/foundation.dart';
const bool inProduction = !kDebugMode;
void yjPrint(Object? object) {
if (kDebugMode) {
print(object);

View File

@ -0,0 +1,75 @@
import 'package:cashier_reserve/common/manager/app_manager.dart';
import 'package:cashier_reserve/common/print/print.dart';
import 'package:dio/dio.dart';
import '../utils/utils.dart';
const String kBaseUrl = 'https://admintestpapi.sxczgkj.cn';
const kSuccessCode = 200;
const kNeedLoginCode = 401;
class RequestManager {
/// HttpClient
static final Dio _c = Dio(BaseOptions(
baseUrl: kBaseUrl,
connectTimeout: const Duration(milliseconds: 5000),
receiveTimeout: const Duration(milliseconds: 5000)
));
/// GET
static Future<dynamic> get(String url, {bool catchError = true}) {
return _doRequest("GET", url, catchError: catchError);
}
/// DELETE
static Future<dynamic> delete(String url, {bool catchError = true}) {
return _doRequest("DELETE", url, catchError: catchError);
}
/// POST
static Future<dynamic> post(String url, Map<String, dynamic>? body,
{bool catchError = true}) {
return _doRequest("POST", url, body: body, catchError: catchError);
}
/// PUT
static Future<dynamic> put(String url, Map<String, dynamic>? body,
{bool catchError = true}) {
return _doRequest("PUT", url, body: body, catchError: catchError);
}
static Future<dynamic> _doRequest(String method, String url,
{Map<String, dynamic>? body, required bool catchError}) async {
yjPrint("[RequestManager req]: $method$url】body === $body");
try {
final resp = await _c.request(url,
data: body,
options: Options(
method: method,
headers: {"authorization": "Bearer ${AppManager.getUserToken()}"}));
yjPrint("[RequestManager resp]: $method$url】body === $resp");
if (catchError) {
if (resp.statusCode == kNeedLoginCode) {
AppManager.gotoLogin();
return null;
}
if (resp.statusCode != kSuccessCode) {
_alertError("提示", resp.data ?? "未知错误");
return null;
}
}
return resp.data;
} catch (e) {
yjPrint("[RequestManager error]: $method$url】error === $e");
// _alertError("网络错误", "请检查您的网络连接!");
return null;
}
}
static _alertError(String title, String errorText) {
Utils.alert(AppManager.globalContext!, errorText, title: title);
}
}

View File

@ -0,0 +1,47 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'func_tools.dart';
class Utils {
///11+8
static bool isPhone(String phone) {
return RegExp('^1\\d{10}\$').hasMatch(phone);
}
static void toast(String? text, BuildContext? context) {
if (isEmptyString(text)) {
return;
}
Fluttertoast.showToast(
msg: "$text",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
// backgroundColor: Colors.red,
// textColor: Colors.white,
fontSize: 16.0);
}
static Future alert(BuildContext context, String? content, {String? title}) {
return showCupertinoDialog(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text(title ?? '提示'),
content: Text(content!),
actions: <Widget>[
TextButton(
child: const Text('确定'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
}

View File

@ -48,12 +48,14 @@ class HomeView extends BaseUI {
return Container(
color: const Color(0xff1D2227),
width: leftBarWidth,
child: Column(
children: _buildDestinations(
context,
provider,
leftBarWidth,
itemHeight,
child: SingleChildScrollView(
child: Column(
children: _buildDestinations(
context,
provider,
leftBarWidth,
itemHeight,
),
),
),
);

View File

@ -1,4 +1,8 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:cashier_reserve/common/print/print.dart';
import 'package:cashier_reserve/model/login_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -20,6 +24,35 @@ class _LoginViewState extends State<LoginView> {
TextEditingController passwordText = TextEditingController();
TextEditingController codeText = TextEditingController();
String authCodeUuid = "";
String authCodeImg = "";
@override
void initState() {
super.initState();
_loadAuthCode();
}
void _loadAuthCode() async {
var res = await LoginModel.getLoginAuthCode();
if (res is Map) {
Map<String, dynamic> result = res as Map<String, dynamic>;
setState(() {
authCodeUuid = result["uuid"] ?? "";
String img = result["img"] ?? "";
if (img.startsWith("data:image/png;base64,")) {
authCodeImg = img.substring("data:image/png;base64,".length);
}
});
} else {
yjPrint("获取验证码失败");
}
}
void _goLogin() async {}
@override
void dispose() {
merchantText.dispose();
@ -31,89 +64,211 @@ class _LoginViewState extends State<LoginView> {
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: const Color(0x55000000),
child: Center(
return Scaffold(
backgroundColor: Colors.black.withOpacity(0.2),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
padding: const EdgeInsets.fromLTRB(30, 30, 30, 30),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
width: 400,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"银收客订餐系统",
style: TextStyle(
fontSize: 25,
color: Color(0xff333333),
decoration: TextDecoration.none),
)
],
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: const Color(0x55000000),
child: Center(
child: Container(
padding: const EdgeInsets.fromLTRB(30, 30, 30, 30),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
const SizedBox(
height: 30,
),
CupertinoSegmentedControl(
//
children: {
0: Container(
width: 60,
height: 30,
alignment: Alignment.center,
child: const Text(
"商户",
style: TextStyle(
fontSize: 14,
// color: Color(0xff333333),
decoration: TextDecoration.none),
width: 400,
// height: 400,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTitle(context),
const SizedBox(
height: 30,
),
),
1: Container(
width: 60,
height: 30,
alignment: Alignment.center,
child: const Text(
"员工",
style: TextStyle(
fontSize: 14,
// color: Color(0xff333333),
decoration: TextDecoration.none),
_buildSegment(context),
const SizedBox(
height: 5,
),
),
},
//
groupValue: segmentIndex,
//
onValueChanged: (int index) {
setState(() {
segmentIndex = index;
loginType = index == 0 ? "merchant" : "staff";
});
},
selectedColor: Colors.blue,
borderColor: Colors.blue,
unselectedColor: Colors.white,
_buildInputTextField(context, merchantText,
hintText: "请输入商户号",
icon: Icons.store_sharp,
isHidden: loginType == "merchant"),
_buildInputTextField(context, accountText,
hintText: "请输入账号", icon: Icons.people),
_buildInputTextField(context, passwordText,
hintText: "请输入密码", icon: Icons.lock, isPassword: true),
_buildInputTextField(context, codeText,
hintText: "请输入验证码",
icon: Icons.admin_panel_settings_sharp,
isCode: true),
_buildLoginBtn(context),
],
),
),
const SizedBox(
height: 5,
),
// TextField(
// controller: merchantText,
// )
],
),
),
),
),
);
}
Widget _buildLoginBtn(BuildContext context) {
return InkWell(
onTap: () {
_goLogin();
},
child: Container(
margin: const EdgeInsets.only(top: 25),
height: 35,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(5),
),
child: const Center(
child: Text(
"登录",
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
),
);
}
Widget _buildTitle(BuildContext context) {
return const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"银收客订餐系统",
style: TextStyle(
fontSize: 25,
color: Color(0xff333333),
decoration: TextDecoration.none),
)
],
);
}
Widget _buildSegment(BuildContext context) {
return CupertinoSegmentedControl(
//
children: {
0: Container(
width: 60,
height: 30,
alignment: Alignment.center,
child: const Text(
"商户",
style: TextStyle(
fontSize: 14,
// color: Color(0xff333333),
decoration: TextDecoration.none),
),
),
1: Container(
width: 60,
height: 30,
alignment: Alignment.center,
child: const Text(
"员工",
style: TextStyle(
fontSize: 14,
// color: Color(0xff333333),
decoration: TextDecoration.none),
),
),
},
//
groupValue: segmentIndex,
//
onValueChanged: (int index) {
setState(() {
segmentIndex = index;
loginType = index == 0 ? "merchant" : "staff";
});
},
selectedColor: Colors.blue,
borderColor: Colors.blue,
unselectedColor: Colors.white,
);
}
Widget _buildInputTextField(
BuildContext context,
TextEditingController controller, {
String hintText = "",
IconData icon = Icons.people,
bool isPassword = false,
bool isHidden = false,
bool isCode = false,
}) {
if (isHidden) {
return Container();
}
return Column(
children: [
const SizedBox(
height: 10,
),
Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: const Color(0xffefefef), width: 1),
borderRadius: BorderRadius.circular(5),
),
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 35,
child: TextField(
controller: controller,
obscureText: isPassword,
decoration: InputDecoration(
icon: Icon(
icon,
color: const Color(0xffa6a6a6),
),
hintText: hintText,
hintStyle: const TextStyle(
fontSize: 14,
color: Color(0xff999999),
),
contentPadding: EdgeInsets.zero,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(5),
),
),
),
),
),
if (isCode)
InkWell(
onTap: () {
_loadAuthCode();
},
child: Container(
margin: const EdgeInsets.only(left: 15),
width: 100,
height: 35,
child: Image.memory(base64ToUint8List(authCodeImg)),
),
)
],
),
],
);
}
Uint8List base64ToUint8List(String base64String) {
const decoder = Base64Decoder();
return decoder.convert(base64String);
}
}

View File

@ -0,0 +1,11 @@
import 'package:cashier_reserve/common/print/print.dart';
import 'package:cashier_reserve/common/request/request_manager.dart';
class LoginModel {
///
static Future<dynamic> getLoginAuthCode() async {
final r = await RequestManager.get("/auth/code");
return r;
}
}

View File

@ -221,6 +221,19 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
fluttertoast:
dependency: "direct main"
description:
name: fluttertoast
sha256: "95f349437aeebe524ef7d6c9bde3e6b4772717cf46a0eb6a3ceaddc740b297cc"
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.2.8"
glob:
dependency: transitive
description:

View File

@ -45,6 +45,7 @@ dependencies:
hive: ^4.0.0-dev.2
isar_flutter_libs: ^4.0.0-dev.13
path_provider: ^2.1.0
fluttertoast: ^8.2.8
dev_dependencies:
flutter_test: