github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Login/components/LoginForm.vue (about)

     1  <script setup lang="ts">
     2  import {reactive, ref, unref, watch} from 'vue'
     3  import {Form} from '@/components/Form'
     4  import {useI18n} from '@/hooks/web/useI18n'
     5  import {ElButton, ElCheckbox, ElLink} from 'element-plus'
     6  import {useForm} from '@/hooks/web/useForm'
     7  import {useCache} from '@/hooks/web/useCache'
     8  import {useAppStore} from '@/store/modules/app'
     9  import {usePermissionStore} from '@/store/modules/permission'
    10  import type {RouteLocationNormalizedLoaded, RouteRecordRaw} from 'vue-router'
    11  import {useRouter} from 'vue-router'
    12  import {UserType} from '@/api/login/types'
    13  import {useValidator} from '@/hooks/web/useValidator'
    14  import {FormSchema} from '@/types/form'
    15  import api from "@/api/api";
    16  import {ApiSigninResponse} from "@/api/stub";
    17  import {prepareUrl} from "@/utils/serverId";
    18  
    19  const {required} = useValidator()
    20  const appStore = useAppStore()
    21  const permissionStore = usePermissionStore()
    22  const {currentRoute, addRoute, push} = useRouter()
    23  const {wsCache} = useCache()
    24  const {t} = useI18n()
    25  
    26  const rules = {
    27    username: [required()],
    28    password: [required()],
    29    server: []
    30  }
    31  
    32  const schema = reactive<FormSchema[]>([
    33    {
    34      field: 'title',
    35      colProps: {
    36        span: 24
    37      }
    38    },
    39    {
    40      field: 'username',
    41      label: t('login.username'),
    42      value: wsCache.get("username"),
    43      component: 'Input',
    44      colProps: {
    45        span: 24
    46      },
    47      componentProps: {
    48        placeholder: t('login.usernamePlaceholder')
    49      }
    50    },
    51    {
    52      field: 'password',
    53      label: t('login.password'),
    54      value: wsCache.get("password"),
    55      component: 'InputPassword',
    56      colProps: {
    57        span: 24
    58      },
    59      componentProps: {
    60        style: {
    61          width: '100%'
    62        },
    63        placeholder: t('login.passwordPlaceholder')
    64      }
    65    },
    66    {
    67      field: 'server',
    68      label: t('login.server'),
    69      value: wsCache.get("serverId"),
    70      component: 'Input',
    71      colProps: {
    72        span: 24
    73      },
    74      hidden: !appStore.getIsGate,
    75      componentProps: {
    76        style: {
    77          width: '100%'
    78        },
    79        placeholder: t('login.serverPlaceholder')
    80      }
    81    },
    82    {
    83      field: 'tool',
    84      colProps: {
    85        span: 24
    86      }
    87    },
    88    {
    89      field: 'login',
    90      colProps: {
    91        span: 24
    92      }
    93    }
    94  ])
    95  const remember = ref(wsCache.get("remember"))
    96  const {register, elFormRef, methods} = useForm()
    97  const loading = ref(false)
    98  const redirect = ref<string>('')
    99  const ipAddress = ref();
   100  
   101  watch(
   102    () => currentRoute.value,
   103    (route: RouteLocationNormalizedLoaded) => {
   104      redirect.value = route?.query?.redirect as string
   105    },
   106    {
   107      immediate: true
   108    }
   109  )
   110  
   111  const getIpAddress = async () => {
   112    fetch('https://api.ipify.org?format=json')
   113      .then(x => x.json())
   114      .then(({ip}) => {
   115        ipAddress.value = ip;
   116      });
   117  }
   118  
   119  getIpAddress()
   120  
   121  // 登录
   122  const signIn = async () => {
   123    const formRef = unref(elFormRef)
   124    await formRef?.validate(async (isValid) => {
   125      if (isValid) {
   126        loading.value = true
   127  
   128        const {getFormData} = methods
   129        const formData = await getFormData<UserType>()
   130        let {username, password, server} = formData;
   131        username = username.trim();
   132        if (server) {
   133          server = server.trim();
   134        }
   135  
   136        appStore.setServerId(server);
   137  
   138        try {
   139          const resp = await api.v1.authServiceSignin({
   140            headers: {Authorization: 'Basic ' + btoa(username + ':' + password), ip: ipAddress.value}
   141          });
   142  
   143          const {accessToken, currentUser} = resp.data as ApiSigninResponse;
   144          if (accessToken) {
   145            wsCache.set("accessToken", accessToken)
   146            wsCache.set("currentUser", currentUser)
   147  
   148            if (remember.value) {
   149              wsCache.set("username", username)
   150              wsCache.set("password", password)
   151              wsCache.set("remember", true)
   152            } else {
   153              wsCache.delete("username")
   154              wsCache.delete("password")
   155              wsCache.delete("remember")
   156            }
   157  
   158            appStore.SetToken(accessToken);
   159            appStore.SetUser(currentUser);
   160  
   161            if (currentUser?.image) {
   162              appStore.SetAvatar(prepareUrl(import.meta.env.VITE_API_BASEPATH as string + currentUser.image.url));
   163            } else {
   164              appStore.SetAvatar('');
   165            }
   166  
   167            await permissionStore.generateRoutes('none').catch(() => {
   168            })
   169            permissionStore.getAddRouters.forEach((route) => {
   170              addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
   171            })
   172            permissionStore.setIsAddRouters(true)
   173            push({path: redirect.value || permissionStore.addRouters[0].path})
   174          }
   175        } finally {
   176          loading.value = false
   177        }
   178      }
   179    })
   180  }
   181  
   182  // 获取角色信息
   183  // const getRole = async () => {
   184  //   const { getFormData } = methods
   185  //   const formData = await getFormData<UserType>()
   186  //   const params = {
   187  //     roleName: formData.username
   188  //   }
   189  //   // admin - 模拟后端过滤菜单
   190  //   // test - 模拟前端过滤菜单
   191  //   const res =
   192  //     formData.username === 'admin' ? await getAdminRoleApi(params) : await getTestRoleApi(params)
   193  //   if (res) {
   194  //     const { wsCache } = useCache()
   195  //     const routers = res.data || []
   196  //     wsCache.set('roleRouters', routers)
   197  //
   198  //     formData.username === 'admin'
   199  //       ? await permissionStore.generateRoutes('admin', routers).catch(() => {})
   200  //       : await permissionStore.generateRoutes('test', routers).catch(() => {})
   201  //
   202  //     permissionStore.getAddRouters.forEach((route) => {
   203  //       addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
   204  //     })
   205  //     permissionStore.setIsAddRouters(true)
   206  //     push({ path: redirect.value || permissionStore.addRouters[0].path })
   207  //   }
   208  // }
   209  
   210  // 去注册页面
   211  const toRestore = () => {
   212    push('/password_reset')
   213  }
   214  </script>
   215  
   216  <template>
   217    <Form
   218      :schema="schema"
   219      :rules="rules"
   220      label-position="top"
   221      hide-required-asterisk
   222      size="large"
   223      class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
   224      @register="register"
   225    >
   226      <template #title>
   227        <h2 class="text-2xl font-bold text-center w-[100%]">{{ t('login.login') }}</h2>
   228      </template>
   229  
   230      <template #tool>
   231        <div class="flex justify-between items-center w-[100%]">
   232          <ElCheckbox v-model="remember" :label="t('login.remember')"/>
   233          <ElLink type="primary" :underline="false" @click="toRestore()">{{ t('login.forgetPassword') }}</ElLink>
   234        </div>
   235      </template>
   236  
   237      <template #login>
   238        <div class="w-[100%]">
   239          <ElButton :loading="loading" type="primary" class="w-[100%]" @click="signIn">
   240            {{ t('login.login') }}
   241          </ElButton>
   242        </div>
   243      </template>
   244    </Form>
   245  </template>
   246  
   247  <style lang="less" scoped>
   248  :deep(.anticon) {
   249    &:hover {
   250      color: var(--el-color-primary) !important;
   251    }
   252  }
   253  </style>