model-user-login.component.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import { Component, Input, OnInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
  2. import { FormsModule } from '@angular/forms';
  3. import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonHeader, IonInput, IonItem, IonLabel, IonSegment, IonSegmentButton, IonTitle, IonToolbar, ModalController, ToastController, IonIcon } from '@ionic/angular/standalone';
  4. import { addIcons } from 'ionicons';
  5. import { personOutline, lockClosedOutline } from 'ionicons/icons';
  6. import { CloudUser } from '../../ncloud';
  7. @Component({
  8. selector: 'model-user-login',
  9. templateUrl: './model-user-login.component.html',
  10. styleUrls: ['./model-user-login.component.scss'],
  11. standalone: true,
  12. schemas: [CUSTOM_ELEMENTS_SCHEMA],
  13. imports: [
  14. FormsModule,
  15. IonHeader,
  16. IonToolbar,
  17. IonTitle,
  18. IonContent,
  19. IonCard,
  20. IonCardContent,
  21. IonButton,
  22. IonCardHeader,
  23. IonCardTitle,
  24. IonCardSubtitle,
  25. IonInput,
  26. IonItem,
  27. IonSegment,
  28. IonSegmentButton,
  29. IonLabel,
  30. IonIcon
  31. ],
  32. })
  33. export class ModelUserLoginComponent implements OnInit {
  34. @Input()
  35. type: "login" | "signup" = "login"
  36. // 添加回 typeChange 方法
  37. typeChange(ev: any) {
  38. this.type = ev?.detail?.value || ev?.value || 'login';
  39. // 切换类型时清空错误信息和密码
  40. this.errorMessage = '';
  41. this.password = '';
  42. this.password2 = '';
  43. }
  44. // 添加 isSignup 计算属性
  45. get isSignup(): boolean {
  46. return this.type === 'signup';
  47. }
  48. username: string = ""
  49. password: string = ""
  50. password2: string = ""
  51. errorMessage: string = ""
  52. constructor(
  53. private modalCtrl: ModalController,
  54. private toastCtrl: ToastController
  55. ) {
  56. addIcons({
  57. 'person-outline': personOutline,
  58. 'lock-closed-outline': lockClosedOutline
  59. });
  60. }
  61. ngOnInit() { }
  62. // 验证用户名
  63. validateUsername(): boolean {
  64. if (!this.username) {
  65. this.showError('用户名不能为空');
  66. return false;
  67. }
  68. if (this.username.length < 3) {
  69. this.showError('用户名长度不能少于3个字符');
  70. return false;
  71. }
  72. if (this.username.length > 20) {
  73. this.showError('用户名长度不能超过20个字符');
  74. return false;
  75. }
  76. if (!/^[a-zA-Z0-9_\u4e00-\u9fa5]+$/.test(this.username)) {
  77. this.showError('用户名只能包含字母、数字、下划线和中文');
  78. return false;
  79. }
  80. return true;
  81. }
  82. // 验证密码
  83. validatePassword(): boolean {
  84. if (!this.password) {
  85. this.showError('密码不能为空');
  86. return false;
  87. }
  88. if (this.password.length < 6) {
  89. this.showError('密码长度不能少于6个字符');
  90. return false;
  91. }
  92. if (this.password.length > 20) {
  93. this.showError('密码长度不能超过20个字符');
  94. return false;
  95. }
  96. if (!/^[a-zA-Z0-9_]+$/.test(this.password)) {
  97. this.showError('密码只能包含字母、数字和下划线');
  98. return false;
  99. }
  100. return true;
  101. }
  102. // 验证确认密码
  103. validateConfirmPassword(): boolean {
  104. if (this.password !== this.password2) {
  105. this.showError('两次输入的密码不一致');
  106. return false;
  107. }
  108. return true;
  109. }
  110. async showError(message: string) {
  111. this.errorMessage = message;
  112. const toast = await this.toastCtrl.create({
  113. message: message,
  114. duration: 2000,
  115. position: 'top',
  116. color: 'danger',
  117. cssClass: 'error-toast'
  118. });
  119. await toast.present();
  120. }
  121. async showSuccess(message: string) {
  122. const toast = await this.toastCtrl.create({
  123. message: message,
  124. duration: 2000,
  125. position: 'top',
  126. color: 'success',
  127. cssClass: 'success-toast'
  128. });
  129. await toast.present();
  130. }
  131. async login() {
  132. this.errorMessage = '';
  133. if (!this.validateUsername() || !this.validatePassword()) {
  134. return;
  135. }
  136. try {
  137. let user: any = new CloudUser();
  138. user = await user.login(this.username, this.password);
  139. if (user?.id) {
  140. await this.showSuccess('登录成功');
  141. this.modalCtrl.dismiss(user, "confirm");
  142. } else {
  143. this.showError('用户名或密码错误');
  144. }
  145. } catch (error) {
  146. this.showError('登录失败,请稍后重试');
  147. }
  148. }
  149. async signup() {
  150. this.errorMessage = '';
  151. if (!this.validateUsername() || !this.validatePassword() || !this.validateConfirmPassword()) {
  152. return;
  153. }
  154. try {
  155. let user: any = new CloudUser();
  156. user = await user.signUp(this.username, this.password);
  157. if (user) {
  158. await this.showSuccess('注册成功,请登录');
  159. this.type = "login";
  160. this.password = '';
  161. this.password2 = '';
  162. } else {
  163. this.showError('注册失败,该用户名可能已被使用');
  164. }
  165. } catch (error) {
  166. this.showError('注册失败,请稍后重试');
  167. }
  168. }
  169. }
  170. export async function openUserLoginModal(modalCtrl: ModalController, type: "login" | "signup" = "login"): Promise<CloudUser | null> {
  171. const modal = await modalCtrl.create({
  172. component: ModelUserLoginComponent,
  173. componentProps: {
  174. type: type
  175. },
  176. breakpoints: [0, 0.6, 0.8],
  177. initialBreakpoint: 0.6,
  178. backdropBreakpoint: 0.6,
  179. cssClass: 'login-modal'
  180. });
  181. modal.present();
  182. const { data, role } = await modal.onWillDismiss();
  183. if (role === 'confirm') {
  184. return data;
  185. }
  186. return null
  187. }