commit 769103ab121cbd820da59a62d96626ad31625071 Author: qubiaobiao <3294694717@qq.com> Date: Tue May 12 17:43:37 2026 +0800 ntrip通信服务平台 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..1511959 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Vue 3 + Vite + +This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` + + + \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..5a1f2d2 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c2094b7 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "ntrip-server", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --port=7025", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.1", + "axios": "^1.6.8", + "core-js": "^3.37.0", + "crypto-js": "^4.2.0", + "element-plus": "^2.7.8", + "fingerprintjs2": "^2.1.4", + "gbk.js": "^0.3.0", + "moment": "^2.30.1", + "pinia": "^2.1.7", + "pinia-plugin-persist": "^1.0.0", + "terser": "^5.31.5", + "vue": "^3.4.21", + "vue-i18n": "^9.13.1", + "vue-router": "^4.3.0", + "zipson": "^0.2.12" + }, + "devDependencies": { + "@vitejs/plugin-legacy": "^5.4.1", + "@vitejs/plugin-vue": "^5.0.4", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.40", + "tailwindcss": "^3.4.7", + "unplugin-auto-import": "^0.17.5", + "unplugin-vue-components": "^0.27.0", + "vite": "^5.4.21" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..6ef5c58 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..1b51f8f Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..65662c0 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..21acfc3 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,118 @@ +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 === 302) { + // localStorage.clear(); + // //转到主页 + // router.push({ path: '/main' }); + // } + 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); + } +}; \ No newline at end of file diff --git a/src/api/ntrip.js b/src/api/ntrip.js new file mode 100644 index 0000000..ea1ba94 --- /dev/null +++ b/src/api/ntrip.js @@ -0,0 +1,191 @@ +import axios from 'axios'; + +export default class NTRIPCaster { + constructor(baseURL) { + this.baseURL = baseURL; + this.client = axios.create({ + baseURL, + // 长连接超时时间 + timeout: 30000, + // 重要:使用流式响应接收实时数据 + responseType: 'stream', + headers: { + 'Ntrip-Version': 'Ntrip/2.0', + // 'User-Agent': 'Virtual-NTRIP-Client/1.0' + }, + }); + this.currentStream = null; + this.sizeStrem = null; + } + + /** + * 连接NTRIP Caster获取差分数据流 + * @param {string} mountpoint - 挂载点 + * @param {Object} options - 额外选项 + */ + async connect(mountpoint, options = {}) { + try { + const response = await fetch(this.baseURL + `/${mountpoint}`, { + headers: { + 'uid': localStorage.data, + 'Authorization': localStorage.access_token, + 'Ntrip-Version': 'Ntrip/2.0', + 'Client-Type': 'Virtual-NTRIP-Client/1.0', + 'User-Agent': 'Virtual-NTRIP-Client/1.0', + 'Connection': 'keep-alive', + 'Accept': '*/*' + } + }); + + if (!response.ok) { + throw new Error(response.status); + } + const reader = response.body.getReader(); + this.currentStream = reader; + // 返回可读流 + return { + stream: reader, + headers: response.headers, + status: response.status + }; + } catch (error) { + throw this._handleError(error); + } + } + + disconnect() { + if (this.currentStream) { + this.currentStream.cancel(); + this.currentStream = null; + } + console.log('NTRIP连接已断开'); + } + + async _delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + /** + * 获取Caster的源列表(Source Table) + */ + async getSourceTable() { + try { + const response = await fetch(this.baseURL + `/`, { + headers: { + 'Ntrip-Version': 'Ntrip/2.0' + } + }); + const reader = response.body.getReader(); + this.sizeStrem = reader; + const { value } = await reader.read(); + const str = new TextDecoder().decode(value); + return this._parseSourceTable(str); + } catch (error) { + throw this._handleError(error); + } + } + + async getSize(mountpoint) { + try { + const response = await fetch(this.baseURL + `/${mountpoint}`, { + headers: { + 'Ntrip-Version': 'Ntrip/2.0', + 'Request-Type': 'SIZE', + 'uid': localStorage.data + } + }); + const reader = response.body.getReader(); + this.sizeStrem = reader; + return { + stream: reader + }; + } catch (error) { + throw this._handleError(error); + } + } + + sizeDisconnect() { + if (this.sizeStrem) { + this.sizeStrem.cancel(); + this.sizeStrem = null; + } + console.log('已挂载客户端数量监测连接已断开'); + } + + /** + * 解析源表 + */ + _parseSourceTable(sourceTable) { + const lines = sourceTable.split('\r\n'); + const sources = []; + for (const line of lines) { + if (line.startsWith('STR;')) { + const parts = line.split(';'); + if (parts.length >= 10) { + sources.push(`format: ${ parts[1] } | mountpoint: ${ parts[2] } | formatDetails: ${ parts[3] } | carrier: ${ parts[4] } | navSystem: ${ parts[5] } | network: ${ parts[6] } | country: ${ parts[7] }, | latitude: ${ parts[8] } | longitude: ${ parts[9] } | nmea: ${ parts[10] } | sourceID: ${ parts[11] }`); + // sources.push({ + // // 格式 + // format: parts[1], + // // 挂载点名称 + // mountpoint: parts[2], + // // 格式详情 + // formatDetails: parts[3], + // // 载体 + // carrier: parts[4], + // // 导航系统 + // navSystem: parts[5], + // // 网络 + // network: parts[6], + // // 国家 + // country: parts[7], + // // 纬度 + // latitude: parts[8], + // // 经度 + // longitude: parts[9], + // // NMEA + // nmea: parts[10], + // // 源ID + // sourceID: parts[11], + // // ... 其他字段 + // // 解决方案 + // // Soution: '', + // // 发生器 + // // Generator: '', + // // 压缩加密 + // // ComprEncryp: '', + // // 认证 + // // Auth: '', + // // 费用 + // // Fee: '', + // // 比特率 + // // Bitrate: '', + // }); + } + } + } + return sources; + } + + _handleError(error) { + if (error.response) { + // 服务器响应了非2xx状态码 + const status = error.response.status; + switch (status) { + case 401: + return new Error('认证失败'); + case 404: + return new Error('挂载点不存在'); + case 403: + return new Error('无访问权限'); + case 400: + return new Error('错误的请求'); + default: + return new Error(`NTRIP错误: ${status}`); + } + } else if (error.request) { + return new Error('网络连接失败'); + } else { + return error; + } + } +} \ No newline at end of file diff --git a/src/api/url.js b/src/api/url.js new file mode 100644 index 0000000..cb361c7 --- /dev/null +++ b/src/api/url.js @@ -0,0 +1,48 @@ +export default { + // 用于确认哪个网页在进行登录 + toLogin: "/authentication/toLogin", + // 退出登录 + unLogin: "/authentication/unLogin", + // 用于获取token + getToken: "/authentication/getToken", + // 用于验证token + verify: "/authentication/verify", + // 获取用户基本信息 + getUser: "/authentication/getUser", + // 修改用户基本信息 + editUser: "/authentication/editUser", + // B端单位管理员编辑用户基本信息 + editUserManager: "/authentication/editUserManager", + // 修改密码 + changePassword: "/authentication/changePassword", + // 重置密码 + resetPassword: "/authentication/resetPassword", + // 保存挂载点 + saveMountpoint: "/ntripService/saveMountpoint", + // 修改挂载点密码 + editPassword: "/ntripService/editPassword", + // 修改挂载点名称 + editMountpoint: "/ntripService/editMountpoint", + // 删除挂载点 + delMountpoint: "/ntripService/delMountpoint", + // 获取挂载点 + getMountpoint: "/ntripService/getMountpoint", + // 搜索挂载点 + searchMountpoint: "/ntripService/searchMountpoint", + // 全局寻获挂载点 + findMountpoint: "/ntripService/findMountpoint", + // 查看ntrip-clinet密码 + viewPassword: "/ntripService/viewPassword", + // 获取挂载点记录 + getRecord: "/ntripService/getRecord", + // 存储消息记录 + saveMsg: "/ntripService/saveMsg", + // 设置ntrip-clinet密码 + setPassword: "/ntripService/setPassword", + // 获取历史消息 + getHistoryMsg: "/ntripService/getHistoryMsg", + // 删除历史消息 + delHistoryMsg: "/ntripService/delHistoryMsg", + // 获取单位用户 + bsideManager: "/ntripService/bsideManager" +} \ No newline at end of file diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico new file mode 100644 index 0000000..1b51f8f Binary files /dev/null and b/src/assets/favicon.ico differ diff --git a/src/assets/img/Q&A/showType.png b/src/assets/img/Q&A/showType.png new file mode 100644 index 0000000..a969c35 Binary files /dev/null and b/src/assets/img/Q&A/showType.png differ diff --git a/src/assets/img/Q&A/tabelTools.png b/src/assets/img/Q&A/tabelTools.png new file mode 100644 index 0000000..b452677 Binary files /dev/null and b/src/assets/img/Q&A/tabelTools.png differ diff --git a/src/assets/img/Q&A/toolsClick.png b/src/assets/img/Q&A/toolsClick.png new file mode 100644 index 0000000..2f05570 Binary files /dev/null and b/src/assets/img/Q&A/toolsClick.png differ diff --git a/src/assets/img/Q&A/toolsSelect.png b/src/assets/img/Q&A/toolsSelect.png new file mode 100644 index 0000000..519e1c9 Binary files /dev/null and b/src/assets/img/Q&A/toolsSelect.png differ diff --git a/src/assets/img/code/changeMode.png b/src/assets/img/code/changeMode.png new file mode 100644 index 0000000..8cc2dbb Binary files /dev/null and b/src/assets/img/code/changeMode.png differ diff --git a/src/assets/img/code/codeGuide.png b/src/assets/img/code/codeGuide.png new file mode 100644 index 0000000..7c3fa24 Binary files /dev/null and b/src/assets/img/code/codeGuide.png differ diff --git a/src/assets/img/code/codeScience.png b/src/assets/img/code/codeScience.png new file mode 100644 index 0000000..20e99a5 Binary files /dev/null and b/src/assets/img/code/codeScience.png differ diff --git a/src/assets/img/code/codeType.png b/src/assets/img/code/codeType.png new file mode 100644 index 0000000..d1054f4 Binary files /dev/null and b/src/assets/img/code/codeType.png differ diff --git a/src/assets/img/code/fontGuide.png b/src/assets/img/code/fontGuide.png new file mode 100644 index 0000000..3573cc5 Binary files /dev/null and b/src/assets/img/code/fontGuide.png differ diff --git a/src/assets/img/code/showType.png b/src/assets/img/code/showType.png new file mode 100644 index 0000000..957b146 Binary files /dev/null and b/src/assets/img/code/showType.png differ diff --git a/src/assets/img/code/transCode.png b/src/assets/img/code/transCode.png new file mode 100644 index 0000000..acd3959 Binary files /dev/null and b/src/assets/img/code/transCode.png differ diff --git a/src/assets/img/code/transFont.png b/src/assets/img/code/transFont.png new file mode 100644 index 0000000..26facfb Binary files /dev/null and b/src/assets/img/code/transFont.png differ diff --git a/src/assets/img/header/headerGuide.png b/src/assets/img/header/headerGuide.png new file mode 100644 index 0000000..44eb98f Binary files /dev/null and b/src/assets/img/header/headerGuide.png differ diff --git a/src/assets/img/header/headerSelect.png b/src/assets/img/header/headerSelect.png new file mode 100644 index 0000000..6316daa Binary files /dev/null and b/src/assets/img/header/headerSelect.png differ diff --git a/src/assets/img/manager/operateSelect.png b/src/assets/img/manager/operateSelect.png new file mode 100644 index 0000000..fa44a1e Binary files /dev/null and b/src/assets/img/manager/operateSelect.png differ diff --git a/src/assets/img/manager/operateType.png b/src/assets/img/manager/operateType.png new file mode 100644 index 0000000..05c0331 Binary files /dev/null and b/src/assets/img/manager/operateType.png differ diff --git a/src/assets/img/msg/msg.png b/src/assets/img/msg/msg.png new file mode 100644 index 0000000..aae75c1 Binary files /dev/null and b/src/assets/img/msg/msg.png differ diff --git a/src/assets/img/msg/operateSelect.png b/src/assets/img/msg/operateSelect.png new file mode 100644 index 0000000..fa44a1e Binary files /dev/null and b/src/assets/img/msg/operateSelect.png differ diff --git a/src/assets/img/msg/operateType.png b/src/assets/img/msg/operateType.png new file mode 100644 index 0000000..0c9a95b Binary files /dev/null and b/src/assets/img/msg/operateType.png differ diff --git a/src/assets/img/msg/showMsg.png b/src/assets/img/msg/showMsg.png new file mode 100644 index 0000000..bbb4462 Binary files /dev/null and b/src/assets/img/msg/showMsg.png differ diff --git a/src/assets/img/xor/errorMsg.png b/src/assets/img/xor/errorMsg.png new file mode 100644 index 0000000..57aadac Binary files /dev/null and b/src/assets/img/xor/errorMsg.png differ diff --git a/src/assets/img/xor/input.png b/src/assets/img/xor/input.png new file mode 100644 index 0000000..a69e1d5 Binary files /dev/null and b/src/assets/img/xor/input.png differ diff --git a/src/assets/img/xor/xor.png b/src/assets/img/xor/xor.png new file mode 100644 index 0000000..0d2516c Binary files /dev/null and b/src/assets/img/xor/xor.png differ diff --git a/src/assets/img/xor/xorGuide.png b/src/assets/img/xor/xorGuide.png new file mode 100644 index 0000000..a44a044 Binary files /dev/null and b/src/assets/img/xor/xorGuide.png differ diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..ee9c6bd Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/main.css b/src/assets/main.css new file mode 100644 index 0000000..2c350cf --- /dev/null +++ b/src/assets/main.css @@ -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; + } +} \ No newline at end of file diff --git a/src/assets/qrcode.jpg b/src/assets/qrcode.jpg new file mode 100644 index 0000000..1ca11ac Binary files /dev/null and b/src/assets/qrcode.jpg differ diff --git a/src/components/calculationXOR/calculationXOR.vue b/src/components/calculationXOR/calculationXOR.vue new file mode 100644 index 0000000..8d3ac3c --- /dev/null +++ b/src/components/calculationXOR/calculationXOR.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/components/features/bsideManager.vue b/src/components/features/bsideManager.vue new file mode 100644 index 0000000..d794e23 --- /dev/null +++ b/src/components/features/bsideManager.vue @@ -0,0 +1,453 @@ + + + + + diff --git a/src/components/features/historyMsg.vue b/src/components/features/historyMsg.vue new file mode 100644 index 0000000..ff91372 --- /dev/null +++ b/src/components/features/historyMsg.vue @@ -0,0 +1,406 @@ + + + + + diff --git a/src/components/features/mountpointList.vue b/src/components/features/mountpointList.vue new file mode 100644 index 0000000..b8dd53e --- /dev/null +++ b/src/components/features/mountpointList.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/src/components/features/mountpointRecord.vue b/src/components/features/mountpointRecord.vue new file mode 100644 index 0000000..0e5e797 --- /dev/null +++ b/src/components/features/mountpointRecord.vue @@ -0,0 +1,324 @@ + + + + + diff --git a/src/components/guide/Q&A.vue b/src/components/guide/Q&A.vue new file mode 100644 index 0000000..79833d0 --- /dev/null +++ b/src/components/guide/Q&A.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/components/guide/code.vue b/src/components/guide/code.vue new file mode 100644 index 0000000..9227cc7 --- /dev/null +++ b/src/components/guide/code.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/components/guide/guide.vue b/src/components/guide/guide.vue new file mode 100644 index 0000000..59b7442 --- /dev/null +++ b/src/components/guide/guide.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/src/components/guide/header.vue b/src/components/guide/header.vue new file mode 100644 index 0000000..31ad6fe --- /dev/null +++ b/src/components/guide/header.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/guide/manager.vue b/src/components/guide/manager.vue new file mode 100644 index 0000000..61b6fa0 --- /dev/null +++ b/src/components/guide/manager.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/components/guide/msg.vue b/src/components/guide/msg.vue new file mode 100644 index 0000000..a2cda6e --- /dev/null +++ b/src/components/guide/msg.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/components/guide/xor.vue b/src/components/guide/xor.vue new file mode 100644 index 0000000..95f9d37 --- /dev/null +++ b/src/components/guide/xor.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/components/manager/changePassword.vue b/src/components/manager/changePassword.vue new file mode 100644 index 0000000..45448c1 --- /dev/null +++ b/src/components/manager/changePassword.vue @@ -0,0 +1,217 @@ + + + + + diff --git a/src/components/manager/setMountpoint.vue b/src/components/manager/setMountpoint.vue new file mode 100644 index 0000000..65e6fac --- /dev/null +++ b/src/components/manager/setMountpoint.vue @@ -0,0 +1,351 @@ + + + + + diff --git a/src/components/manager/userManager.vue b/src/components/manager/userManager.vue new file mode 100644 index 0000000..ad5e05d --- /dev/null +++ b/src/components/manager/userManager.vue @@ -0,0 +1,344 @@ + + + + + diff --git a/src/components/operate/dataShow.vue b/src/components/operate/dataShow.vue new file mode 100644 index 0000000..ae6c2b0 --- /dev/null +++ b/src/components/operate/dataShow.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/src/components/operate/editBsideUser.vue b/src/components/operate/editBsideUser.vue new file mode 100644 index 0000000..17b5815 --- /dev/null +++ b/src/components/operate/editBsideUser.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/src/components/operate/passwordOauth.vue b/src/components/operate/passwordOauth.vue new file mode 100644 index 0000000..8a0caa0 --- /dev/null +++ b/src/components/operate/passwordOauth.vue @@ -0,0 +1,146 @@ + + + + + diff --git a/src/components/operate/realTimeMsg.vue b/src/components/operate/realTimeMsg.vue new file mode 100644 index 0000000..d6c8caf --- /dev/null +++ b/src/components/operate/realTimeMsg.vue @@ -0,0 +1,409 @@ + + + + + diff --git a/src/components/operate/tabelSelect.vue b/src/components/operate/tabelSelect.vue new file mode 100644 index 0000000..3fe6b73 --- /dev/null +++ b/src/components/operate/tabelSelect.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/components/operate/tabelTools.vue b/src/components/operate/tabelTools.vue new file mode 100644 index 0000000..606e513 --- /dev/null +++ b/src/components/operate/tabelTools.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/src/components/pageStructure/footer.vue b/src/components/pageStructure/footer.vue new file mode 100644 index 0000000..571b278 --- /dev/null +++ b/src/components/pageStructure/footer.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/pageStructure/header.vue b/src/components/pageStructure/header.vue new file mode 100644 index 0000000..437440a --- /dev/null +++ b/src/components/pageStructure/header.vue @@ -0,0 +1,151 @@ + + + + + diff --git a/src/components/pageStructure/main.vue b/src/components/pageStructure/main.vue new file mode 100644 index 0000000..4a70a51 --- /dev/null +++ b/src/components/pageStructure/main.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/components/search/dateTimePicker.vue b/src/components/search/dateTimePicker.vue new file mode 100644 index 0000000..c269dcc --- /dev/null +++ b/src/components/search/dateTimePicker.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/components/search/pagination.vue b/src/components/search/pagination.vue new file mode 100644 index 0000000..e7b41f3 --- /dev/null +++ b/src/components/search/pagination.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/search/searchKey.vue b/src/components/search/searchKey.vue new file mode 100644 index 0000000..b7a4687 --- /dev/null +++ b/src/components/search/searchKey.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/search/selectSearch.vue b/src/components/search/selectSearch.vue new file mode 100644 index 0000000..3ffc2d4 --- /dev/null +++ b/src/components/search/selectSearch.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/components/search/sortSearch.vue b/src/components/search/sortSearch.vue new file mode 100644 index 0000000..de6dc8f --- /dev/null +++ b/src/components/search/sortSearch.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/components/transcoding/codeHelp.vue b/src/components/transcoding/codeHelp.vue new file mode 100644 index 0000000..e192936 --- /dev/null +++ b/src/components/transcoding/codeHelp.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/components/transcoding/decode.vue b/src/components/transcoding/decode.vue new file mode 100644 index 0000000..83f0c68 --- /dev/null +++ b/src/components/transcoding/decode.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/components/transcoding/encode.vue b/src/components/transcoding/encode.vue new file mode 100644 index 0000000..523aa66 --- /dev/null +++ b/src/components/transcoding/encode.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..ff9e433 --- /dev/null +++ b/src/main.js @@ -0,0 +1,23 @@ +import './assets/main.css' + +import { createApp } from 'vue'; +import { createPinia } from 'pinia'; +import piniaPersist from 'pinia-plugin-persist'; +import ElementPlus from 'element-plus'; +import zhCn from 'element-plus/es/locale/lang/zh-cn'; +import 'element-plus/dist/index.css'; + +import App from './App.vue'; +import router from './router'; + +const app = createApp(App); // 创建 vue 实例 + +const store = createPinia(); // 创建 pinia 实例 + +store.use(piniaPersist); + +app.use(store); +app.use(ElementPlus, { locale: zhCn }); +app.use(router); + +app.mount('#app'); diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..9bc7140 --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,31 @@ +import { createRouter, createWebHistory } from 'vue-router'; + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/main', + name: 'main', + component: () => import('../views/Main.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: '/main' }); + } else { + router.push({ path: '/404page' }); + } + } else { + next(); + } +}); + +export default router; diff --git a/src/stores/bsideManager.js b/src/stores/bsideManager.js new file mode 100644 index 0000000..7925ddb --- /dev/null +++ b/src/stores/bsideManager.js @@ -0,0 +1,37 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const bsideManagerActiveStore = defineStore('bsideManager', { + state: () => ({ + // 持久化数据 + offset: 1, + limit: 10, + dataCount: 0, + pageCount: 0, + searchOptions: { + account_name: "", + user_name: "", + phone: "", + }, + dialogVisible: false, + dialogSearchVisible: false, + dialogSortVisible: false, + dialogOperationVisible: false + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'bsideManagerActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["offset", "limit", "dataCount", "pageCount", "searchOptions", "dialogVisible", "dialogSearchVisible", "dialogSortVisible", "dialogOperationVisible"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ] + }, +}); + +export default bsideManagerActiveStore; \ No newline at end of file diff --git a/src/stores/decode.js b/src/stores/decode.js new file mode 100644 index 0000000..bf22c72 --- /dev/null +++ b/src/stores/decode.js @@ -0,0 +1,33 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const decodeActiveStore = defineStore('decode', { + state: () => ({ + // 持久化数据 + decodeType: "", + showType: "", + fontcode: "", + transcode: "", + transcodehex: "", + transcodebin: "", + fontcodedec: "", + fontcodehex: "", + fontcodebin: "", + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'decodeActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["decodeType", "showType", "fontcode", "transcode", "transcodehex", "transcodebin", "fontcodedec", "fontcodehex", "fontcodebin"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ], + }, +}); + +export default decodeActiveStore; \ No newline at end of file diff --git a/src/stores/encode.js b/src/stores/encode.js new file mode 100644 index 0000000..6f68c33 --- /dev/null +++ b/src/stores/encode.js @@ -0,0 +1,29 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const encodeActiveStore = defineStore('encode', { + state: () => ({ + // 持久化数据 + showType: "", + inputfont: "", + transfont: "", + transfonthex: "", + transfontbin: "", + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'encodeActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["showType", "inputfont", "transfont", "transfonthex", "transfontbin"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ] + }, +}); + +export default encodeActiveStore; \ No newline at end of file diff --git a/src/stores/historyMsg.js b/src/stores/historyMsg.js new file mode 100644 index 0000000..894cbba --- /dev/null +++ b/src/stores/historyMsg.js @@ -0,0 +1,41 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const historyMsgActiveStore = defineStore('historyMsg', { + state: () => ({ + // 持久化数据 + activeIndex: "1", + offset: 1, + limit: 10, + dataCount: 0, + pageCount: 0, + searchOptions: { + mountpoint: "", + original_msg: "", + created_at: "", + }, + sortOptions: { + mountpoint: false, + created_at: false, + }, + dialogSearchVisible: false, + dialogSortVisible: false, + dialogOperationVisible: false + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'historyMsgActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["activeIndex", "offset", "limit", "dataCount", "pageCount", "searchOptions", "sortOptions", "dialogSearchVisible", "dialogSortVisible", "dialogOperationVisible"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ] + }, +}); + +export default historyMsgActiveStore; \ No newline at end of file diff --git a/src/stores/mountpoint.js b/src/stores/mountpoint.js new file mode 100644 index 0000000..3def0ee --- /dev/null +++ b/src/stores/mountpoint.js @@ -0,0 +1,25 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const mountpointActiveStore = defineStore('mountpoint', { + state: () => ({ + // 持久化数据 + selectedMountpoint: "", + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'mountpointActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["selectedMountpoint"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ], + }, +}); + +export default mountpointActiveStore; \ No newline at end of file diff --git a/src/stores/mountpointRecord.js b/src/stores/mountpointRecord.js new file mode 100644 index 0000000..a731267 --- /dev/null +++ b/src/stores/mountpointRecord.js @@ -0,0 +1,42 @@ +import { defineStore } from 'pinia'; +import { parse, stringify } from 'zipson'; + +const recordActiveStore = defineStore('record', { + state: () => ({ + // 持久化数据 + offset: 1, + limit: 10, + dataCount: 0, + searchOptions: { + mountpoint: "", + befor_edit: "", + created_at: "", + updated_at: "" + }, + sortOptions: { + mountpoint: false, + befor_edit: false, + created_at: false, + updated_at: false + }, + dialogSearchVisible: false, + dialogSortVisible: false, + dialogOperationVisible: false + }), + persist: { + enabled: true, // Store 中数据持久化生效 + strategies: [ + { + key: 'recordActive', // 存储的 key + storage: localStorage, // 存储位置 + paths: ["offset", "limit", "dataCount", "searchOptions", "sortOptions", "dialogSearchVisible", "dialogSortVisible", "dialogOperationVisible"], // 需要持久化的字段 + serializer: { + deserialize: parse, + serialize: stringify, + }, + } + ] + }, +}); + +export default recordActiveStore; \ No newline at end of file diff --git a/src/stores/userManager.js b/src/stores/userManager.js new file mode 100644 index 0000000..4442b85 --- /dev/null +++ b/src/stores/userManager.js @@ -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; \ No newline at end of file diff --git a/src/utils/aes.js b/src/utils/aes.js new file mode 100644 index 0000000..9ca4cdc --- /dev/null +++ b/src/utils/aes.js @@ -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); + } +}; \ No newline at end of file diff --git a/src/utils/hasNullOrEmptyPropertyWithTypeof.js b/src/utils/hasNullOrEmptyPropertyWithTypeof.js new file mode 100644 index 0000000..6af4b89 --- /dev/null +++ b/src/utils/hasNullOrEmptyPropertyWithTypeof.js @@ -0,0 +1,9 @@ +export const hasNullOrEmptyPropertyWithTypeof = (obj) => { + let hasNullOrEmpty = false; + for (const prop in obj) { + if (!(obj.hasOwnProperty(prop) && ((obj[prop] === null) || obj[prop] === undefined || (typeof obj[prop] === 'string' && obj[prop] === '')))) { + hasNullOrEmpty = true; + } + } + return hasNullOrEmpty; +} \ No newline at end of file diff --git a/src/utils/judgment.js b/src/utils/judgment.js new file mode 100644 index 0000000..46ab749 --- /dev/null +++ b/src/utils/judgment.js @@ -0,0 +1,5 @@ +export const judgment = (keyWord, key, value, val) => { + if (value !== null) { + keyWord[key] = value[val]; + } +}; \ No newline at end of file diff --git a/src/utils/toFullWidth.js b/src/utils/toFullWidth.js new file mode 100644 index 0000000..38d1c93 --- /dev/null +++ b/src/utils/toFullWidth.js @@ -0,0 +1,7 @@ +//将半角空格,制表符,回车和半角字符转为全角空格,全角制表符,全角回车和全角字符 +export const toFullWidth = (str) => { + //全角制表符使用4个全角空格模拟 + return str.replace(/ /g, '\u3000').replace(/\t/g, '\u3000\u3000\u3000\u3000').replace(/\n/g, '\u21B5').replace(/[\x21-\x7E]/g, (font) => { + return String.fromCharCode(font.charCodeAt(0) + 0xFEE0); + }); +}; \ No newline at end of file diff --git a/src/views/404page.vue b/src/views/404page.vue new file mode 100644 index 0000000..10a1ca1 --- /dev/null +++ b/src/views/404page.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/views/Main.vue b/src/views/Main.vue new file mode 100644 index 0000000..c171990 --- /dev/null +++ b/src/views/Main.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..1f9ce20 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +export default { + purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], + darkMode: false, // or 'media' or 'class' + content: [], + theme: { + extend: {}, + }, + variants: { + extend: {}, + }, + plugins: [], +} \ No newline at end of file diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..c0bd783 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,53 @@ +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' +import legacy from '@vitejs/plugin-legacy' + +// https://vitejs.dev/config/ +export default defineConfig({ + base: './', + publicPath: './', + plugins: [ + vue(), + AutoImport({ + resolvers: [ElementPlusResolver()], + }), + Components({ + resolvers: [ElementPlusResolver()], + }), + legacy({ + target: ['ie>=11'], + additionalLegacyPolyfills: ['regenerator-runtime/runtime'], + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + server: { + //用来配置跨域 + host: '127.0.0.1', + port: 7035, + proxy: { + '/authentication': { + target: 'http://127.0.0.1:8011',//鉴权服务器地址 + changeOrigin: true, + rewrite: (path) => path.replace(/^\/authentication/, '') + }, + '/ntripService': { + target: 'http://127.0.0.1:8022',//资源服务器地址 + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ntripService/, '') + }, + '/ntripCaster': { + target: 'http://127.0.0.1:2101',//资源服务器地址 + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ntripCaster/, '') + } + } + } +}); \ No newline at end of file