实现登录逻辑
概述
登录模块位于 packages/auth,示例里展示了一个最小登录流程:点击按钮 → 发起登录请求 → 更新全局用户状态 → 返回上一页。实际业务只需替换参数和仓库实现即可。
登录流程
- View 触发
login()。 - ViewModel 调用仓库发起请求,并通过
RequestHelper处理结果。 - 登录成功后更新用户状态并刷新用户信息。
- 结束时关闭加载态并返回上一页。
View 示例
ts
import { IBestButton } from "@core/ibestui";
import { ColumnBase, MediumPaddingVerticalScroll, P100 } from "@core/designsystem";
import { AppNavDestination } from "@core/components";
import LoginViewModel from "../viewmodel/LoginViewModel";
/**
* @file 登录页视图
* @author Joker.X
*/
@ComponentV2
export struct LoginPage {
/**
* 登录页 ViewModel
*/
@Local
private vm: LoginViewModel = new LoginViewModel();
/**
* 构建登录页
* @returns {void} 无返回值
*/
build() {
AppNavDestination({
title: $r("app.string.login_title"),
viewModel: this.vm
}) {
this.LoginContent();
}
}
/**
* 登录页内容视图
* @returns {void} 无返回值
*/
@Builder
private LoginContent() {
MediumPaddingVerticalScroll() {
ColumnBase({ widthValue: P100 }) {
IBestButton({
text: $r("app.string.login_action"),
type: "primary",
buttonSize: "large",
round: true,
btnWidth: P100,
loading: this.vm.isLoginLoading,
disabled: this.vm.isLoginLoading,
onBtnClick: (): void => {
this.vm.login();
}
});
};
};
}
}ViewModel 示例
ts
import { BaseViewModel } from "@core/base";
import { IAuthRepository, AUTH_REPOSITORY_KEY } from '@shared/contracts';
import { Auth, PasswordLoginRequest } from "@shared/types";
import { RequestHelper } from "@core/network";
import { getUserState, UserState } from "@shared/state";
import { ToastUtils } from "@core/util";
import { CoreServiceKeys, getContainer } from "@core/di";
import { AuthRepositoryImpl } from "../services/AuthRepositoryImpl";
import { NavigationService } from "@core/navigation";
/**
* @file 登录页 ViewModel
* @author Joker.X
*/
@ObservedV2
export default class LoginViewModel extends BaseViewModel {
/**
* 全局用户状态
*/
private readonly userState: UserState = getUserState();
/**
* 认证仓库
*/
private readonly authRepository: IAuthRepository = getContainer().resolve<IAuthRepository>(AUTH_REPOSITORY_KEY, () => new AuthRepositoryImpl());
/**
* 登录按钮加载状态
*/
@Trace
isLoginLoading: boolean = false;
/**
* 执行登录操作
* @returns {void} 无返回值
*/
login(): void {
const params: PasswordLoginRequest = new PasswordLoginRequest(
"16666666666",
"123456"
);
RequestHelper.fromResult<Auth>(this.authRepository.loginByPassword(params))
.start(() => {
this.isLoginLoading = true;
})
.execute()
.then((authData: Auth) => {
this.onLoginSuccess(authData);
})
.finally(() => {
this.isLoginLoading = false;
});
}
/**
* 登录成功处理
* @param {Auth} authData - 认证数据
*/
private async onLoginSuccess(authData: Auth) {
this.userState.updateAuth(authData);
this.userState.refreshUserInfo();
ToastUtils.showSuccess($r("app.string.login_success"));
const navigation = getContainer().tryResolve<NavigationService>(CoreServiceKeys.NavigationService);
navigation?.navigateBack();
}
}注意事项
- 账号与密码为示例数据,实际业务应替换为真实输入。
- 登录成功后统一走
UserState更新全局信息,避免页面间重复处理。 - 登录按钮需绑定加载态,防止重复提交。