pwd-login.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <script setup lang="ts">
  2. import { computed, onMounted, reactive, ref, watch } from 'vue';
  3. import { Crypto } from '@sa/utils';
  4. import { fetchGetCaptcha } from '@/service/api/common';
  5. import { fetchGetTenantOptions } from '@/service/api/auth';
  6. import { useAuthStore } from '@/store/modules/auth';
  7. import { useFormRules, useNaiveForm } from '@/hooks/common/form';
  8. import { localStg } from '@/utils/storage';
  9. import { $t } from '@/locales';
  10. defineOptions({
  11. name: 'PwdLogin'
  12. });
  13. const pd = new Crypto<{ data: string }>('zhongshuweilai');
  14. const authStore = useAuthStore();
  15. const { formRef, validate } = useNaiveForm();
  16. const isRememberMe = ref(false);
  17. const imgPath = ref('');
  18. // 租户选项
  19. const tenantOptions = ref<{ label: string; value: string }[]>([]);
  20. const selectedTenantCode = ref<string | null>(null);
  21. async function loadTenantOptions() {
  22. const { data } = await fetchGetTenantOptions();
  23. if (data) {
  24. tenantOptions.value = (data as any[]).map((item: any) => ({
  25. label: item.tenantName,
  26. value: item.tenantCode
  27. }));
  28. }
  29. }
  30. loadTenantOptions();
  31. interface FormModel {
  32. userName: string;
  33. password: string;
  34. captchaCode: string;
  35. }
  36. const model: FormModel = reactive({
  37. userName: '',
  38. password: '',
  39. captchaCode: ''
  40. });
  41. onMounted(() => {
  42. const userName = localStg.get('userName');
  43. const password = localStg.get('password');
  44. const obj = pd.decrypt(String(password));
  45. if (userName && password && obj) {
  46. model.userName = userName;
  47. model.password = obj.data;
  48. isRememberMe.value = true;
  49. }
  50. });
  51. const rules = computed<Record<keyof FormModel, App.Global.FormRule[]>>(() => {
  52. // inside computed to make locale reactive, if not apply i18n, you can define it without computed
  53. const { formRules } = useFormRules();
  54. return {
  55. userName: formRules.userName,
  56. password: formRules.pwd,
  57. captchaCode: formRules.captchaCode
  58. };
  59. });
  60. const captchaKey = ref('');
  61. async function handleSubmit() {
  62. await validate();
  63. if (!selectedTenantCode.value) {
  64. window.$message?.error('请选择租户');
  65. return;
  66. }
  67. if (isRememberMe.value) {
  68. const pwd = pd.encrypt({ data: model.password });
  69. localStg.set('userName', model.userName);
  70. localStg.set('password', pwd);
  71. }
  72. await authStore.login({ ...model, captchaKey: captchaKey.value, tenantCode: selectedTenantCode.value || undefined });
  73. }
  74. async function getDataCode() {
  75. const { data } = await fetchGetCaptcha();
  76. imgPath.value = String(data?.captchaBase64);
  77. captchaKey.value = String(data?.captchaId);
  78. model.captchaCode = '';
  79. }
  80. getDataCode();
  81. watch(
  82. () => authStore.loginLoading,
  83. () => {
  84. if (!authStore.loginLoading) {
  85. getDataCode();
  86. }
  87. }
  88. );
  89. </script>
  90. <template>
  91. <NForm ref="formRef" :model="model" :rules="rules" size="large" :show-label="false" @keyup.enter="handleSubmit">
  92. <NFormItem :rule="{ required: true, message: '请选择租户', trigger: 'change' }">
  93. <NSelect v-model:value="selectedTenantCode" :options="tenantOptions" placeholder="请选择租户" />
  94. </NFormItem>
  95. <NFormItem path="userName">
  96. <NInput v-model:value="model.userName" :placeholder="$t('page.login.common.userNamePlaceholder')" />
  97. </NFormItem>
  98. <NFormItem path="password">
  99. <NInput
  100. v-model:value="model.password"
  101. type="password"
  102. show-password-on="click"
  103. :placeholder="$t('page.login.common.passwordPlaceholder')"
  104. />
  105. </NFormItem>
  106. <NFormItem path="imageCode">
  107. <NInput v-model:value="model.captchaCode" placeholder="请输入验证码" />
  108. <img :src="imgPath" alt="" class="ml20px h40px w220px cursor-pointer" @click="getDataCode" />
  109. </NFormItem>
  110. <NSpace vertical :size="24">
  111. <div class="flex-y-center justify-between">
  112. <NCheckbox v-model:checked="isRememberMe">{{ $t('page.login.pwdLogin.rememberMe') }}</NCheckbox>
  113. </div>
  114. <NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="handleSubmit">
  115. {{ $t('common.confirm') }}
  116. </NButton>
  117. </NSpace>
  118. </NForm>
  119. </template>
  120. <style scoped></style>