LoginForm.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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 { loginApi, getTestRoleApi, getAdminRoleApi } from '@/api/login'
  8. import { useCache } from '@/hooks/web/useCache'
  9. import { useAppStore } from '@/store/modules/app'
  10. import { usePermissionStore } from '@/store/modules/permission'
  11. import { useRouter } from 'vue-router'
  12. import type { RouteLocationNormalizedLoaded, RouteRecordRaw } from 'vue-router'
  13. import { UserType } from '@/api/login/types'
  14. import { useValidator } from '@/hooks/web/useValidator'
  15. import { FormSchema } from '@/types/form'
  16. const { required } = useValidator()
  17. const emit = defineEmits(['to-register'])
  18. const appStore = useAppStore()
  19. const permissionStore = usePermissionStore()
  20. const { currentRoute, addRoute, push } = useRouter()
  21. const { wsCache } = useCache()
  22. const { t } = useI18n()
  23. const rules = {
  24. username: [required()],
  25. password: [required()]
  26. }
  27. const schema = reactive<FormSchema[]>([
  28. {
  29. field: 'title',
  30. colProps: {
  31. span: 24
  32. }
  33. },
  34. {
  35. field: 'username',
  36. label: t('login.username'),
  37. value: 'admin',
  38. component: 'Input',
  39. colProps: {
  40. span: 24
  41. },
  42. componentProps: {
  43. placeholder: t('login.usernamePlaceholder')
  44. }
  45. },
  46. {
  47. field: 'password',
  48. label: t('login.password'),
  49. value: 'admin',
  50. component: 'InputPassword',
  51. colProps: {
  52. span: 24
  53. },
  54. componentProps: {
  55. style: {
  56. width: '100%'
  57. },
  58. placeholder: t('login.passwordPlaceholder')
  59. }
  60. },
  61. {
  62. field: 'tool',
  63. colProps: {
  64. span: 24
  65. }
  66. },
  67. {
  68. field: 'login',
  69. colProps: {
  70. span: 24
  71. }
  72. },
  73. {
  74. field: 'other',
  75. component: 'Divider',
  76. label: t('login.otherLogin'),
  77. componentProps: {
  78. contentPosition: 'center'
  79. }
  80. },
  81. {
  82. field: 'otherIcon',
  83. colProps: {
  84. span: 24
  85. }
  86. }
  87. ])
  88. const iconSize = 30
  89. const remember = ref(false)
  90. const { register, elFormRef, methods } = useForm()
  91. const loading = ref(false)
  92. const iconColor = '#999'
  93. const redirect = ref<string>('')
  94. watch(
  95. () => currentRoute.value,
  96. (route: RouteLocationNormalizedLoaded) => {
  97. redirect.value = route?.query?.redirect as string
  98. },
  99. {
  100. immediate: true
  101. }
  102. )
  103. // 登录
  104. const signIn = async () => {
  105. const formRef = unref(elFormRef)
  106. await formRef?.validate(async (isValid) => {
  107. if (isValid) {
  108. loading.value = true
  109. const { getFormData } = methods
  110. const formData = await getFormData<UserType>()
  111. try {
  112. const res = await loginApi(formData)
  113. if (res) {
  114. wsCache.set(appStore.getUserInfo, res.data)
  115. // 是否使用动态路由
  116. if (appStore.getDynamicRouter) {
  117. getRole()
  118. } else {
  119. await permissionStore.generateRoutes('none').catch(() => {})
  120. permissionStore.getAddRouters.forEach((route) => {
  121. addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
  122. })
  123. permissionStore.setIsAddRouters(true)
  124. push({ path: redirect.value || permissionStore.addRouters[0].path })
  125. }
  126. }
  127. } finally {
  128. loading.value = false
  129. }
  130. }
  131. })
  132. }
  133. // 获取角色信息
  134. const getRole = async () => {
  135. const { getFormData } = methods
  136. const formData = await getFormData<UserType>()
  137. const params = {
  138. roleName: formData.username
  139. }
  140. // admin - 模拟后端过滤菜单
  141. // test - 模拟前端过滤菜单
  142. const res =
  143. formData.username === 'admin' ? await getAdminRoleApi(params) : await getTestRoleApi(params)
  144. if (res) {
  145. const { wsCache } = useCache()
  146. const routers = res.data || []
  147. wsCache.set('roleRouters', routers)
  148. formData.username === 'admin'
  149. ? await permissionStore.generateRoutes('admin', routers).catch(() => {})
  150. : await permissionStore.generateRoutes('test', routers).catch(() => {})
  151. permissionStore.getAddRouters.forEach((route) => {
  152. addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
  153. })
  154. permissionStore.setIsAddRouters(true)
  155. push({ path: redirect.value || permissionStore.addRouters[0].path })
  156. }
  157. }
  158. // 去注册页面
  159. const toRegister = () => {
  160. emit('to-register')
  161. }
  162. </script>
  163. <template>
  164. <Form
  165. :schema="schema"
  166. :rules="rules"
  167. label-position="top"
  168. hide-required-asterisk
  169. size="large"
  170. class="dark:(border-1 border-[var(--el-border-color)] border-solid)"
  171. @register="register"
  172. >
  173. <template #title>
  174. <h2 class="text-2xl font-bold text-center w-[100%]">{{ t('login.login') }}</h2>
  175. </template>
  176. <template #tool>
  177. <div class="flex justify-between items-center w-[100%]">
  178. <ElCheckbox v-model="remember" :label="t('login.remember')" size="small" />
  179. <ElLink type="primary" :underline="false">{{ t('login.forgetPassword') }}</ElLink>
  180. </div>
  181. </template>
  182. <template #login>
  183. <div class="w-[100%]">
  184. <ElButton :loading="loading" type="primary" class="w-[100%]" @click="signIn">
  185. {{ t('login.login') }}
  186. </ElButton>
  187. </div>
  188. <div class="w-[100%] mt-15px">
  189. <ElButton class="w-[100%]" @click="toRegister">
  190. {{ t('login.register') }}
  191. </ElButton>
  192. </div>
  193. </template>
  194. <template #otherIcon>
  195. <div class="flex justify-between w-[100%]">
  196. <Icon
  197. icon="ant-design:github-filled"
  198. :size="iconSize"
  199. class="cursor-pointer anticon"
  200. :color="iconColor"
  201. />
  202. <Icon
  203. icon="ant-design:wechat-filled"
  204. :size="iconSize"
  205. class="cursor-pointer anticon"
  206. :color="iconColor"
  207. />
  208. <Icon
  209. icon="ant-design:alipay-circle-filled"
  210. :size="iconSize"
  211. :color="iconColor"
  212. class="cursor-pointer anticon"
  213. />
  214. <Icon
  215. icon="ant-design:weibo-circle-filled"
  216. :size="iconSize"
  217. :color="iconColor"
  218. class="cursor-pointer anticon"
  219. />
  220. </div>
  221. </template>
  222. </Form>
  223. </template>
  224. <style lang="less" scoped>
  225. :deep(.anticon) {
  226. &:hover {
  227. color: var(--el-color-primary) !important;
  228. }
  229. }
  230. </style>