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

feat: 添加系统证书校验

parent 26a7915e
...@@ -28,3 +28,13 @@ export function editPassword(params) { ...@@ -28,3 +28,13 @@ export function editPassword(params) {
export function changeForgotPassword(params) { export function changeForgotPassword(params) {
return http.post(`${baseURL}/zwfw/user/forgot/password`, 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(); ...@@ -63,6 +63,9 @@ Vue.prototype.$bus = new Vue();
// swiper // swiper
import "swiper/css/swiper.min.css"; import "swiper/css/swiper.min.css";
// 注册证书过期提示弹窗
import registryModal from "@/components/licenseHint";
Vue.use(registryModal);
Vue.config.productionTip = false; Vue.config.productionTip = false;
// 图片预览 // 图片预览
......
...@@ -42,7 +42,7 @@ axios.interceptors.response.use( ...@@ -42,7 +42,7 @@ axios.interceptors.response.use(
message.error({ message.error({
content: msg, content: msg,
maxCount: 1, maxCount: 1,
duration: 1, duration: 2,
}); });
if (msg === "非法用户,不可访问") { if (msg === "非法用户,不可访问") {
store.commit("user/reset"); store.commit("user/reset");
...@@ -117,7 +117,7 @@ axios.interceptors.response.use( ...@@ -117,7 +117,7 @@ axios.interceptors.response.use(
message.error({ message.error({
message: error.message, message: error.message,
maxCount: 1, maxCount: 1,
duration: 1, duration: 2,
}); });
return Promise.resolve(error.response); return Promise.resolve(error.response);
......
...@@ -27,6 +27,10 @@ router.beforeEach((to, from, next) => { ...@@ -27,6 +27,10 @@ router.beforeEach((to, from, next) => {
// let bol = hasIntersection(toRootPathArr, routerPath); // let bol = hasIntersection(toRootPathArr, routerPath);
if (islogin) { if (islogin) {
next(); next();
let licenseInfo = store.getters["user/licenseInfo"];
if (licenseInfo.isExpire) {
Vue.prototype.$licenseHintModal();
}
// if (routerPath.includes(to.path) || bol) { // if (routerPath.includes(to.path) || bol) {
// next(); // next();
// } // }
......
...@@ -12,6 +12,11 @@ export default { ...@@ -12,6 +12,11 @@ export default {
siteId: "", // 站点id siteId: "", // 站点id
searForm: {}, // 报表搜索 searForm: {}, // 报表搜索
routerList: [], // 用户权限路由 routerList: [], // 用户权限路由
licenseInfo: {
// 系统证书信息
isExpire: false, // 是否过期,
msg: "", // 过期提示信息
},
}, },
getters: { getters: {
siteId: (state) => state.siteId, siteId: (state) => state.siteId,
...@@ -29,6 +34,9 @@ export default { ...@@ -29,6 +34,9 @@ export default {
siteTreeList(state) { siteTreeList(state) {
return state.siteList; return state.siteList;
}, },
licenseInfo(state) {
return state.licenseInfo;
},
}, },
mutations: { mutations: {
SET_routerList(state, routerList) { SET_routerList(state, routerList) {
...@@ -58,6 +66,10 @@ export default { ...@@ -58,6 +66,10 @@ export default {
set_siteId(state, siteId) { set_siteId(state, siteId) {
state.siteId = siteId; state.siteId = siteId;
}, },
set_licenseInfo(state, { isExpire, msg }) {
state.licenseInfo.isExpire = isExpire;
state.licenseInfo.msg = msg;
},
// 重置所有仓库状态 // 重置所有仓库状态
reset: () => {}, reset: () => {},
}, },
......
...@@ -248,7 +248,12 @@ ...@@ -248,7 +248,12 @@
<script> <script>
import Swiper from "swiper"; 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 { mapMutations, mapState } from "vuex";
import { changeAccount, changePassWord } from "@/utils/js/validate"; import { changeAccount, changePassWord } from "@/utils/js/validate";
import { encrypt, findSitesById } from "@/utils"; import { encrypt, findSitesById } from "@/utils";
...@@ -329,7 +334,9 @@ export default { ...@@ -329,7 +334,9 @@ export default {
this.createCode(); this.createCode();
}, },
mounted() { mounted() {
this.checkCipher();
this.initSwiper(); this.initSwiper();
this.$licenseHintModal();
}, },
methods: { methods: {
...mapMutations("user", [ ...mapMutations("user", [
...@@ -337,7 +344,24 @@ export default { ...@@ -337,7 +344,24 @@ export default {
"SET_USERDATA", "SET_USERDATA",
"set_siteList", "set_siteList",
"SET_routerList", "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() { getTitle() {
getSlogan("signImg").then((res) => { getSlogan("signImg").then((res) => {
if (res.code == 1) { 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