Commit 695103c3 authored by 张宏's avatar 张宏

登录

parent c7d9fb26
......@@ -25,20 +25,13 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
Emitter<AuthState> emit,
) async {
emit(AuthLoading());
try {
// todo 这里暂定返回bool
// final success = await _authService.login(event.username, event.password);
final success = true;
if (success) {
final userInfo = const UserInfoBO(
username: "张三丰",
);
emit(AuthSuccess(userInfo));
} else {
emit(const AuthFailure('登录失败,请检查用户名和密码'));
}
try {
await _authService.login(event.username, event.password);
const userInfo = UserInfoBO(
username: "管理员",
);
emit(const AuthSuccess(userInfo));
} catch (e) {
emit(AuthFailure(e.toString()));
}
......
import 'package:equatable/equatable.dart';
class LoginBO extends Equatable {
final String? scope;
final String? openid;
final String? accessToken;
final String? refreshToken;
final int? expireIn;
final int? refreshExpireIn;
final String? clientId;
const LoginBO({
this.scope,
this.openid,
this.accessToken,
this.refreshToken,
this.expireIn,
this.refreshExpireIn,
this.clientId,
});
factory LoginBO.fromJson(Map<String, dynamic> json) {
return LoginBO(
scope: json['scope'] as String?,
openid: json['openid'] as String?,
accessToken: json['access_token'] as String?,
refreshToken: json['refresh_token'] as String?,
expireIn: json['expire_in'] as int?,
refreshExpireIn: json['refresh_expire_in'] as int?,
clientId: json['client_id'] as String?,
);
}
@override
List<Object?> get props => [
scope,
openid,
accessToken,
refreshToken,
expireIn,
refreshExpireIn,
clientId,
];
}
\ No newline at end of file
import '../utils/http/response_model.dart';
import '../utils/http/dio_request.dart';
import '../models/bo/login_bo.dart';
class AuthRepository {
Future<ResponseModel> login(Map<String, dynamic> params) {
return DioRequest.instance.post('/login', data: params);
Future<ResponseModel<LoginBO>> login(Map<String, dynamic> params) {
return DioRequest.instance.post<LoginBO>(
'/app/auth/login/password',
data: params,
fromJsonT: (data) => LoginBO.fromJson(data as Map<String, dynamic>),
);
}
}
import '../models/bo/login_bo.dart';
import '../repositories/auth_repository.dart';
import '../utils/constants.dart';
import '../utils/storage/storage_service.dart';
......@@ -12,27 +13,23 @@ class AuthService {
}) : _authRepository = authRepository,
_storageService = storageService;
Future<bool> login(String username, String password) async {
Future<LoginBO> login(String username, String password) async {
final result = await _authRepository.login({
'username': username,
'password': password,
});
if (result.success) {
final data = result.data;
if (data is Map<String, dynamic> && data.containsKey('token')) {
final token = data['token'] as String?;
if (token != null && token.isNotEmpty) {
await _storageService.saveToken(
token,
expiryHours: Constants.tokenExpiryHours,
);
return true;
}
if (result.success && result.data != null) {
final loginBO = result.data!;
if (loginBO.accessToken != null && loginBO.accessToken!.isNotEmpty) {
await _storageService.saveToken(
loginBO.accessToken!,
expiryHours: Constants.tokenExpiryHours,
);
}
return loginBO;
}
return false;
throw Exception(result.msg);
}
Future<bool> isTokenExpired() async {
......
class Constants {
// ==================== 环境配置 ====================
static const String baseUrl = 'http://localhost:8080';
static const String baseUrl = 'http://121.41.57.178:9090';
// ==================== 超时配置 ====================
static const int connectTimeout = 30000;
......
......@@ -327,9 +327,9 @@ class DioRequest {
if (response.data is Map<String, dynamic>) {
jsonData = Map<String, dynamic>.from(response.data);
// 如果响应中有token但没有data,把token放到data里
if (jsonData.containsKey('token') && !jsonData.containsKey('data')) {
jsonData['data'] = {'token': jsonData['token']};
}
// if (jsonData.containsKey('token') && !jsonData.containsKey('data')) {
// jsonData['data'] = {'token': jsonData['token']};
// }
} else {
jsonData = {
'code': response.statusCode ?? -1,
......
......@@ -41,7 +41,7 @@ class RequestInterceptor extends Interceptor {
}
void _printRequestLog(RequestOptions options, String uuid) {
print('========== Request START ==========');
print('==================== Request START ======================');
print('UUID: $uuid');
print('Method: ${options.method}');
print('URL: ${options.uri}');
......@@ -52,6 +52,6 @@ class RequestInterceptor extends Interceptor {
if (options.queryParameters.isNotEmpty) {
print('Params: ${options.queryParameters}');
}
print('========== Request END ==========');
print('==================== Request END ======================');
}
}
\ No newline at end of file
......@@ -11,10 +11,10 @@ class ResponseInterceptor extends Interceptor {
}
void _printResponseLog(Response response, String uuid) {
print('========== Response START ==========');
print('==================== Response START ======================');
print('UUID: $uuid');
print('Status Code: ${response.statusCode}');
print('Data: ${response.data}');
print('========== Response END ==========');
print('==================== Response END ======================');
}
}
\ No newline at end of file
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_event.dart';
import 'package:smart_hotel_app/blocs/auth/auth_state.dart';
import 'package:smart_hotel_app/utils/storage/storage_service.dart';
import 'package:smart_hotel_app/views/login/cubit/login_state.dart';
......@@ -11,7 +12,21 @@ class LoginCubit extends Cubit<LoginState> {
LoginCubit({
required this.authBloc,
required this.storageService,
}) : super(const LoginState());
}) : super(const LoginState()) {
_listenAuthState();
}
void _listenAuthState() {
authBloc.stream.listen((authState) {
if (authState is AuthFailure) {
emit(state.copyWith(isLoading: false, error: authState.error));
} else if (authState is AuthLoading) {
emit(state.copyWith(isLoading: true, error: null));
} else if (authState is AuthSuccess) {
emit(state.copyWith(isLoading: false, error: null));
}
});
}
void toggleRememberPassword(bool value) {
emit(state.copyWith(rememberPassword: value));
......@@ -31,7 +46,10 @@ class LoginCubit extends Cubit<LoginState> {
storageService.clearRememberCredentials();
}
authBloc.add(AuthLoginRequested(username: username, password: password));
authBloc.add(AuthLoginRequested(
username: username,
password: password,
));
}
Future<void> loadRememberCredentials() async {
......
......@@ -3,12 +3,14 @@ import 'package:equatable/equatable.dart';
class LoginState extends Equatable {
final bool rememberPassword;
final bool isLoading;
final String? error;
final String? savedUsername;
final String? savedPassword;
const LoginState({
this.rememberPassword = false,
this.isLoading = false,
this.error,
this.savedUsername,
this.savedPassword,
});
......@@ -16,12 +18,14 @@ class LoginState extends Equatable {
LoginState copyWith({
bool? rememberPassword,
bool? isLoading,
String? error,
String? savedUsername,
String? savedPassword,
}) {
return LoginState(
rememberPassword: rememberPassword ?? this.rememberPassword,
isLoading: isLoading ?? this.isLoading,
error: error,
savedUsername: savedUsername ?? this.savedUsername,
savedPassword: savedPassword ?? this.savedPassword,
);
......@@ -31,6 +35,7 @@ class LoginState extends Equatable {
List<Object?> get props => [
rememberPassword,
isLoading,
error,
savedUsername,
savedPassword,
];
......
......@@ -162,8 +162,9 @@ class LoginView extends StatelessWidget {
if (_frmGlobalKey.currentState!
.validate()) {
cubit.login(
username: _txtUserNameController.text
.trim(),
username:
_txtUserNameController.text
.trim(),
password:
_txtPwdController.text.trim(),
rememberPassword:
......
......@@ -9,7 +9,7 @@ class ProfileCubit extends Cubit<ProfileState> {
void initData() {
emit(state.copyWith(
phoneNumber: '15391514233',
username: '15391514233',
welcomeText: '欢迎来到智能酒店',
menuList: [
const MenuItem(icon: Icons.list, title: '设备列表'),
......
......@@ -14,28 +14,28 @@ class MenuItem {
}
class ProfileState extends Equatable {
final String phoneNumber;
final String username;
final String welcomeText;
final List<MenuItem> menuList;
const ProfileState({
this.phoneNumber = '',
this.username = '',
this.welcomeText = '',
this.menuList = const [],
});
ProfileState copyWith({
String? phoneNumber,
String? username,
String? welcomeText,
List<MenuItem>? menuList,
}) {
return ProfileState(
phoneNumber: phoneNumber ?? this.phoneNumber,
username: username ?? this.username,
welcomeText: welcomeText ?? this.welcomeText,
menuList: menuList ?? this.menuList,
);
}
@override
List<Object?> get props => [phoneNumber, welcomeText, menuList];
List<Object?> get props => [username, welcomeText, menuList];
}
\ No newline at end of file
......@@ -30,7 +30,7 @@ class ProfileView extends StatelessWidget {
return Column(
children: [
ProfileHeaderBlock(
phoneNumber: state.phoneNumber,
username: state.username,
welcomeText: state.welcomeText,
),
SizedBox(height: 10.h),
......
......@@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class ProfileHeaderBlock extends StatelessWidget {
final String phoneNumber;
final String username;
final String welcomeText;
const ProfileHeaderBlock({
super.key,
required this.phoneNumber,
required this.username,
required this.welcomeText,
});
......@@ -59,7 +59,7 @@ class ProfileHeaderBlock extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
phoneNumber,
username,
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
......
# 智慧酒店 App 接口对接方案
# 智慧酒店 App 接口对接方案
......@@ -16,8 +16,8 @@
```dart
// lib/repositories/xxx_repository.dart
import '../http/response_model.dart';
import '../http/dio_request.dart';
import '../utils/http/response_model.dart';
import '../utils/http/dio_request.dart';
import '../models/bo/xxx_bo.dart';
class XxxRepository {
......@@ -178,43 +178,43 @@ class xxxBO extends Equatable {
### 3.1 接口总览
| 序号 | 方法 | 路径 | 说明 | 所属模块 |
| 页面序号 | 方法 | 路径 | 状态 | 所属模块 |
|------|------|------|------|---------|
| 登录页 |POST | /app/auth/login/sms | 已对接 | 用户模块 |
### 3.2 接口详细定义
#### 模版
#### 登录
**POST /api/login**
**POST /app/auth/login/password**
```
求体:
{
"username": "string",
"password": "string"
"username": "string", // 用户名
"password": "string", // 密码
"clientId": "string", // 客户端ID 可选
"grantType": "string", // 授权类型 可选
"tenantId": "string", // 租户ID 可选
"code": "string", // 授权码 可选
"uuid": "string" // 唯一标识 可选
}
应 data:
{
"token": "string",
"userInfo": {
"username": "string",
"phone": "string"
"code": 0,
"msg": "string",
"data": {
"scope": "string",
"openid": "string",
"access_token": "string",
"refresh_token": "string",
"expire_in": 0,
"refresh_expire_in": 0,
"client_id": "string"
}
}
```
**GET /api/user/profile**
```
应 data:
{
"phone": "string",
"welcomeText": "string"
}
```
---
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment