卫星通信与导航应用服务平台入口页面
This commit is contained in:
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
29
README.md
Normal file
29
README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# open-map-assistant
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
49
index.html
Normal file
49
index.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="w-h-full">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>卫星通信与导航应用服务平台</title>
|
||||
<style>
|
||||
/* 当屏幕宽度大于或等于3000px时 */
|
||||
@media (min-width: 3000px) {
|
||||
html {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 当屏幕宽度在1920px到2999px之间时 */
|
||||
@media (min-width: 1920px) and (max-width: 2999px) {
|
||||
html {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 当屏幕宽度在750px到1919px之间时 */
|
||||
@media (min-width: 750px) and (max-width: 1919px) {
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 当屏幕宽度在600px到749px之间时 */
|
||||
@media (min-width: 600px) and (max-width: 749px) {
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 当屏幕宽度小于600px时 */
|
||||
@media (max-width: 599px) {
|
||||
html {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="w-h-full">
|
||||
<div id="app" class="w-h-full text-white"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
8
jsconfig.json
Normal file
8
jsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
42
package.json
Normal file
42
package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "Satellite-Communication-And-Navigation-Application-Service-Platform",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --port=7023",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"axios": "^1.6.8",
|
||||
"cesium": "^1.117.0",
|
||||
"core-js": "^3.37.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts": "^5.5.0",
|
||||
"element-plus": "^2.7.2",
|
||||
"esbuild": "^0.21.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"fingerprintjs2": "^2.1.4",
|
||||
"ol": "^9.1.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persist": "^1.0.0",
|
||||
"vue": "^3.4.21",
|
||||
"vue-cesium": "^v3.2.7",
|
||||
"vue-echarts": "^6.7.2",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.3.0",
|
||||
"vue3-openlayers": "^8.1.0",
|
||||
"zipson": "^0.2.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"unplugin-auto-import": "^0.17.5",
|
||||
"unplugin-vue-components": "^0.27.0",
|
||||
"vite": "^5.2.8"
|
||||
}
|
||||
}
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
11
src/App.vue
Normal file
11
src/App.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
113
src/api/index.js
Normal file
113
src/api/index.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import axios from "axios";
|
||||
import $url from "./url";
|
||||
import router from "../router";
|
||||
import { encrypt } from "../utils/aes";
|
||||
|
||||
// 添加请求拦截器
|
||||
axios.interceptors.request.use(function (config) {
|
||||
// 在发送请求之前做些什么
|
||||
if (config.headers) {
|
||||
config.headers.uid = localStorage.data;
|
||||
if (localStorage.access_token && localStorage.access_token !== "" && localStorage.access_token !== null && localStorage.access_token !== undefined && localStorage.access_token !== NaN) {
|
||||
config.headers.authorization = localStorage.access_token;
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}, function (error) {
|
||||
// 对请求错误做些什么
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// 转到登录页面
|
||||
const toLogin = () => {
|
||||
localStorage.clear();
|
||||
const data = { origin_url: window.location.href };
|
||||
axios.post($url.toLogin, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
window.location.href = res.data.redirect;
|
||||
} else {
|
||||
router.push({ path: '/404page' });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加响应拦截器
|
||||
let result = true;
|
||||
axios.interceptors.response.use(function (response) {
|
||||
// 2xx 范围内的状态码都会触发该函数。
|
||||
// 对响应数据做点什么
|
||||
if (response.data.code === 200) {
|
||||
if ("access_token" in response.data) {
|
||||
localStorage.setItem("access_token", response.data.access_token);
|
||||
}
|
||||
if ("refresh_token" in response.data) {
|
||||
localStorage.setItem("refresh_token", response.data.refresh_token);
|
||||
}
|
||||
if ("data" in response.data) {
|
||||
localStorage.setItem("data", response.data.data);
|
||||
}
|
||||
}
|
||||
if(response.data.code === 401 && result) {
|
||||
result = false;
|
||||
setTimeout(() => {
|
||||
result = true;
|
||||
}, 1000);
|
||||
let getCode = window.location.href.indexOf('?');
|
||||
if (getCode != '-1') {
|
||||
let code = window.location.href.substring(getCode + 1);
|
||||
const data = {
|
||||
code: code,
|
||||
type: encrypt('code')
|
||||
};
|
||||
axios.post($url.getToken, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.setItem("data", res.data.data);
|
||||
localStorage.setItem("access_token", res.data.access_token);
|
||||
localStorage.setItem("refresh_token", res.data.refresh_token);
|
||||
window.location.href = res.data.redirect;
|
||||
} else {
|
||||
toLogin();
|
||||
}
|
||||
});
|
||||
} else if (localStorage.refresh_token && localStorage.refresh_token !== "" && localStorage.refresh_token !== null && localStorage.refresh_token !== undefined && localStorage.refresh_token !== NaN) {
|
||||
const data = {
|
||||
code: localStorage.refresh_token,
|
||||
type: localStorage.data
|
||||
};
|
||||
axios.post($url.getToken, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.setItem("data", res.data.data);
|
||||
localStorage.setItem("access_token", res.data.access_token);
|
||||
localStorage.setItem("refresh_token", res.data.refresh_token);
|
||||
window.location.reload();
|
||||
} else {
|
||||
toLogin();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
toLogin();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}, function (error) {
|
||||
// 超出 2xx 范围的状态码都会触发该函数。
|
||||
// 对响应错误做点什么
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default {
|
||||
get(url, query = {}) {
|
||||
return axios.get(url, {
|
||||
params: query
|
||||
});
|
||||
},
|
||||
post(url, body) {
|
||||
return axios.post(url, body);
|
||||
},
|
||||
put(url, body) {
|
||||
return axios.put(url, body);
|
||||
},
|
||||
del(url) {
|
||||
return axios.delete(url);
|
||||
},
|
||||
}
|
||||
16
src/api/url.js
Normal file
16
src/api/url.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export default {
|
||||
// 用于确认哪个网页在进行登录
|
||||
toLogin: "/authentication/toLogin",
|
||||
// 退出登录
|
||||
unLogin: "/authentication/unLogin",
|
||||
// 用于获取token
|
||||
getToken: "/authentication/getToken",
|
||||
// 用于验证token
|
||||
verify: "/authentication/verify",
|
||||
// 获取用户基本信息
|
||||
getUser: "/authentication/getUser",
|
||||
// 修改用户基本信息
|
||||
editUser: "/authentication/editUser",
|
||||
// 修改密码
|
||||
changePassword: "/authentication/changePassword",
|
||||
}
|
||||
BIN
src/assets/bdjyLogo.png
Normal file
BIN
src/assets/bdjyLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 166 KiB |
BIN
src/assets/bdqhLogo.png
Normal file
BIN
src/assets/bdqhLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/assets/bg.jpg
Normal file
BIN
src/assets/bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 760 KiB |
BIN
src/assets/favicon.ico
Normal file
BIN
src/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
9
src/assets/main.css
Normal file
9
src/assets/main.css
Normal file
@@ -0,0 +1,9 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.w-h-full {
|
||||
@apply w-full h-full m-0 p-0 overflow-hidden;
|
||||
}
|
||||
}
|
||||
173
src/components/changePassword.vue
Normal file
173
src/components/changePassword.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="密码管理" width="600" center align-center>
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
style="max-width: 600px"
|
||||
:model="ruleForm"
|
||||
:rules="rules"
|
||||
label-width="auto"
|
||||
size="default"
|
||||
status-icon
|
||||
>
|
||||
<el-form-item label="原密码" prop="oldPassword">
|
||||
<el-input
|
||||
clearable
|
||||
placeholder="请输入原密码"
|
||||
type="password"
|
||||
show-password
|
||||
maxlength="16"
|
||||
autocomplete="off"
|
||||
v-model="ruleForm.oldPassword"
|
||||
@input="filter(ruleForm.oldPassword, 'oldPassword')"
|
||||
oncut="return false"
|
||||
onpaste="return false"
|
||||
oncopy="return false"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-text class="mx-1" size="small" type="info">
|
||||
密码必须包含数字、大小写字母以及特殊字符(!@#$%^&*),且长度在8-16位之间
|
||||
</el-text>
|
||||
<el-input
|
||||
clearable
|
||||
placeholder="请输入新密码"
|
||||
type="password"
|
||||
show-password
|
||||
maxlength="16"
|
||||
autocomplete="off"
|
||||
v-model="ruleForm.newPassword"
|
||||
@input="filter(ruleForm.newPassword, 'newPassword')"
|
||||
oncut="return false"
|
||||
onpaste="return false"
|
||||
oncopy="return false"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码" prop="checkPass">
|
||||
<el-input
|
||||
clearable
|
||||
placeholder="请再次输入新密码"
|
||||
type="checkPass"
|
||||
show-password
|
||||
maxlength="16"
|
||||
autocomplete="off"
|
||||
v-model="ruleForm.checkPass"
|
||||
@input="filter(ruleForm.checkPass, 'checkPass')"
|
||||
oncut="return false"
|
||||
onpaste="return false"
|
||||
oncopy="return false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="resetForm(ruleFormRef)">取消</el-button>
|
||||
<el-button type="primary" @click="changePassword(ruleFormRef)">
|
||||
提交修改
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
import { encrypt } from "../utils/aes";
|
||||
|
||||
import $http from "../api/index";
|
||||
import $url from "../api/url";
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
|
||||
const ruleFormRef = ref();
|
||||
const ruleForm = reactive({
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
checkPass: "",
|
||||
});
|
||||
|
||||
const filter = (value, label) => {
|
||||
if (/[=\s"'+-]/.test(value)) {
|
||||
if (ruleForm[label]) {
|
||||
ruleForm[label] = value.replace(/[=\s"'+-]/g, "");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const passwordRegex = /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*]).{8,16}$/;
|
||||
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error("请输入密码"));
|
||||
} else if (!passwordRegex.test(value)) {
|
||||
callback(
|
||||
new Error(
|
||||
"密码必须包含数字、大小写字母以及特殊字符(!@#$%^&*),且长度在8-16位之间"
|
||||
)
|
||||
);
|
||||
} else {
|
||||
if (ruleForm.checkPass !== "") {
|
||||
if (!ruleFormRef.value) return;
|
||||
ruleFormRef.value.validateField("checkPass");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const validateCheck = (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error("请再次输入密码"));
|
||||
} else if (value !== ruleForm.newPassword) {
|
||||
callback(new Error("两次输入的密码不一致"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const rules = reactive({
|
||||
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
|
||||
newPassword: [{ required: true, validator: validatePass, trigger: "blur" }],
|
||||
checkPass: [{ required: true, validator: validateCheck, trigger: "blur" }],
|
||||
});
|
||||
|
||||
const resetForm = (formEl) => {
|
||||
dialogVisible.value = false;
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
};
|
||||
|
||||
const changePassword = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
dialogVisible.value = false;
|
||||
let encryptForm = {
|
||||
oldPassword: encrypt(ruleForm.oldPassword),
|
||||
newPassword: encrypt(ruleForm.newPassword),
|
||||
};
|
||||
formEl.resetFields();
|
||||
const data = {
|
||||
passwordForm: encryptForm,
|
||||
uid: localStorage.data
|
||||
};
|
||||
$http
|
||||
.post($url.changePassword, data)
|
||||
.then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
} else {
|
||||
ElMessage.error("密码修改失败!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ElMessage.error("提交失败!");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({ dialogVisible });
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
12
src/components/footer.vue
Normal file
12
src/components/footer.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
class="h-full p-5 flex justify-center items-center text-white font-bold"
|
||||
style="background-color: #222d2b"
|
||||
>
|
||||
技术支持电话:400-166-5286
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style scoped></style>
|
||||
187
src/components/header.vue
Normal file
187
src/components/header.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<div
|
||||
class="h-full p-5 flex flex-wrap justify-between items-center"
|
||||
style="background-color: #232d3b"
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<a href="http://www.hwasmart.com"><img style="width: 150px;" :src="bdqhLogo" alt="" /></a>
|
||||
|
||||
|
||||
<a href="http://www.beidouin.com"><img style="width:150px;" :src="bdjyLogo" alt="" /></a>
|
||||
</div>
|
||||
<div style="font-size: 2rem;" class="text-center flex-auto font-bold text-gray-800 text-white">卫星通信与导航应用服务平台</div>
|
||||
<div style="width: 320px;" class="flex justify-end">
|
||||
<el-button style="font-weight: bold;" v-if="!loginMark" type="primary" @click="toLogin"> 登录 </el-button>
|
||||
</div>
|
||||
<el-dropdown style="width: 320px;" class="text-center felx justify-end items-center" v-if="loginMark">
|
||||
<el-button style="font-weight: bold;" type="success" size="small">
|
||||
账户名: {{ userMsg.account_name }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item style="background-color: rgba(56, 188, 248, 0.1)" @click="editUser">
|
||||
<el-link style="font-weight: bold;" :underline="false" type="primary">
|
||||
账户管理
|
||||
</el-link>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item style="background-color: rgba(56, 188, 248, 0.1)" @click="changePassword">
|
||||
<el-link style="font-weight: bold;" :underline="false" type="primary">
|
||||
密码管理
|
||||
</el-link>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item style="background-color: rgba(240, 70, 70, 0.1)" @click="unLogin">
|
||||
<el-link style="font-weight: bold;" :underline="false" type="danger">
|
||||
退出登录
|
||||
</el-link>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<UserManager @resetData="resetData" ref="userManagerRef" :msg="userMsg" />
|
||||
<PasswordManager ref="passwordManagerRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { ArrowDown } from '@element-plus/icons-vue';
|
||||
|
||||
import $http from "../api/index";
|
||||
import $url from "../api/url";
|
||||
|
||||
import { encrypt } from "../utils/aes";
|
||||
|
||||
import bdqhLogo from "../assets/bdqhLogo.png";
|
||||
import bdjyLogo from "../assets/bdjyLogo.png";
|
||||
import UserManager from "./userManager.vue";
|
||||
import PasswordManager from "./changePassword.vue";
|
||||
|
||||
const loginMark = ref(false);
|
||||
const userManagerRef = ref(null);
|
||||
const userMsg = ref({});
|
||||
const passwordManagerRef = ref(null);
|
||||
|
||||
const toLogin = () => {
|
||||
localStorage.clear();
|
||||
const data = {
|
||||
origin_url: window.location.href
|
||||
};
|
||||
$http.post($url.toLogin, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
window.location.href = res.data.redirect;
|
||||
} else {
|
||||
router.push({ path: "/404page" });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const editUser = () => {
|
||||
if (userManagerRef.value) {
|
||||
userManagerRef.value.dialogVisible = true;
|
||||
userManagerRef.value.reset();
|
||||
}
|
||||
};
|
||||
|
||||
const changePassword = () => {
|
||||
if (passwordManagerRef.value) {
|
||||
passwordManagerRef.value.dialogVisible = true;
|
||||
}
|
||||
};
|
||||
|
||||
const unLogin = () => {
|
||||
const data = {
|
||||
uid: localStorage.data,
|
||||
access_token: localStorage.access_token,
|
||||
refresh_token: localStorage.refresh_token
|
||||
};
|
||||
$http.post($url.unLogin, data).then((res) => {
|
||||
localStorage.clear();
|
||||
window.location.reload();
|
||||
});
|
||||
};
|
||||
|
||||
const resetData = () => {
|
||||
const data = {
|
||||
uid: localStorage.data
|
||||
};
|
||||
$http.post($url.getUser, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
userMsg.value = res.data.userData;
|
||||
} else {
|
||||
ElMessage.error("获取用户信息失败!");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
let getCode = window.location.href.indexOf('?');
|
||||
if (getCode != "-1") {
|
||||
let code = window.location.href.substring(getCode + 1);
|
||||
const data = {
|
||||
code: code,
|
||||
type: encrypt("code")
|
||||
};
|
||||
$http.post($url.getToken, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.setItem("data", res.data.data);
|
||||
localStorage.setItem("access_token", res.data.access_token);
|
||||
localStorage.setItem("refresh_token", res.data.refresh_token);
|
||||
window.location.href = res.data.redirect;
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
localStorage.data &&
|
||||
localStorage.data !== "" &&
|
||||
localStorage.data !== null &&
|
||||
localStorage.data !== undefined &&
|
||||
localStorage.data !== NaN &&
|
||||
localStorage.access_token &&
|
||||
localStorage.access_token !== "" &&
|
||||
localStorage.access_token !== null &&
|
||||
localStorage.access_token !== undefined &&
|
||||
localStorage.access_token !== NaN
|
||||
) {
|
||||
const data = {
|
||||
access_token: localStorage.access_token,
|
||||
data: localStorage.data
|
||||
};
|
||||
$http.post($url.verify, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.setItem("data", res.data.data);
|
||||
loginMark.value = true;
|
||||
resetData();
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
localStorage.data &&
|
||||
localStorage.data !== "" &&
|
||||
localStorage.data !== null &&
|
||||
localStorage.data !== undefined &&
|
||||
localStorage.data !== NaN &&
|
||||
localStorage.refresh_token &&
|
||||
localStorage.refresh_token !== "" &&
|
||||
localStorage.refresh_token !== null &&
|
||||
localStorage.refresh_token !== undefined &&
|
||||
localStorage.refresh_token !== NaN
|
||||
) {
|
||||
const data = {
|
||||
code: localStorage.refresh_token,
|
||||
type: localStorage.data
|
||||
};
|
||||
$http.post($url.getToken, data).then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
localStorage.setItem("data", res.data.data);
|
||||
localStorage.setItem("access_token", res.data.access_token);
|
||||
localStorage.setItem("refresh_token", res.data.refresh_token);
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
39
src/components/main.vue
Normal file
39
src/components/main.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="maina w-h-full flex justify-center items-center">
|
||||
<div>
|
||||
<a class="block" href="http://bdrdserver.hwasmart.com">北斗短报文通信服务平台</a>
|
||||
</div>
|
||||
<div>
|
||||
<a class="block" href="http://tq.hwasmart.com">卫星通信服务平台(天启)</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.maina {
|
||||
display:block;
|
||||
background-color: #222222;
|
||||
background-image: url('../assets/bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.block {
|
||||
color: #ffffff;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
padding: 20px;
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
transition: background-color 0.3s ease;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.4);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
284
src/components/userManager.vue
Normal file
284
src/components/userManager.vue
Normal file
@@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" title="账户管理" width="600" center align-center>
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
style="max-width: 600px"
|
||||
:model="ruleForm"
|
||||
:rules="rules"
|
||||
label-width="auto"
|
||||
size="default"
|
||||
status-icon
|
||||
>
|
||||
<el-form-item label="用户名" prop="account_name">
|
||||
<el-input
|
||||
:disabled="acabled"
|
||||
minlength="1"
|
||||
maxlength="20"
|
||||
clearable
|
||||
placeholder="请输入用户名"
|
||||
v-model="ruleForm.account_name"
|
||||
@input="filter(ruleForm.account_name, 'account_name')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="user_name">
|
||||
<el-input
|
||||
maxlength="20"
|
||||
clearable
|
||||
placeholder="请输入姓名"
|
||||
v-model="ruleForm.user_name"
|
||||
@input="filter(ruleForm.user_name, 'user_name')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="电话号码" prop="phone">
|
||||
<el-input
|
||||
minlength="11"
|
||||
maxlength="11"
|
||||
clearable
|
||||
placeholder="请输入电话号码"
|
||||
v-model="ruleForm.phone"
|
||||
@input="filter(ruleForm.phone, 'phone')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sideMark == 'C'" label="性别" prop="gender">
|
||||
<el-radio-group v-model="ruleForm.gender">
|
||||
<el-radio value="1">男</el-radio>
|
||||
<el-radio value="0">女</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sideMark == 'C'" label="年龄" prop="age">
|
||||
<el-input
|
||||
maxlength="2"
|
||||
clearable
|
||||
placeholder="请输入年龄"
|
||||
v-model="ruleForm.age"
|
||||
@input="filter(ruleForm.age, 'age')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sideMark == 'C'" label="邮箱号" prop="email">
|
||||
<el-input
|
||||
maxlength="254"
|
||||
clearable
|
||||
placeholder="请输入邮箱号"
|
||||
v-model="ruleForm.email"
|
||||
@input="filter(ruleForm.email, 'email')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sideMark == 'C'" label="通信地址" prop="address">
|
||||
<el-input
|
||||
maxlength="300"
|
||||
clearable
|
||||
placeholder="请输入通信地址"
|
||||
v-model="ruleForm.address"
|
||||
@input="filter(ruleForm.address, 'address')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="sideMark == 'C'" label="邮政编码" prop="post_code">
|
||||
<el-input
|
||||
maxlength="6"
|
||||
clearable
|
||||
placeholder="请输入邮政编码"
|
||||
v-model="ruleForm.post_code"
|
||||
@input="filter(ruleForm.post_code, 'post_code')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="resetForm(ruleFormRef)">取消</el-button>
|
||||
<el-button type="primary" @click="editUser(ruleFormRef)"> 提交修改 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
import userManagerActiveStore from "../stores/userManager";
|
||||
|
||||
import { encrypt, decrypt } from "../utils/aes";
|
||||
|
||||
import $http from "../api/index";
|
||||
import $url from "../api/url";
|
||||
|
||||
const phoneRegex = /^(?:13\d|14[579]|15\d|16[67]|17[0135678]|18\d|19[89])\d{8}$/;
|
||||
const emailRegex = /^([a-zA-Z0-9]+[|-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[|-|.]?)*[a-zA-Z0-9]+(.[a-zA-Z]{2,3})+$/;
|
||||
const postCodeRegex = /^(0[1234567]|1[012356]|2[01234567]|3[0123456]|4[01234567]|5[1234567]|6[1234567]|7[012345]|8[013456])\d{4}$/;
|
||||
|
||||
const userManagerActive = userManagerActiveStore();
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
|
||||
const props = defineProps({
|
||||
msg: Object,
|
||||
});
|
||||
|
||||
let sideMark;
|
||||
const acabled = ref(true);
|
||||
const ruleFormRef = ref();
|
||||
const ruleForm = reactive({
|
||||
account_name: "",
|
||||
user_name: "",
|
||||
phone: "",
|
||||
});
|
||||
|
||||
const filter = (value, label) => {
|
||||
let filterValue;
|
||||
if (/[=\s"'+-]/.test(value)) {
|
||||
if (ruleForm[label]) {
|
||||
filterValue = value.replace(/[=\s"'+-]/g, "");
|
||||
}
|
||||
} else {
|
||||
filterValue = value;
|
||||
}
|
||||
if (label == "phone" || label == "age" || label == "post_code") {
|
||||
ruleForm[label] = filterValue.replace(/\D/g, "");
|
||||
} else {
|
||||
ruleForm[label] = filterValue;
|
||||
}
|
||||
};
|
||||
|
||||
const validatePhone = (rule, value, callback) => {
|
||||
if (value && !phoneRegex.test(value)) {
|
||||
callback(new Error("请输入正确的电话号码"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const validateEmail = (rule, value, callback) => {
|
||||
if (value && !emailRegex.test(value)) {
|
||||
callback(new Error("请输入正确的邮箱地址"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const validateCode = (rule, value, callback) => {
|
||||
if (value && !postCodeRegex.test(value)) {
|
||||
callback(new Error("请输入正确的邮政编码"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const rules = reactive({
|
||||
account_name: [{ required: false, message: "请输入用户名", trigger: "blur" }],
|
||||
user_name: [],
|
||||
phone: [
|
||||
{ required: false, message: "请输入手机号", trigger: "blur" },
|
||||
{ min: 11, max: 11, message: "输入长度应当为 11 位", trigger: "change" },
|
||||
{ validator: validatePhone },
|
||||
],
|
||||
});
|
||||
|
||||
const resetForm = (formEl) => {
|
||||
dialogVisible.value = false;
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
};
|
||||
|
||||
const emit = defineEmits(["resetData"]);
|
||||
|
||||
const reset = () => {
|
||||
ruleForm.account_name = props.msg.account_name;
|
||||
ruleForm.user_name = props.msg.user_name;
|
||||
ruleForm.phone = props.msg.phone;
|
||||
if (sideMark == "C") {
|
||||
ruleForm.gender = props.msg.gender ? "1" : "0";
|
||||
ruleForm.age = props.msg.age;
|
||||
ruleForm.email = props.msg.email;
|
||||
ruleForm.address = props.msg.address;
|
||||
ruleForm.post_code = props.msg.post_code;
|
||||
}
|
||||
};
|
||||
|
||||
const editUser = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
dialogVisible.value = false;
|
||||
const data = {
|
||||
userMsg: ruleForm,
|
||||
uid: localStorage.data
|
||||
};
|
||||
$http
|
||||
.post($url.editUser, data)
|
||||
.then((res) => {
|
||||
if (res.data.code === 200) {
|
||||
emit("resetData");
|
||||
} else {
|
||||
ElMessage.error("编辑用户信息失败!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ElMessage.error("提交失败!");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({ dialogVisible, reset });
|
||||
|
||||
watch(ruleForm, (value) => {
|
||||
if (dialogVisible.value) {
|
||||
userManagerActive.dialogVisible = dialogVisible.value;
|
||||
userManagerActive.ruleForm.account_name = encrypt(value.account_name);
|
||||
userManagerActive.ruleForm.user_name = encrypt(value.user_name);
|
||||
userManagerActive.ruleForm.phone = encrypt(value.phone);
|
||||
if (sideMark == "C") {
|
||||
userManagerActive.ruleForm.gender = encrypt(value.gender);
|
||||
userManagerActive.ruleForm.age = encrypt(value.age.toString());
|
||||
userManagerActive.ruleForm.email = encrypt(value.email);
|
||||
userManagerActive.ruleForm.address = encrypt(value.address);
|
||||
userManagerActive.ruleForm.post_code = encrypt(value.post_code);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watch(dialogVisible, (value) => {
|
||||
if (!value) {
|
||||
userManagerActive.dialogVisible = value;
|
||||
userManagerActive.ruleForm = {};
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
dialogVisible.value = userManagerActive.dialogVisible;
|
||||
if (localStorage.data) {
|
||||
let decryptData = decrypt(localStorage.data);
|
||||
sideMark = decryptData[decryptData.length - 1];
|
||||
}
|
||||
if (sideMark == "C") {
|
||||
acabled.value = false;
|
||||
ruleForm.gender = "";
|
||||
ruleForm.age = "";
|
||||
ruleForm.email = "";
|
||||
ruleForm.address = "";
|
||||
ruleForm.post_code = "";
|
||||
rules.account_name[0].required = true;
|
||||
rules.phone[0].required = true;
|
||||
rules.age = [];
|
||||
rules.email = [{ validator: validateEmail }];
|
||||
rules.address = [];
|
||||
rules.post_code = [
|
||||
{ min: 6, max: 6, message: "输入长度应当为 6 位", trigger: "change" },
|
||||
{ validator: validateCode },
|
||||
];
|
||||
}
|
||||
if (userManagerActive.dialogVisible) {
|
||||
ruleForm.account_name = decrypt(userManagerActive.ruleForm.account_name);
|
||||
ruleForm.user_name = decrypt(userManagerActive.ruleForm.user_name);
|
||||
ruleForm.phone = decrypt(userManagerActive.ruleForm.phone);
|
||||
if (sideMark == "C") {
|
||||
ruleForm.gender = decrypt(userManagerActive.ruleForm.gender);
|
||||
ruleForm.age = decrypt(userManagerActive.ruleForm.age);
|
||||
ruleForm.email = decrypt(userManagerActive.ruleForm.email);
|
||||
ruleForm.address = decrypt(userManagerActive.ruleForm.address);
|
||||
ruleForm.post_code = decrypt(userManagerActive.ruleForm.post_code);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
17
src/main.js
Normal file
17
src/main.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(ElementPlus)
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
31
src/router/index.js
Normal file
31
src/router/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/bdhome',
|
||||
name: 'bdhome',
|
||||
component: () => import('../views/bdHome.vue')
|
||||
},
|
||||
{
|
||||
path: '/404page',
|
||||
name: '404',
|
||||
component: () => import('../views/404page.vue')
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.matched.length === 0) {
|
||||
if (to.path == "/") {
|
||||
router.push({ path: '/bdHome' });
|
||||
} else {
|
||||
router.push({ path: '/404page' });
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
12
src/stores/counter.js
Normal file
12
src/stores/counter.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useCounterStore = defineStore('counter', () => {
|
||||
const count = ref(0)
|
||||
const doubleCount = computed(() => count.value * 2)
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
|
||||
return { count, doubleCount, increment }
|
||||
})
|
||||
35
src/stores/userManager.js
Normal file
35
src/stores/userManager.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { parse, stringify } from 'zipson';
|
||||
|
||||
const userManagerActiveStore = defineStore('userManager', {
|
||||
state: () => ({
|
||||
// 持久化数据
|
||||
dialogVisible: false,
|
||||
ruleForm: {
|
||||
account_name: "",
|
||||
user_name: "",
|
||||
phone: "",
|
||||
gender: "",
|
||||
age: "",
|
||||
email: "",
|
||||
address: "",
|
||||
post_code: "",
|
||||
},
|
||||
}),
|
||||
persist: {
|
||||
enabled: true, // Store 中数据持久化生效
|
||||
strategies: [
|
||||
{
|
||||
key: 'userManagerActive', // 存储的 key
|
||||
storage: localStorage, // 存储位置
|
||||
paths: ["dialogVisible", "ruleForm"], // 需要持久化的字段
|
||||
serializer: {
|
||||
deserialize: parse,
|
||||
serialize: stringify,
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
|
||||
export default userManagerActiveStore
|
||||
21
src/utils/aes.js
Normal file
21
src/utils/aes.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
const KEY = CryptoJS.enc.Utf8.parse('BDQH');
|
||||
|
||||
export const encrypt = (plaintext) => {
|
||||
if(plaintext !== null && plaintext !== undefined && plaintext !== "") {
|
||||
return CryptoJS.AES.encrypt(plaintext, KEY, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}).toString();
|
||||
}
|
||||
}
|
||||
|
||||
export const decrypt = (plaintext) => {
|
||||
if(plaintext !== null && plaintext !== undefined && !plaintext == "") {
|
||||
return CryptoJS.AES.decrypt(plaintext, KEY, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}).toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
}
|
||||
21
src/views/404page.vue
Normal file
21
src/views/404page.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div class="common-layout w-h-full">
|
||||
<el-text class="mx-1"> 404 not found </el-text>
|
||||
<br />
|
||||
<el-text class="mx-1"> 您搜索的页面不存在 </el-text>
|
||||
<br />
|
||||
<el-button type="primary" @click="backHome">返回首页</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const backHome = () => {
|
||||
router.push("/bdHome");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
23
src/views/bdHome.vue
Normal file
23
src/views/bdHome.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="common-layout w-h-full">
|
||||
<el-container class="w-h-full">
|
||||
<el-header style="padding: 0;" height="136px">
|
||||
<Header />
|
||||
</el-header>
|
||||
<el-main style="padding: 0;">
|
||||
<Main />
|
||||
</el-main>
|
||||
<el-footer style="padding: 0;" height="66px">
|
||||
<Footer />
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Header from "../components/header.vue";
|
||||
import Main from "../components/main.vue";
|
||||
import Footer from "../components/footer.vue";
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
18
tailwind.config.js
Normal file
18
tailwind.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
content: [],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'graywhite': '#f5f5f5',
|
||||
'grayblue': '#0da3e2',
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
38
vite.config.js
Normal file
38
vite.config.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
publicPath: './',
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
server: {
|
||||
//用来配置跨域
|
||||
host: '127.0.0.1',
|
||||
port: 7008,
|
||||
proxy: {
|
||||
'/authentication': {
|
||||
target: 'http://127.0.0.1:8011',//目标服务器地址
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/authentication/, '')
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user