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

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
src/api/crops/classify.js Normal file
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',
})
}

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
src/assets/images/1.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

BIN
src/assets/images/below.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
src/assets/images/login-background.jpg Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 KiB

After

Width:  |  Height:  |  Size: 7.0 MiB

BIN
src/assets/images/start.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
src/assets/images/suspend.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
src/assets/images/upper.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

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>

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>

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>

View File

@ -1,5 +1,5 @@
<template>
<div id="cesiumContainer"></div>
<div style="width: 100%; height: 100%" id="cesiumContainer"></div>
</template>
<script setup>

24
src/hooks/useEcharts.js Executable file
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);
});
};

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" />

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>

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

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>

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

File diff suppressed because it is too large Load Diff

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>