|
@@ -1,9 +1,168 @@
|
|
|
<template>
|
|
|
- 登录
|
|
|
+ <div class="common-form-container">
|
|
|
+ <van-form label-width="50" label-align="left" colon @submit="onSubmit">
|
|
|
+ <div class="form-item">
|
|
|
+ <div class="form-header">
|
|
|
+ <div class="form-header-left">
|
|
|
+ <div class="form-title">欢迎登录智慧应急工作台</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="common-form-content">
|
|
|
+ <div class="common-form-item">
|
|
|
+ <van-field
|
|
|
+ v-model="form.username"
|
|
|
+ class="common-field"
|
|
|
+ label="账号"
|
|
|
+ placeholder="请输入账号"
|
|
|
+ :rules="rules.username"
|
|
|
+ />
|
|
|
+ <van-field
|
|
|
+ v-model="form.password"
|
|
|
+ class="common-field"
|
|
|
+ type="password"
|
|
|
+ label="密码"
|
|
|
+ placeholder="请输入密码"
|
|
|
+ :rules="rules.password"
|
|
|
+ />
|
|
|
+ <van-field
|
|
|
+ v-model="form.code"
|
|
|
+ class="common-field"
|
|
|
+ label="验证码"
|
|
|
+ placeholder="请输入验证码"
|
|
|
+ show-word-limit
|
|
|
+ :rules="rules.code">
|
|
|
+ <template #button>
|
|
|
+ <div class="login-code">
|
|
|
+ <img :src="codeUrl" class="login-code-img" @click="getCode" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-field>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </van-form>
|
|
|
+ <div class="form-footer">
|
|
|
+ <van-button class="btn primary-btn" :loading="loading" type="primary" native-type="submit">登录</van-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
</template>
|
|
|
|
|
|
-<script lang="ts" setup>
|
|
|
+<script setup lang="ts">
|
|
|
+import { getCodeImg } from '@/api/login';
|
|
|
+import { useUserStore } from '@/store/modules/user';
|
|
|
+import { to } from 'await-to-js';
|
|
|
+
|
|
|
+const userStore = useUserStore();
|
|
|
+const router = useRouter();
|
|
|
+// 表单校验规则
|
|
|
+const rules = reactive({
|
|
|
+ username: [{ required: true, message: "请输入您的账号" }],
|
|
|
+ password: [{ required: true, message: "请输入您的密码" }],
|
|
|
+ code: [{ required: true, message: "请输入验证码" }],
|
|
|
+});
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const form = ref({
|
|
|
+ username: 'admin',
|
|
|
+ password: '123456',
|
|
|
+ code: '',
|
|
|
+ uuid: ''
|
|
|
+});
|
|
|
+
|
|
|
+const codeUrl = ref('');
|
|
|
+const loading = ref(false);
|
|
|
+// 验证码开关
|
|
|
+const captchaEnabled = ref(true);
|
|
|
+const redirect = ref(undefined);
|
|
|
+
|
|
|
+watch(
|
|
|
+() => router.currentRoute.value,
|
|
|
+(newRoute: any) => {
|
|
|
+ redirect.value = newRoute.query && newRoute.query.redirect;
|
|
|
+},
|
|
|
+{ immediate: true }
|
|
|
+);
|
|
|
+
|
|
|
+const onSubmit = async() => {
|
|
|
+ if (loading.value) return;
|
|
|
+ loading.value = true;
|
|
|
+ const [err] = await to(userStore.login(form.value));
|
|
|
+ if (!err) {
|
|
|
+ const redirectUrl = redirect.value || '/';
|
|
|
+ await router.push(redirectUrl);
|
|
|
+ loading.value = false;
|
|
|
+ } else {
|
|
|
+ loading.value = false;
|
|
|
+ // 重新获取验证码
|
|
|
+ if (captchaEnabled.value) {
|
|
|
+ await getCode();
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取验证码
|
|
|
+ */
|
|
|
+const getCode = async () => {
|
|
|
+const res = await getCodeImg();
|
|
|
+const { data } = res;
|
|
|
+captchaEnabled.value = data.captchaEnabled === undefined ? true : data.captchaEnabled;
|
|
|
+if (captchaEnabled.value) {
|
|
|
+ codeUrl.value = 'data:image/gif;base64,' + data.img;
|
|
|
+ form.value.uuid = data.uuid;
|
|
|
+}
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getCode();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-</style>
|
|
|
+ .login-code {
|
|
|
+ width: 100px;
|
|
|
+ float: right;
|
|
|
+
|
|
|
+ img {
|
|
|
+ cursor: pointer;
|
|
|
+ vertical-align: middle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .login-code-img {
|
|
|
+ height: 30px;
|
|
|
+ padding-left: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .form-footer {
|
|
|
+ width: 100%;
|
|
|
+ height: 70px;
|
|
|
+ background: #FFFFFF;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ .btn {
|
|
|
+ width: 90px;
|
|
|
+ height: 36px;
|
|
|
+ border: 1px solid #D1D1D1;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border-radius: 2px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #B3B3B3;
|
|
|
+ margin-left: 24px;
|
|
|
+ &:first-child {
|
|
|
+ margin-left: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .primary-btn {
|
|
|
+ width: 110px;
|
|
|
+ height: 36px;
|
|
|
+ border: 1px solid #2C81FF;
|
|
|
+ background: #2C81FF;
|
|
|
+ border-radius: 2px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|