提交 a41dc529 authored 作者: 冯小芳's avatar 冯小芳
VITE_DEV_API="/mock"
VITE_PRD_API="/mock"
VITE_DEV_API="/api"
VITE_PRD_API="/"
VITE_SYSTEM_NAMR="创新示范绩效评价"
\ No newline at end of file
<template>
<div class="app-container">
<AppHead />
<div class="main-warpper">
<!-- <div class="main-warpper">
<router-view> </router-view>
</div>
</div>
</div> -->
<router-view> </router-view>
</template>
<script lang="ts">
import { defineComponent } from "vue";
......@@ -31,21 +30,4 @@ export default defineComponent({
font-family: "tabTypeFace";
src: url("../public/assets/tabTypeFace.TTF");
}
#app {
box-sizing: border-box;
}
.app-container {
display: flex;
flex-direction: column;
height: 100%;
padding: 20px;
background: #f5f9fb;
min-width: 1920px;
box-sizing: border-box;
}
.main-warpper {
flex: 1;
box-sizing: border-box;
}
</style>
import { AxiosResponse } from "axios"
export default (response: AxiosResponse) => {
const { data } = response;
// console.log("---", response)
return response.data
}
\ No newline at end of file
......@@ -76,15 +76,14 @@
<!-- 年度 -->
<el-col class="year-items">
<div class="years" align="middle" >
<div class="years" align="middle">
<span
v-for="(item, index) in years"
:key="item.label"
:class="{
active: index === curYearIndex,
disabed: item.disabed
disabed: item.disabed,
}"
@click="yearHandle(item, index)"
>{{ item.label }}</span
>
......@@ -98,7 +97,6 @@
import { defineComponent } from "vue";
import { getNavList } from "./service";
import { ArrowLeftBold, CaretRight } from "@element-plus/icons";
import { routes } from "@/route";
const ENV_PARAMS = import.meta.env; // 这是Vite官方指导获取环境变量的方式
......@@ -118,17 +116,17 @@ export default defineComponent({
{
label: "2020年第四季度",
value: "typeOne",
disabed: true
disabed: true,
},
{
label: "2021年第二季度",
value: "typeTwo",
disabed: false
disabed: false,
},
{
label: "2021年第三季度",
value: "typeThree",
disabed: false
disabed: false,
},
],
curYearIndex: 1,
......@@ -138,15 +136,18 @@ export default defineComponent({
async mounted() {
const { data: navList } = await getNavList();
this.navList = navList || [];
// @ts-ignore
this.secodndList = navList[this.activeIndex]?.children || [];
this.init();
},
watch: {
$route() {
const { meta, path } = this.$route;
const { VITE_SYSTEM_NAMR = "创新示范绩效评价" } = ENV_PARAMS;
const routHistroy = [];
meta.person &&
routHistroy.push({
path: meta.person.path,
......@@ -166,10 +167,25 @@ export default defineComponent({
];
},
},
methods: {
init() {
const { meta, path } = this.$route;
const { VITE_SYSTEM_NAMR = "创新示范绩效评价" } = ENV_PARAMS;
this.curRouteHistoy = [
{
path: "/",
label: VITE_SYSTEM_NAMR,
},
{
path,
label: meta.label,
},
];
},
yearHandle(item: {}, index: Number) {
if(item.disabed) return;
if (item.disabed) return;
this.$store.commit("SET_CUR_DATA_TYPE", item.value);
this.curYearIndex = index;
},
......@@ -337,7 +353,7 @@ export default defineComponent({
color: #4198ff;
}
}
.disabed{
.disabed {
// background:#f5f5f5 !important;
cursor: not-allowed !important;
color: #ccc !important;
......
......@@ -5,12 +5,50 @@ import {
DataCenterRouter
} from "./dataCenter"
/**
* 基础路由
*/
export enum BaseRouteRouter {
LOGIN = "/login",
SSO = '/sso',
NOT_FIND="/404"
}
export const routes: any[] = [
...dataCenter,
{
path: "/:pathMatch(.*)*",
path: "/",
redirect: DataCenterRouter.DATA_MAP,
},
{
path: "/index",
redirect: DataCenterRouter.DATA_MAP,
},
{
path: BaseRouteRouter.LOGIN,
meta: {
label: "登录",
},
name: "login",
component: () => import("@/views/login/index.vue")
},
{
path: BaseRouteRouter.SSO,
meta: {
label: "卫士通",
},
name: "sso",
component: () => import("@/views/sso/index.vue")
},
{
path: "/:pathMatch(.*)*",
meta: {
label: "404",
},
name: "404",
component: () => import("@/views/404/index.vue")
},
]
const router = createRouter({
......
import {Router} from "vue-router"
import { Router } from "vue-router"
import { TOKEN_KEY } from "@/utils/enum/token.ts";
import { BaseRouteRouter } from "./index"
const whiteRoutes = ["/login", "/sso"]
export default (router: Router) => {
const token = localStorage.getItem("token")
// router.beforeEach((to, from, next) => {
// // if(!token) {
// // to.path === "/login" ? next() : router.replace("/login");
// // }else {
// // next()
// // }
// next()
// })
const token = localStorage.getItem(TOKEN_KEY)
router.beforeEach((to, from, next) => {
if (whiteRoutes.includes(to.path)) {
return next()
}
if (!token) {
router.replace(BaseRouteRouter.LOGIN);
} else {
next()
}
})
return router
}
\ No newline at end of file
export const TOKEN_KEY = "cxsf_echartd_token"
\ No newline at end of file
import request from '@/axios'
//单点登录校验
export const getLogin = async () => {
return request({
url: "/user/generatorChallenge"
})
}
/**
* 登录系统
* @param {*} challenge // getLogin 接口返回的
* @param {*} ticket // webSokect 成功后返回的
* @param {*} type // 0|1 平台端|企业端
* @param {*} flag // false 卫士通登录
* @returns
*/
export const postLogin = async (challenge:string, ticket:string) => {
return request({
url: "/sso",
method: "post",
data: {
challenge,
ticket,
type: 0,
flag: false
}
})
}
\ No newline at end of file
import wstVaildate from "./wst"
import {ElMessage, ElLoading } from "element-plus";
import { getLogin, postLogin } from "./api"
export const SINGLE_LOGIN_KEY = "mcj_platform_single_login"
const OPTION_LOADING = {
// 声明一个loading对象
lock: true, // 是否锁屏
text: "正在检查key,请稍后...", // 加载动画的文字
spinner: "el-icon-loading", // 引入的loading图标
background: "rgba(0, 0, 0, 0.5)", // 背景颜色
target: ".sub-main", // 需要遮罩的区域
body: true,
customClass: "mask", // 遮罩层新增类名
}
// 单点登录校验
const singleLogin = async () => {
return new Promise(async (resolve, reject) => {
const loading = ElLoading.service(OPTION_LOADING);
try {
getLogin().then(async (res) => {
const { data } = res || {}
if (!data) {
loading.close();
ElMessage.error("身份校验失败");
return resolve(true)
}
const { result = false, params = {} } = await wstVaildate(data);
const { challenge, ticket } = params;
if (result) {
postLogin(challenge, ticket).then((res) => {
resolve(true)
}).catch(() => {
reject()
})
}
}).catch(() => {
reject()
})
} catch (error) {
console.log("error:", error);
reject()
} finally {
loading.close();
}
})
}
export default singleLogin
\ No newline at end of file
import {
ElMessage
} from "element-plus";
const WEB_SOCKET_URL = "ws://127.0.0.1:36107"
const bl = async (L) => {
var l = "";
for (let i = 0; i < L; i++) {
l = l + "0";
}
return l;
}
//计算body长度
const sendlen = async (str) => {
var s = 0;
for (var i = 0; i < str.length; i++) {
if (str.charAt(i).match(/^[\u4e00-\u9fa5]+$/)) {
s += 3;
} else {
s++;
}
}
s = String(s);
var l = s.length;
var L = 10 - l;
var bodylen = await bl(L) + s;
return bodylen;
}
const xmlStrToXmlObj = async (xmlStr) => {
var xmlObj = {};
if (document.all) {
var xmlDom = new ActiveXObject("Microsoft.XMLDOM");
xmlDom.loadXML(xmlStr);
xmlObj = xmlDom;
} else {
xmlObj = new DOMParser().parseFromString(xmlStr, "text/xml");
}
return xmlObj;
}
const xmlObjToJsonObj = (xmlNodes) => {
var obj = {};
if (xmlNodes.length == 0) {
obj = "";
} else {
for (var i = 0; i < xmlNodes.length; i++) {
var node = xmlNodes[i];
if (typeof node.tagName == "undefined" || node.nodeName == "#text") {
obj = node.nodeValue;
} else {
var key = node.tagName;
var value = xmlObjToJsonObj(node.childNodes);
obj[key] = value;
}
}
}
return obj;
}
// xml数据格式转换
const xmlStrToJsonObj = async (xmlStr) => {
const xmlObj = await xmlStrToXmlObj(xmlStr);
let jsonObj = {};
if (xmlObj.childNodes.length > 0) {
jsonObj = await xmlObjToJsonObj(xmlObj.childNodes);
}
return jsonObj;
}
// 建立webSokect连接
const webSokect = async (randSign, webSocketUrl) => {
if (!randSign || !webSocketUrl) {
return {
result: false
}
}
return new Promise(async (resolve, reject) => {
const bodyx =
`<body><plain><info><random>${randSign}</random></info></plain></body>`;
const bodylen = await sendlen(bodyx);
//套接字单点登录
const ws = new WebSocket(webSocketUrl);
ws.onopen = async function (event) {
ws.send(
"<head><bsid> ml0305c</bsid><bodylen>" +
bodylen +
"</bodylen><digest_id> </digest_id><cipher_id> </cipher_id></head>" +
bodyx +
""
);
};
// websokect 错误处理
ws.onerror = async (event) => {
reject(new Error("websokect连接错误"))
};
ws.onmessage = async function (event) {
let resStr = event.data;
//在外面包了一层他反过来的结构不标准
resStr = `<cush>${resStr}</cush>`;
const jsonObj = await xmlStrToJsonObj(resStr);
const {
errcode,
appendix,
errstr
} = jsonObj.cush.body.plain || {}
if (errcode == "0") {
resStr = appendix
} else {
ElMessage.error(errstr)
reject(new Error("onmessage响应,errorCode命中"))
}
if ("generate random2 error" == resStr) {
reject(new Error("generate random2 error"))
} else {
//要求后进行验证
resolve({
result: true,
params: {
challenge: randSign,
ticket: resStr
}
})
}
};
})
}
/**
* 卫士通验证
*/
const wstVaildate = async (randSign) => {
return webSokect(randSign, WEB_SOCKET_URL)
}
export default wstVaildate
\ No newline at end of file
<template>
404
</template>
\ No newline at end of file
<template>
<router-view></router-view>
<div class="main-warpper">
<AppHead />
<router-view> </router-view>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { defineComponent } from "vue";
import AppHead from "@/layout/head.vue";
/**
* 数据中心模块
*/
export default defineComponent({
setup() {
},
})
components: {
AppHead,
},
setup() {},
});
</script>
<style lang="scss" scoped>
.main-warpper {
min-width: 1920px;
flex: 1;
box-sizing: border-box;
padding: 20px;
}
</style>
<template>
<div class="login">
<div class="main">
<!-- logo -->
<img src="../../assets/logo/logo.png" alt class="img1" />
<!-- 中间插图 -->
<img src="../../assets/img/img2.png" alt class="img2" />
<!-- 标题 -->
<h5>创新示范和绩效评价数智应用</h5>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<h2 class="title">欢迎登录</h2>
<!-- 用户名 -->
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
@focus="isUsername = true"
@blur="isUsername = false"
placeholder="用户名"
>
</el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="密码"
@focus="isPassword = true"
@blur="isPassword = false"
@keyup.enter.native="handleLogin"
>
</el-input>
</el-form-item>
<!-- 登录按钮 -->
<el-checkbox
v-model="loginForm.rememberMe"
style="margin: 0px 0px 35px 0px"
>记住密码</el-checkbox
>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click="handleLogin"
>
{{ loading ? "登 录 中..." : "登 录" }}
</el-button>
<el-button
size="medium"
style="width: 100%; margin-left: 0px"
@click="wstLogin"
>
统一身份登录
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import singleLogin from "@/utils/singleLogin/index";
import { TOKEN_KEY } from "@/utils/enum/token";
import { defineComponent } from "vue";
import { getToken, login } from "./service";
export default defineComponent({
name: "Login",
data() {
return {
wstLoading: false,
isUsername: false,
isPassword: false,
loginForm: {
username: "",
password: "",
rememberMe: false,
code: "",
uuid: "",
type: 1,
},
loginRules: {
username: [
{ required: true, trigger: "blur", message: "用户名不能为空" },
],
password: [
{ required: true, trigger: "blur", message: "密码不能为空" },
],
code: [
{ required: true, trigger: "change", message: "验证码不能为空" },
],
},
loading: false,
};
},
watch: {},
created() {
localStorage.removeItem(TOKEN_KEY);
},
methods: {
wstLogin() {
this.wstLoading = true;
singleLogin()
.then(async () => {
const { data } = await getToken();
localStorage.setItem(TOKEN_KEY, data);
this.$router.push("/");
})
.catch(() => {
this.$message.error("身份验证失败");
})
.finally(() => {
this.wstLoading = false;
});
},
handleLogin() {
const loginForm = this.loginForm;
login(loginForm.username, loginForm.password)
.then(async (res) => {
const { data } = await getToken();
localStorage.setItem(TOKEN_KEY, data);
this.$router.push("/");
})
.catch((err) => {
this.$message.error("用户名或密码错误!");
});
},
},
});
</script>
<style lang="scss" scoped>
.login {
background-image: url("../../assets/img/login_bg.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: 100vh;
min-height: 810px;
min-width: 1050px;
font-size: 0.16rem;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.main {
position: relative;
width: 940px;
height: 495px;
background: #407ef2;
border-radius: 12px;
box-shadow: 0px 2px 12px 0px rgba(80, 15, 180, 1);
color: rgba(255, 255, 255, 1);
.img1 {
position: absolute;
top: 54px;
left: 80px;
width: 26px;
}
.img2 {
position: absolute;
top: 138px;
left: 86px;
width: 384px;
height: 335px;
}
h3 {
margin-left: 52px;
margin-top: 383px;
margin-bottom: 0;
font-size: 32px;
}
h5 {
margin-left: 115px;
margin-top: 52px;
font-size: 24px;
font-weight: 600;
}
.login-form {
position: absolute;
right: 0;
top: 0;
border-radius: 6px;
background: #ffffff;
width: 299px;
height: 404px;
padding: 58px 33px 33px 33px;
.title {
width: 85px;
font-size: 20px;
margin: 12px auto 56px auto;
border-bottom: 3px #1790ff ridge;
border-radius: 2px;
text-align: center;
color: #333333;
padding-bottom: 8px;
}
.el-input {
height: 32px;
input:focus {
color: rgba(6, 104, 185, 1);
}
input {
outline: none;
height: 38px;
border-top: 0;
border-left: 0;
border-right: 0;
border-radius: 0;
}
}
.color-class {
color: rgba(6, 104, 185, 1);
}
.input-icon {
height: 39px;
width: 19px;
margin-left: 2px;
}
}
}
}
</style>
import request from "@/axios";
//token
export const getToken = async () => {
return request({
url: "/user/getCurrentUser",
method: "get",
})
}
/**
* 登录
* @param username
* @param password
*/
export const login = async (username: string, password: string) => {
request({
url: "/user/login?username=" + username + '&password=' + password,
method: "POST",
})
}
\ No newline at end of file
<template>
<div v-loading="wstLoading" class="login1">
<div class="main">
<img src="../../assets/img/login_bg.jpg" alt class="img1" />
</div>
</div>
</template>
<script>
import singleLogin from "@/utils/singleLogin/index";
import { getToken } from "./service";
import { TOKEN_KEY } from "@/utils/enum/token";
export default {
name: "sso",
data() {
return {
wstLoading: false,
};
},
watch: {},
created() {
localStorage.removeItem(TOKEN_KEY);
this.wstLogin();
},
mounted() {
},
methods: {
wstLogin() {
this.wstLoading = true;
singleLogin()
.then(async() => {
const { data } = await getToken();
localStorage.setItem(TOKEN_KEY, data);
this.$router.push("/");
})
.catch(() => {
this.$message.error("身份验证失败");
this.$router.push("/login");
})
.finally(() => {
this.wstLoading = false;
});
},
},
};
</script>
<style lang="scss" scoped>
.login1 {
width: 100%;
height: 100%;
.main {
width: 100%;
height: 100%;
.img1 {
width: 100%;
height: 100%;
}
}
}
</style>
import request from "@/axios";
//token
export const getToken = async () => {
return request({
url: "/user/getCurrentUser",
method: "get",
})
}
/**
* 登录
* @param username
* @param password
*/
export const login = async (username: string, password: string) => {
request({
url: "",
method: "POST",
data: {
username,
password
}
})
}
\ No newline at end of file
......@@ -7,7 +7,14 @@ import { resolve } from 'path'
export default defineConfig({
server:{
host:'0.0.0.0'
host:'0.0.0.0',
proxy: { // 配置域名代理
"/api": {
target: "http://192.168.0.100:9064",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
resolve: {
alias: {
......@@ -29,13 +36,5 @@ export default defineConfig({
// delay: [0, 200],
// }),
],
// server: {
// proxy: { // 配置域名代理
// "/api": {
// target: "http://jsonplaceholder.typicode.com",
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ""),
// },
// },
// },
});
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论