This commit is contained in:
2023-04-23 09:41:12 +08:00
parent 0339a49d2b
commit d20a1e0ca1
1552 changed files with 98219 additions and 190234 deletions
+3 -42
View File
@@ -1,16 +1,7 @@
<template>
<VScaleScreen fullScreen width="1920" height="1080">
<VScaleScreen width="100%" height="100%">
<div class="center">
<div ref="head" class="headers">
种植业生产监管数字化系统
<span @click="exitMaximize" class="exit">
<img
src="@/assets/svg/quxiaoquanping.svg"
style="width: 14px; height: 14px; cursor: pointer"
/>
退出全屏
</span>
</div>
<Headers />
<router-view />
</div>
</VScaleScreen>
@@ -19,8 +10,8 @@
<script setup>
import useSettingsStore from '@/store/modules/settings';
import { handleThemeStyle } from '@/utils/theme';
import VScaleScreen from 'v-scale-screen';
import Headers from '@/components/heades/index';
onMounted(() => {
nextTick(() => {
@@ -34,34 +25,4 @@ onMounted(() => {
width: 100%;
height: 100%;
}
.headers {
position: fixed;
left: 0;
top: 0;
z-index: 1;
height: 80px;
line-height: 80px;
width: 100%;
display: flex;
box-sizing: border-box;
background-image: url('@/assets/images/header.png');
background-size: 100% 100%;
justify-content: center;
opacity: 1;
text-shadow: 0px 0px 6px 0px rgba(41, 255, 255, 1);
font-weight: 400;
font-size: 21px;
letter-spacing: 4px;
color: rgba(255, 255, 255, 1);
transform: translate(0, -100%);
.exit {
position: absolute;
top: 20px;
right: 20px;
display: flex;
align-items: center;
font-size: 14px;
color: rgba(41, 255, 219, 1);
}
}
</style>
+39
View File
@@ -0,0 +1,39 @@
import request from '@/utils/request'
export function getarea(query) {
return request({
url: '/crops/area',
method: 'get',
params: query
})
}
export function getTownship() {
return request({
url: 'http://121.36.229.60:9080/geoserver/shuzisannong/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=shuzisannong%3Ahuangdaoqu_town&maxFeatures=50&outputFormat=application%2Fjson',
method: 'get',
})
}
export function getvillage() {
return request({
url: 'http://121.36.229.60:9080/geoserver/shuzisannong/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=shuzisannong%3Ahuangdaoqu_village&maxFeatures=1180&outputFormat=application%2Fjson',
method: 'get',
})
}
export function getareas() {
return request({
url: 'http://121.36.229.60:9080/geoserver/shuzisannong/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=shuzisannong%3Afenlei&maxFeatures=1180&outputFormat=application%2Fjson',
method: 'get',
})
}
export function dow() {
return request({
url: 'http://118.24.27.47:6802/crops/export_area?subregion=1&parent=黄岛区&time=2023-04-19',
method: 'get',
})
}
+3 -2
View File
@@ -1,9 +1,10 @@
import request from '@/utils/request'
// 获取路由
export const getRouters = () => {
export const getRouters = (query) => {
return request({
url: '/getRouters',
method: 'get'
method: 'get',
params: query
})
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 KiB

After

Width:  |  Height:  |  Size: 7.0 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+30 -14
View File
@@ -1,28 +1,44 @@
<template>
<div @click="max">
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" @click="toggle" />
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" />
</div>
</template>
<script setup>
import { useFullscreen } from '@vueuse/core';
import { onMounted } from 'vue';
import { onMounted, ref } from 'vue';
import useSettingsStore from '@/store/modules/settings';
const settingsStore = useSettingsStore();
const { isFullscreen, enter, exit, toggle } = useFullscreen();
let navbar = null;
let container = null;
let hasLogo = null;
onMounted(() => {
navbar = document.querySelector('.navbar');
container = document.querySelector('#tags-view-container');
hasLogo = document.querySelector('.has-logo');
});
//获取dom
let navbar = null;
let app_main = null;
let headers = null;
let leftWra = null;
let rightWra = null;
let flag = ref(true);
let leftment = null;
let main_container = null;
onMounted(() => {
navbar = document.querySelector('.navDiv');
app_main = document.querySelector('.app-main');
headers = document.querySelector('.headers');
leftWra = document.querySelector('.leftWra');
rightWra = document.querySelector('.rightWra');
leftment = document.querySelector('.leftment');
main_container = document.querySelector('.main-container');
});
//隐藏导航栏
const max = () => {
console.log(hasLogo.style);
navbar.style.display = 'none';
container.style.display = 'none';
hasLogo.style.left = '-100px';
app_main.style.height = '100%';
headers.style.transform = `translate(0, 0)`;
leftment.style.display = 'none';
main_container.style.marginLeft = '0';
document.querySelector('.leftWra').style.top = '80px';
document.querySelector('.rightWra').style.top = '80px';
// settingsStore.changeSetting({ key: 'topNav', value: flag.value });
};
</script>
+186
View File
@@ -0,0 +1,186 @@
<template>
<div class="timeline">
<el-slider
v-model="value2"
:step="step"
:marks="marks"
show-stops
:show-tooltip="false"
:min="min"
:max="max"
></el-slider>
<div class="optionWrapper">
<img @click="leftHandle" src="@/assets/images/upper.png" alt="《" />
<img @click="autoPlay" v-if="!times" src="@/assets/images/start.png" alt="||" />
<img @click="pausePlay" v-if="times" src="@/assets/images/suspend.png" alt="||" />
<img @click="rightHandle" src="@/assets/images/below.png" alt="》" />
</div>
</div>
</template>
<script>
/*
dataSource=[
{name:'year1',value:''}
]
*/
export default {
props: ['dataSource', 'theme'],
data() {
return {
value2: 0, //当前的值
marks: {}, //时间轴刻度
step: 10,
times: null,
min: 0,
max: 100,
};
},
watch: {
// 监听数值变化进行操作
value2: function (val, oldVal) {
// 筛选出原始数据
const oldData = this.dataSource.find(item => item.name === this.marks[val].label);
this.$emit('dataHandle', oldData);
},
dataSource: function (val, oldVal) {
//源数据监听
this.dataHandleInit();
},
},
mounted() {
this.dataHandleInit(); //
},
methods: {
dataHandleInit() {
const dataSource = [
{ name: '11/25' },
{ name: '11/25' },
{ name: '11/25' },
{ name: '11/25' },
{ name: '11/25' },
];
const markNum = dataSource.map(item => item.name);
this.max = (markNum.length - 1) * 10; //时间轴最大值
const splitNumber = 10;
// const splitNumber = 100 / (markNum.length - 1)
// this.step = splitNumber //确定间隔长度
let num = 0;
let marks = {};
// 排序,确定marks
dataSource
.sort((a, b) => Number(a.name) - Number(b.name))
.forEach((item, index) => {
if (dataSource.length < 10) {
marks[num] = { label: item.name };
} else {
marks[num] = {
label: item.name,
style: {
top: index % 2 === 1 ? '-40px' : '0px',
},
};
}
num += splitNumber;
});
this.marks = marks; //赋值mark
},
// 上一个
leftHandle() {
// 判断是不是第一个
if (this.value2 === 0) {
this.value2 = this.max;
} else {
this.value2 -= this.step;
}
},
// 下一个
rightHandle() {
// 判断是否是最后一个
if (this.value2 === this.max) {
// 跳转到第一个
this.value2 = 0;
} else {
this.value2 += this.step;
}
},
// 自动播放
autoPlay() {
this.times = setInterval(() => {
this.rightHandle();
}, 1000 * 2);
},
// 暂停播放
pausePlay() {
clearInterval(this.times);
this.times = null;
},
},
};
</script>
<style scoped lang="scss">
.timeline {
width: 100%;
height: 100%;
// padding: 0 4em;
align-items: center;
display: flex;
align-items: center;
::v-deep .el-slider {
flex: 1;
padding: 2em;
.el-slider__runway {
background-color: rgba(255, 255, 255, 0.2);
min-width: 200px;
width: 90%;
.el-slider__bar {
background-color: rgba(108, 177, 184, 1);
border-radius: 5px;
}
// 点
.el-slider__stop {
background-color: rgba(108, 177, 184, 1);
height: 10px;
width: 1px;
// top: -2px;
}
.el-slider__button {
display: none;
// background: linear-gradient(180deg, rgba(101, 220, 252, 1) 0%, rgba(67, 148, 171, 1) 100%);
// box-shadow: 0px 2px 4px 0px rgba(29, 142, 173, 0.6);
// filter: blur(0px);
}
// marks字
.el-slider__marks-text {
color: rgba(222, 244, 255, 1);
text-align: left;
left: 13%;
font-size: 14px;
font-weight: 400;
color: rgba(255, 255, 255, 1);
}
}
}
.optionWrapper {
display: flex;
justify-content: space-evenly;
align-items: center;
color: white;
width: fit-content;
height: 100%;
& > img {
// width: 40px;
height: 48%;
cursor: pointer;
}
}
}
</style>
+71
View File
@@ -0,0 +1,71 @@
/
<template>
<div ref="head" class="headers">
种植业生产监管数字化系统
<span @click="exitMaximize" class="exit">
<img
src="@/assets/svg/quxiaoquanping.svg"
style="width: 14px; height: 14px; cursor: pointer"
/>
退出全屏
</span>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import useSettingsStore from '@/store/modules/settings';
import useAppStore from '@/store/modules/app';
import usePermissionStore from '@/store/modules/permission';
const settingsStore = useSettingsStore();
const appStore = useAppStore();
const permissionStore = usePermissionStore();
let flag = ref(false);
onMounted(() => {
// console.log(document.querySelector('.menubar'));
});
const exitMaximize = () => {
document.querySelector('.navDiv').style.display = '';
document.querySelector('.app-main').style.height = 'calc(100% - 50px)';
document.querySelector('.headers').style.transform = `translate(0, -100%)`;
document.querySelector('.leftWra').style.top = '10px';
document.querySelector('.rightWra').style.top = '10px';
document.querySelector('.leftment').style.display = 'block';
document.querySelector('.main-container').style.marginLeft =
document.querySelector('.leftment').style.width;
};
</script>
<style lang="scss" scoped>
.headers {
position: fixed;
left: 0;
top: 0;
z-index: 1;
height: 80px;
line-height: 80px;
width: 100%;
display: flex;
box-sizing: border-box;
background-image: url('@/assets/images/header.png');
background-size: 100% 100%;
justify-content: center;
opacity: 1;
text-shadow: 0px 0px 6px 0px rgba(41, 255, 255, 1);
font-weight: 400;
font-size: 21px;
letter-spacing: 4px;
color: rgba(255, 255, 255, 1);
transform: translate(0, -100%);
.exit {
position: absolute;
top: 20px;
right: 20px;
display: flex;
align-items: center;
font-size: 14px;
color: rgba(41, 255, 219, 1);
cursor: pointer;
}
}
</style>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div id="cesiumContainer"></div>
<div style="width: 100%; height: 100%" id="cesiumContainer"></div>
</template>
<script setup>
+24
View File
@@ -0,0 +1,24 @@
import { onActivated, onDeactivated, onBeforeUnmount } from "vue";
// import echarts from "@/plugins/echarts";
export const useEcharts = (myChart, options) => {
if (options && typeof options === "object") {
myChart.setOption(options);
}
const echartsResize = () => {
myChart && myChart.resize();
};
window.addEventListener("resize", echartsResize);
onActivated(() => {
window.addEventListener("resize", echartsResize);
});
onDeactivated(() => {
window.removeEventListener("resize", echartsResize);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", echartsResize);
});
};
-1
View File
@@ -3,7 +3,6 @@
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" />
<top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" />
<div class="right-menu">
<template v-if="appStore.device !== 'mobile'">
<header-search id="header-search" class="right-menu-item" />
+4 -4
View File
@@ -2,12 +2,12 @@
<div class="sidebar-logo-container" :class="{ 'collapse': collapse }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
<!-- <img v-if="logo" :src="logo" class="sidebar-logo" /> -->
<!-- <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1> -->
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }}</h1>
<!-- <img v-if="logo" :src="logo" class="sidebar-logo" /> -->
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">种植业生产监管数字化系统</h1>
</router-link>
</transition>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<div class="leftment" :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
<el-menu
+1 -1
View File
@@ -3,7 +3,7 @@
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<sidebar v-if="!sidebar.hide" class="sidebar-container" />
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<div class="navDiv" :class="{ 'fixed-header': fixedHeader }">
<navbar @setLayout="setLayout" />
<tags-view v-if="needTagsView" />
</div>
+34 -34
View File
@@ -1,5 +1,5 @@
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
@@ -15,7 +15,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
baseURL: serverAPI.baseUrl,
// 超时
timeout: 10000
})
@@ -61,46 +61,46 @@ service.interceptors.request.use(config => {
}
return config
}, error => {
console.log(error)
Promise.reject(error)
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
})
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
error => {
console.log('err' + error)
let { message } = error;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+258 -471
View File
File diff suppressed because it is too large Load Diff
+172 -161
View File
@@ -1,94 +1,102 @@
<template>
<div class="login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">若依后台管理系统</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
size="large"
auto-complete="off"
placeholder="账号"
>
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
placeholder="密码"
@keyup.enter="handleLogin"
>
<template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
size="large"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter="handleLogin"
>
<template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
<div class="login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">登陆</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
size="large"
auto-complete="off"
placeholder="账号"
>
<template #prefix>
<svg-icon icon-class="user" class="el-input__icon input-icon" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
placeholder="密码"
@keyup.enter="handleLogin"
>
<template #prefix>
<svg-icon icon-class="password" class="el-input__icon input-icon" />
</template>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
size="large"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter="handleLogin"
>
<template #prefix>
<svg-icon icon-class="validCode" class="el-input__icon input-icon" />
</template>
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" />
</div>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">
记住密码
</el-checkbox>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="large"
type="primary"
style="width: 100%"
@click.prevent="handleLogin"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
</div>
</el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
<el-form-item style="width:100%;">
<el-button
:loading="loading"
size="large"
type="primary"
style="width:100%;"
@click.prevent="handleLogin"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
<div style="float: right;" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>
<script setup>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user'
import { getCodeImg } from '@/api/login';
import Cookies from 'js-cookie';
import { encrypt, decrypt } from '@/utils/jsencrypt';
import useUserStore from '@/store/modules/user';
const userStore = useUserStore()
const userStore = useUserStore();
const router = useRouter();
const { proxy } = getCurrentInstance();
const loginForm = ref({
username: "admin",
password: "admin123",
rememberMe: false,
code: "",
uuid: ""
username: 'admin',
password: 'admin123',
rememberMe: false,
code: '',
uuid: '',
});
const loginRules = {
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
code: [{ required: true, trigger: "change", message: "请输入验证码" }]
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
code: [{ required: true, trigger: 'change', message: '请输入验证码' }],
};
const codeUrl = ref("");
const codeUrl = ref('');
const loading = ref(false);
// 验证码开关
const captchaEnabled = ref(true);
@@ -97,119 +105,122 @@ const register = ref(false);
const redirect = ref(undefined);
function handleLogin() {
proxy.$refs.loginRef.validate(valid => {
if (valid) {
loading.value = true;
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
if (loginForm.value.rememberMe) {
Cookies.set("username", loginForm.value.username, { expires: 30 });
Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 });
Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 });
} else {
// 否则移除
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove("rememberMe");
}
// 调用action的登录方法
userStore.login(loginForm.value).then(() => {
router.push({ path: redirect.value || "/" });
}).catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
proxy.$refs.loginRef.validate(valid => {
if (valid) {
loading.value = true;
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
if (loginForm.value.rememberMe) {
Cookies.set('username', loginForm.value.username, { expires: 30 });
Cookies.set('password', encrypt(loginForm.value.password), { expires: 30 });
Cookies.set('rememberMe', loginForm.value.rememberMe, { expires: 30 });
} else {
// 否则移除
Cookies.remove('username');
Cookies.remove('password');
Cookies.remove('rememberMe');
}
// 调用action的登录方法
userStore
.login(loginForm.value)
.then(() => {
router.push({ path: redirect.value || '/' });
})
.catch(() => {
loading.value = false;
// 重新获取验证码
if (captchaEnabled.value) {
getCode();
}
});
}
});
}
});
});
}
function getCode() {
getCodeImg().then(res => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (captchaEnabled.value) {
codeUrl.value = "data:image/gif;base64," + res.img;
loginForm.value.uuid = res.uuid;
}
});
getCodeImg().then(res => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (captchaEnabled.value) {
codeUrl.value = 'data:image/gif;base64,' + res.img;
loginForm.value.uuid = res.uuid;
}
});
}
function getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get("rememberMe");
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
};
const username = Cookies.get('username');
const password = Cookies.get('password');
const rememberMe = Cookies.get('rememberMe');
loginForm.value = {
username: username === undefined ? loginForm.value.username : username,
password: password === undefined ? loginForm.value.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
};
}
getCode();
getCookie();
</script>
<style lang='scss' scoped>
<style lang="scss" scoped>
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url("../assets/images/login-background.jpg");
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('../assets/images/login-background.jpg');
background-size: cover;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
.el-input {
height: 40px;
input {
height: 40px;
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
.el-input {
height: 40px;
input {
height: 40px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 0px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
width: 33%;
height: 40px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 40px;
padding-left: 12px;
height: 40px;
padding-left: 12px;
}
</style>