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>