Commit c51749d5 authored by “yiyousong”'s avatar “yiyousong”

feat: 添加系统证书校验

parent 26a7915e
......@@ -28,3 +28,13 @@ export function editPassword(params) {
export function changeForgotPassword(params) {
return http.post(`${baseURL}/zwfw/user/forgot/password`, params);
}
// 证书有效期检测
export function checkCipher(params) {
return http.get(`${baseURL}/zwfw/cipher/check`, params);
}
// 证书上传
export function uploadCipher(params) {
return http.post(`${baseURL}/zwfw/cipher/upload`, params);
}
<template>
<div class="license-hint" v-if="show">
<div class="card">
<div class="header">
<span class="icon">
<svg
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M18 3a1 1 0 00-1.447-.894L8.763 6H5a3 3 0 000 6h.28l1.771 5.316A1 1 0 008 18h1a1 1 0 001-1v-4.382l6.553 3.276A1 1 0 0018 15V3z"
fill-rule="evenodd"
></path>
</svg>
</span>
<p class="alert">证书过期提示!</p>
</div>
<p class="message">{{ licenseInfo.msg }}</p>
<div class="actions">
<a-button class="read" :loading="loading" @click="handleUpload">
点击上传新证书
</a-button>
<a-button
class="mark-as-read"
:disabled="isDisabled"
@click="handleClose"
>
关闭弹窗<span v-if="time">{{ time }}</span>
</a-button>
</div>
</div>
</div>
</template>
<script>
import { uploadCipher, checkCipher } from "@/api/user";
import { mapMutations, mapState } from "vuex";
export default {
data() {
return {
accept: "application/x-zip-compressed",
loading: false,
timer: null,
isDisabled: true,
time: 0,
show: true,
};
},
computed: {
...mapState("user", ["licenseInfo"]),
},
created() {
this.countDown();
},
methods: {
...mapMutations("user", ["set_licenseInfo"]),
countDown() {
this.time = this.duration;
this.timer = setInterval(() => {
this.time -= 1;
if (this.time <= 0) {
this.isDisabled = false;
this.time = 0;
clearInterval(this.timer);
}
}, 1000);
},
handleClose() {
// if (this.isDisabled) return;
this.show = false;
},
async handleUpload() {
let file = await this.getFile();
if (!file) return;
this.loading = true;
let formData = new FormData();
formData.append("file", file[0]);
let res = await uploadCipher(formData);
this.loading = false;
if (res.code == 1) {
this.checkCipher();
}
},
// 检测系统证书
async checkCipher() {
let res = await checkCipher();
if (res.code == 1) {
let { startTime, endTime } = res.data;
let msg = `证书上传成功,证书有效期:${startTime}${endTime}`;
this.set_licenseInfo({
isExpire: false,
msg: "",
});
this.$message.success(msg);
this.show = false;
} else {
this.set_licenseInfo({
isExpire: true,
msg: res.msg,
});
}
},
// 获取文件
getFile() {
let input = document.createElement("input");
document.body.appendChild(input);
return new Promise((resolve, reject) => {
Object.assign(input, {
accept: this.accept,
onchange: () => {
input.files ? resolve(input.files) : reject();
},
multiple: false,
onerror: reject,
type: "file",
hidden: true,
value: null,
});
input.click();
document.body.removeChild(input);
});
},
},
beforeDestroy() {
clearInterval(this.timer);
},
};
</script>
<style lang="less" scoped>
.license-hint {
width: 100%;
height: 100%;
position: fixed;
left: 0px;
top: 0px;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
.card {
width: 320px;
border-radius: 16px;
background-color: #fff;
padding: 16px;
}
.header {
display: flex;
align-items: center;
grid-gap: 16px;
gap: 16px;
}
.icon {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: #0857e8;
padding: 8px;
color: rgba(255, 255, 255, 1);
}
.icon svg {
height: 16px;
width: 16px;
}
.alert {
font-weight: 600;
color: rgba(107, 114, 128, 1);
}
.message {
margin-top: 16px;
color: rgba(107, 114, 128, 1);
line-height: 24px;
}
.actions {
margin-top: 20px;
}
/deep/.ant-upload {
width: 100%;
}
.mark-as-read,
.read {
width: 100%;
height: 44px;
// display: flex;
// align-items: center;
// justify-content: center;
// cursor: pointer;
border: none;
border-radius: 8px;
font-weight: 600;
}
.read {
background-color: #0857e8;
color: rgba(255, 255, 255, 1);
}
.mark-as-read {
margin-top: 8px;
background-color: rgba(249, 250, 251, 1);
color: rgba(107, 114, 128, 1);
transition: all 0.15s ease;
}
.mark-as-read:hover {
background-color: rgb(230, 231, 233);
}
// .mark-as-read[disabled] {
// cursor: not-allowed;
// }
}
</style>
import vue from "vue";
import LicenseHintModal from "./LicenseHint.vue";
import store from "@/store"; // 导入 Vuex store 实例
const licenseHintModal = vue.extend(LicenseHintModal);
function showLicenseHintModal(duration = 5) {
const existingModal = document.getElementById("licenseHintModal");
if (!existingModal) {
const dom = new licenseHintModal({
store,
el: document.createElement("div"),
data() {
return {
duration: duration,
};
},
});
dom.$el.id = "licenseHintModal";
document.body.appendChild(dom.$el);
}
}
function registryModal() {
vue.prototype.$licenseHintModal = showLicenseHintModal;
}
export default registryModal;
......@@ -63,6 +63,9 @@ Vue.prototype.$bus = new Vue();
// swiper
import "swiper/css/swiper.min.css";
// 注册证书过期提示弹窗
import registryModal from "@/components/licenseHint";
Vue.use(registryModal);
Vue.config.productionTip = false;
// 图片预览
......
......@@ -42,7 +42,7 @@ axios.interceptors.response.use(
message.error({
content: msg,
maxCount: 1,
duration: 1,
duration: 2,
});
if (msg === "非法用户,不可访问") {
store.commit("user/reset");
......@@ -117,7 +117,7 @@ axios.interceptors.response.use(
message.error({
message: error.message,
maxCount: 1,
duration: 1,
duration: 2,
});
return Promise.resolve(error.response);
......
......@@ -27,6 +27,10 @@ router.beforeEach((to, from, next) => {
// let bol = hasIntersection(toRootPathArr, routerPath);
if (islogin) {
next();
let licenseInfo = store.getters["user/licenseInfo"];
if (licenseInfo.isExpire) {
Vue.prototype.$licenseHintModal();
}
// if (routerPath.includes(to.path) || bol) {
// next();
// }
......
......@@ -12,6 +12,11 @@ export default {
siteId: "", // 站点id
searForm: {}, // 报表搜索
routerList: [], // 用户权限路由
licenseInfo: {
// 系统证书信息
isExpire: false, // 是否过期,
msg: "", // 过期提示信息
},
},
getters: {
siteId: (state) => state.siteId,
......@@ -29,6 +34,9 @@ export default {
siteTreeList(state) {
return state.siteList;
},
licenseInfo(state) {
return state.licenseInfo;
},
},
mutations: {
SET_routerList(state, routerList) {
......@@ -58,6 +66,10 @@ export default {
set_siteId(state, siteId) {
state.siteId = siteId;
},
set_licenseInfo(state, { isExpire, msg }) {
state.licenseInfo.isExpire = isExpire;
state.licenseInfo.msg = msg;
},
// 重置所有仓库状态
reset: () => {},
},
......
......@@ -248,7 +248,12 @@
<script>
import Swiper from "swiper";
import { LoginInterface, changeForgotPassword, getSlogan } from "@/api/user.js";
import {
LoginInterface,
changeForgotPassword,
getSlogan,
checkCipher,
} from "@/api/user.js";
import { mapMutations, mapState } from "vuex";
import { changeAccount, changePassWord } from "@/utils/js/validate";
import { encrypt, findSitesById } from "@/utils";
......@@ -329,7 +334,9 @@ export default {
this.createCode();
},
mounted() {
this.checkCipher();
this.initSwiper();
this.$licenseHintModal();
},
methods: {
...mapMutations("user", [
......@@ -337,7 +344,24 @@ export default {
"SET_USERDATA",
"set_siteList",
"SET_routerList",
"set_licenseInfo",
]),
// 检测系统证书是否过期
async checkCipher() {
let res = await checkCipher();
if (res.code == 1) {
this.set_licenseInfo({
isExpire: false,
msg: "",
});
} else {
this.set_licenseInfo({
isExpire: true,
msg: res.msg,
});
this.$licenseHintModal();
}
},
getTitle() {
getSlogan("signImg").then((res) => {
if (res.code == 1) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment