北斗短报文应用服务系统入口页面

This commit is contained in:
2026-03-27 17:38:42 +08:00
commit e5757c61e7
29 changed files with 1201 additions and 0 deletions

30
.gitignore vendored Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

42
package.json Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "bd-short-message-platform-home",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --port=7018",
"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
View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

11
src/App.vue Normal file
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 KiB

BIN
src/assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

9
src/assets/main.css Normal file
View 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;
}
}

View 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
View 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
View 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>
&nbsp;&nbsp;
&nbsp;&nbsp;
<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>

16
src/components/main.vue Normal file
View File

@@ -0,0 +1,16 @@
<template>
<a class="maina w-h-full" href="http://bdrdserver.hwasmart.com"></a>
</template>
<script setup>
</script>
<style scoped>
.maina {
display:block;
background-color: #222222;
background-image: url('../assets/bg.jpg');
background-size: cover;
background-position: center;
}
</style>

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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/, '')
},
}
}
})