index.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <script setup lang="ts">
  2. import type { FormInstance, FormRules } from "element-plus";
  3. import useUserStore from "@/store/modules/user";
  4. import { ref, useTemplateRef, onMounted,onUnmounted } from "vue";
  5. defineOptions({
  6. name: "LoginForm",
  7. });
  8. const props = defineProps<{
  9. userName?: string;
  10. passWord?: string;
  11. captcha?: string;
  12. system?: string;
  13. captchaId?: number;
  14. }>();
  15. const emits = defineEmits<{
  16. onLogin: [userName: string];
  17. onRegister: [userName: string];
  18. onResetPassword: [userName: string];
  19. }>();
  20. const userStore = useUserStore();
  21. // const title = import.meta.env.VITE_APP_TITLE
  22. const baseurl = import.meta.env.VITE_APP_API_BASEURL;
  23. const loading = ref(false);
  24. const remember = ref(false);
  25. const captchaSrc = ref(""); //验证码图片
  26. // const system = ref([
  27. // 'PLATFORM',
  28. // 'JZG'
  29. // ])
  30. // 登录方式,default 账号密码登录,qrcode 扫码登录
  31. const type = ref("default");
  32. const formRef = useTemplateRef<FormInstance>("formRef");
  33. const form = ref({
  34. userName: props.userName ?? localStorage.login_account ?? "",
  35. passWord: "",
  36. captcha: "",
  37. system: "PLATFORM",
  38. captchaId: 0,
  39. system: "",
  40. });
  41. const rules = ref<FormRules>({
  42. userName: [{ required: true, trigger: "blur", message: "请输入用户名" }],
  43. system: [{ required: true, trigger: "blur", message: "请输入租户编码" }],
  44. passWord: [
  45. { required: true, trigger: "blur", message: "请输入密码" },
  46. { min: 6, max: 18, trigger: "blur", message: "密码长度为6到18位" },
  47. ],
  48. });
  49. onMounted(() => {
  50. refreshCaptcha();
  51. window.addEventListener('keydown', handleEnter)
  52. });
  53. onUnmounted(() => {
  54. window.removeEventListener('keydown', handleEnter, false)
  55. })
  56. //获取验证码接口
  57. function refreshCaptcha() {
  58. let randnum = Math.floor(Math.random() * (1000000 - 1 + 1)) + 1;
  59. captchaSrc.value =
  60. baseurl +
  61. "/auth/captchaById?t=" +
  62. new Date().getTime() +
  63. "&captchaId=" +
  64. randnum;
  65. form.value.captchaId = randnum;
  66. }
  67. function handleEnter (e:any) {
  68. // console.log(e)
  69. // console.log(e)
  70. if (e.keyCode == 13 || e.keyCode == 108) {
  71. //登录接口逻辑
  72. handleLogin()
  73. }
  74. }
  75. function handleLogin() {
  76. // console.log(123)
  77. formRef.value?.validate((valid) => {
  78. if (valid) {
  79. loading.value = true;
  80. userStore
  81. .login(form.value)
  82. .then(() => {
  83. if (remember) {
  84. localStorage.setItem("login_account", form.value.userName);
  85. } else {
  86. localStorage.removeItem("login_account");
  87. }
  88. localStorage.setItem("login_system", form.value.system);
  89. emits("onLogin", form.value.userName);
  90. })
  91. .finally(() => {
  92. loading.value = false;
  93. refreshCaptcha();
  94. });
  95. }
  96. });
  97. }
  98. // function testAccount(userName: string) {
  99. // form.value.userName = userName
  100. // form.value.passWord = '123456'
  101. // handleLogin()
  102. // }
  103. </script>
  104. <style lang="scss" scoped>
  105. :deep(.el-form-item--large) {
  106. margin-bottom: 30px;
  107. }
  108. :deep(.el-input__prefix) {
  109. color: #3275ff;
  110. }
  111. .title {
  112. position: relative;
  113. margin-bottom: 56px;
  114. font-size: 36px;
  115. color: #333;
  116. span {
  117. position: relative;
  118. z-index: 9999;
  119. letter-spacing: 5px;
  120. }
  121. .tag {
  122. position: absolute;
  123. bottom: 0;
  124. width: 76px;
  125. height: 8px;
  126. background: linear-gradient(90deg, #4fcaff 0%, #2b62ff 100%);
  127. }
  128. }
  129. .loginCSS {
  130. padding: 2px;
  131. font-size: 20px;
  132. background: linear-gradient(91deg, #4fcaff 0%, #2b62ff 100%);
  133. }
  134. </style>
  135. <template>
  136. <ElForm
  137. ref="formRef"
  138. :model="form"
  139. :rules="rules"
  140. class="min-h-500px w-full flex-col-stretch-center"
  141. style="padding: 81px 75px"
  142. size="large"
  143. >
  144. <!-- <div class="mb-6">
  145. <HTabList v-model="type" :options="[
  146. { label: '账号密码登录', value: 'default' },
  147. { label: '扫码登录', value: 'qrcode' },
  148. ]" />
  149. </div> -->
  150. <template v-if="type === 'default'">
  151. <!-- <h3 class="mb-8 text-xl color-[var(--el-text-color-primary)] font-bold">
  152. 欢迎使用 {{ title }} ! 👋🏻
  153. </h3> -->
  154. <div class="title strong">
  155. <span>登录</span>
  156. <div class="tag"></div>
  157. </div>
  158. <div>
  159. <ElFormItem prop="system">
  160. <ElInput
  161. v-model="form.system"
  162. placeholder="输入租户编码"
  163. type="text"
  164. tabindex="1"
  165. >
  166. <template #prefix>
  167. <el-icon><Postcard /></el-icon>
  168. </template>
  169. </ElInput>
  170. </ElFormItem>
  171. <ElFormItem prop="userName">
  172. <ElInput
  173. v-model="form.userName"
  174. placeholder="手机号或工号"
  175. type="text"
  176. tabindex="1"
  177. >
  178. <template #prefix>
  179. <el-icon><User /></el-icon>
  180. </template>
  181. </ElInput>
  182. </ElFormItem>
  183. <ElFormItem prop="passWord">
  184. <ElInput
  185. v-model="form.passWord"
  186. type="password"
  187. placeholder="登录密码"
  188. tabindex="2"
  189. show-password
  190. @keyup.enter="handleLogin"
  191. >
  192. <template #prefix>
  193. <el-icon><Lock /></el-icon>
  194. </template>
  195. </ElInput>
  196. </ElFormItem>
  197. <ElFormItem prop="captcha" style="margin-bottom: 0">
  198. <ElCol :md="14" :sm="14" :xs="14">
  199. <ElInput
  200. v-model="form.captcha"
  201. placeholder="验证码"
  202. type="text"
  203. tabindex="3"
  204. >
  205. <template #prefix>
  206. <el-icon><CircleCheck /></el-icon>
  207. </template>
  208. </ElInput>
  209. </ElCol>
  210. <ElCol :md="10" :sm="10" :xs="10" flex>
  211. <img
  212. style="width: 100%; height: 32px; margin-left: 20px"
  213. class="pointer"
  214. :src="captchaSrc"
  215. @click="refreshCaptcha"
  216. />
  217. </ElCol>
  218. </ElFormItem>
  219. </div>
  220. <div class="mb-17 flex-center-between">
  221. <ElCheckbox v-model="remember"> 记住密码 </ElCheckbox>
  222. <ElLink
  223. type="primary"
  224. :underline="false"
  225. @click="emits('onResetPassword', form.userName)"
  226. >
  227. 忘记密码
  228. </ElLink>
  229. </div>
  230. <ElButton
  231. class="loginCSS"
  232. :loading="loading"
  233. type="primary"
  234. @keydown.enter="handleEnter"
  235. style="width: 100%"
  236. @click.prevent="handleLogin"
  237. >
  238. 登录
  239. </ElButton>
  240. <!-- <div class="mt-4 flex-center gap-2 text-sm color-[var(--el-text-color-secondary)]">
  241. 还没有帐号?
  242. <ElLink type="primary" :underline="false" @click="emits('onRegister', form.userName)">
  243. 创建新帐号
  244. </ElLink>
  245. </div> -->
  246. </template>
  247. <template v-else-if="type === 'qrcode'">
  248. <div class="flex-col-center">
  249. <el-image
  250. src="https://s2.loli.net/2024/04/26/GsahtuIZ9XOg5jr.png"
  251. class="h-[250px] w-[250px]"
  252. />
  253. <div class="mt-2 op-50">请使用微信扫码登录</div>
  254. </div>
  255. </template>
  256. <!-- <div class="mt-4 text-center -mb-4">
  257. <ElDivider>演示账号一键登录</ElDivider>
  258. <ElButton type="primary" size="small" plain @click="testAccount('admin')">
  259. admin
  260. </ElButton>
  261. <ElButton size="small" plain @click="testAccount('test')">
  262. test
  263. </ElButton>
  264. </div> -->
  265. </ElForm>
  266. </template>