betaqi 5 days ago
parent
commit
5546f8ae3e
  1. 3
      .env.cloud
  2. 2
      .env.local
  3. 2
      package.json
  4. 3
      src/api/module/taks/index.ts
  5. 27
      src/composables/useZMQJsonWorker.ts
  6. 20
      src/router/index.ts
  7. 26
      src/views/firmwareUpload/index.vue
  8. 52
      src/views/taskList/index.vue
  9. 70
      src/views/taskList/infoDrawer.vue
  10. 12
      src/views/testG6/index.vue
  11. 122
      vite.config.ts

3
.env.cloud

@ -1,2 +1,3 @@
VITE_APP_ENV = cloud VITE_APP_ENV = cloud
VITE_BASE_URL = 'http://192.168.1.99:8080' VITE_BASE_URL = 'http://192.168.1.99:8080'
VITE_ZMQ_BASE_URL = '192.168.1.99'

2
.env.local

@ -1 +1,3 @@
VITE_APP_ENV = local VITE_APP_ENV = local
VITE_BASE_URL = 'http://192.168.1.99:8080'
VITE_ZMQ_BASE_URL = '192.168.1.99'

2
package.json

@ -9,7 +9,7 @@
"preview": "vite preview", "preview": "vite preview",
"build-only": "vite build", "build-only": "vite build",
"build:dev": "vite build --mode development", "build:dev": "vite build --mode development",
"build:prod": "vite build --mode prod", "build:cloud": "vite build --mode cloud",
"type-check": "vue-tsc --build" "type-check": "vue-tsc --build"
}, },
"dependencies": { "dependencies": {

3
src/api/module/taks/index.ts

@ -12,8 +12,7 @@ export const getTaskList = (params: Param) =>
}>({ }>({
url: 'api/task/summary', url: 'api/task/summary',
method: 'get', method: 'get',
data: params, params,
}) })

27
src/composables/useZMQJsonWorker.ts

@ -1,15 +1,26 @@
import { WorkerCMD, ZmqCMD, } from '@/utils/zmq' import { WorkerCMD, ZmqCMD, } from '@/utils/zmq'
import type { ManualAction, PublishMsg, PubMsgData, SubMsgData, TimeoutMsg, ZmqMessage } from '@/utils/zmq' import type {
ManualAction,
PublishMsg,
PubMsgData,
SubMsgData,
TimeoutMsg,
ZmqMessage
} from '@/utils/zmq'
import webWorker from '@/utils/zmqJsonWorker?worker' import webWorker from '@/utils/zmqJsonWorker?worker'
const env = import.meta.env const env = import.meta.env
const defaultHost = import.meta.env.PROD ? window.location.hostname : '192.168.1.199' let defaultHost = env.VITE_ZMQ_BASE_URL
if (env.VITE_APP_ENV === 'local') {
defaultHost = window.location.hostname === 'localhost' ? env.VITE_ZMQ_BASE_URL : window.location.hostname
}
class ZMQJsonWorker { class ZMQJsonWorker {
private static instance: ZMQJsonWorker | null = null; // ➤ 单例实例 private static instance: ZMQJsonWorker | null = null; // ➤ 单例实例
private worker: Worker; private worker: Worker;
private scribeHandlers: Map<string, (msg: SubMsgData | PubMsgData) => void> = new Map(); private scribeHandlers: Map<string, (msg: SubMsgData | PubMsgData) => void> = new Map();
private pubTimeoutHandlers: Map<string, (msg: TimeoutMsg) => void> = new Map(); private pubTimeoutHandlers: Map<string, (msg: TimeoutMsg) => void> = new Map();
private host: string; private readonly host: string;
private statusCallback: ((status: string) => void) | null = null; private statusCallback: ((status: string) => void) | null = null;
private isAlwaysListenMsgMap: Map<string, PublishMsg<any>> = new Map(); private isAlwaysListenMsgMap: Map<string, PublishMsg<any>> = new Map();
@ -64,7 +75,13 @@ class ZMQJsonWorker {
if (isAlwaysListen) { if (isAlwaysListen) {
this.isAlwaysListenMsgMap.set(`${msg.id}`, msg) this.isAlwaysListenMsgMap.set(`${msg.id}`, msg)
} }
this.worker.postMessage({ cmd: WorkerCMD.PUBLISH, topic, msg: JSON.stringify(msg), isTimeout, isAlwaysListen }); this.worker.postMessage({
cmd: WorkerCMD.PUBLISH,
topic,
msg: JSON.stringify(msg),
isTimeout,
isAlwaysListen
});
} }
setStatusCallback(callback: (status: string) => void) { setStatusCallback(callback: (status: string) => void) {
@ -104,7 +121,7 @@ class ZMQJsonWorker {
private handleMessage(e: MessageEvent<ZmqMessage>) { private handleMessage(e: MessageEvent<ZmqMessage>) {
const { cmd, msg, topic, community } = e.data; const { cmd, msg, topic, community } = e.data;
console.log(e.data)
if (cmd === ZmqCMD.STATUS) { if (cmd === ZmqCMD.STATUS) {
const status = community ? 'disconnected' : 'connected'; const status = community ? 'disconnected' : 'connected';
if (this.statusCallback) { if (this.statusCallback) {

20
src/router/index.ts

@ -53,16 +53,16 @@ export const defaultRouter = [
icon: 'i-mingcute:task-line', icon: 'i-mingcute:task-line',
} }
}, },
{ // {
path: '/testG6', // path: '/testG6',
name: 'testG6', // name: 'testG6',
component: () => import('@/views/testG6/index.vue'), // component: () => import('@/views/testG6/index.vue'),
meta: { // meta: {
title: '测试G6', // title: '测试G6',
isShow: true, // isShow: true,
icon: 'i-mingcute:task-line', // icon: 'i-mingcute:task-line',
} // }
} // }
], ],
}, },
] ]

26
src/views/firmwareUpload/index.vue

@ -1,17 +1,23 @@
<template> <template>
<div class="flex justify-center items-center size-full"> <div class="flex justify-center items-center size-full">
<EdfsWrap :title="title" style="width: 50%; height: 50%"> <EdfsWrap :title="title" style="width: 50%; height: 50%">
<el-upload v-model:fileList="fileList" v-loading="loading" element-loading-text="上传中..." drag action="" <el-upload v-model:fileList="fileList" v-loading="loading" element-loading-text="上传中..."
accept=".zip,.tar,.tar.gz" :limit="1" :on-exceed="handleExceed" :auto-upload="false" ref="uploadRef" drag action=""
:before-upload="beforeAvatarUpload" class="h-[calc(100%-30px)] w-full"> accept=".zip,.tar,.tar,.gz" :limit="1" :on-exceed="handleExceed"
:auto-upload="false"
ref="uploadRef"
:before-upload="beforeAvatarUpload" class="h-[calc(100%-30px)] w-full">
<div class="i-line-md:cloud-alt-upload-loop text-20px mx-auto"></div> <div class="i-line-md:cloud-alt-upload-loop text-20px mx-auto"></div>
<div class="text">拖拽文件或者 <em>点击上传</em></div> <div class="text">拖拽文件或者 <em>点击上传</em></div>
<template #tip v-if="!fileList.length"> <template #tip v-if="!fileList.length">
<div class="el-upload__tip">上传限制一个文件新文件会覆盖旧文件仅支持 .zip.tar .tar.gz 格式</div> <div class="el-upload__tip">上传限制一个文件新文件会覆盖旧文件仅支持 .zip.tar
.tar.gz 格式
</div>
</template> </template>
</el-upload> </el-upload>
<div class="flex justify-center"> <div class="flex justify-center">
<el-button type="primary" @click="onSave" v-show="fileList.length && !loading">确定上传</el-button> <el-button type="primary" @click="onSave" v-show="fileList.length && !loading">确定上传
</el-button>
<el-button type="info" v-show="loading" @click="onClone">取消上传</el-button> <el-button type="info" v-show="loading" @click="onClone">取消上传</el-button>
</div> </div>
</EdfsWrap> </EdfsWrap>
@ -46,22 +52,23 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
const fileName = rawFile.name.toLowerCase() const fileName = rawFile.name.toLowerCase()
const supportedFormats = ['.zip', '.tar', '.tar.gz'] const supportedFormats = ['.zip', '.tar', '.tar.gz']
const isValidFormat = supportedFormats.some(format => fileName.endsWith(format)) const isValidFormat = supportedFormats.some(format => fileName.endsWith(format))
if (!isValidFormat) { if (!isValidFormat) {
message.error('请上传 .zip、.tar 或 .tar.gz 格式的文件') message.error('请上传 .zip、.tar 或 .tar.gz 格式的文件')
uploadRef.value?.clearFiles?.() uploadRef.value?.clearFiles?.()
return false return false
} }
// const maxSize = 100 * 1024 * 1024 // const maxSize = 100 * 1024 * 1024
// if (rawFile.size > maxSize) { // if (rawFile.size > maxSize) {
// message.error('100MB') // message.error('100MB')
// uploadRef.value?.clearFiles?.() // uploadRef.value?.clearFiles?.()
// return false // return false
// } // }
return true return true
} }
function validate() { function validate() {
if (!fileList.value.length) { if (!fileList.value.length) {
message.error('请上传文件') message.error('请上传文件')
@ -70,6 +77,7 @@ function validate() {
return beforeAvatarUpload(fileList.value[0].raw!) return beforeAvatarUpload(fileList.value[0].raw!)
} }
const loading = ref(false) const loading = ref(false)
const abortController = ref<AbortController>() const abortController = ref<AbortController>()
@ -163,6 +171,7 @@ async function createChunksFromFileData(file: File, chunkSize: number) {
function clearData() { function clearData() {
fileList.value = [] fileList.value = []
} }
function onClone() { function onClone() {
if (loading.value) { if (loading.value) {
abortController.value?.abort() abortController.value?.abort()
@ -170,6 +179,7 @@ function onClone() {
} }
clearData() clearData()
} }
const firmwarePath = ref<string>() const firmwarePath = ref<string>()
const title = computed(() => { const title = computed(() => {

52
src/views/taskList/index.vue

@ -1,46 +1,60 @@
<template> <template>
<div class="task-list wh-full"> <div class="task-list wh-full">
<EdfsWrap title="任务列表" class="h-full"> <EdfsWrap title="任务列表" class="h-full">
<EdfsTable class="wh-full" v-loading="loading" :data="list" ref="tableRef" :highlight-current-row="true" <EdfsTable class="wh-full" v-loading="loading" :data="list" ref="tableRef"
:page-total="total" :current-page="queryParams.page" :page-size="queryParams.size" row-class-name="row" :highlight-current-row="true"
@pageCurrentChange="handleJump"> :page-total="total" :current-page="queryParams.page" :page-size="queryParams.size"
row-class-name="row"
@pageCurrentChange="handleJump">
<template v-for="(col, idx) in tableCol" :key="idx"> <template v-for="(col, idx) in tableCol" :key="idx">
<el-table-column v-if="col.prop.endsWith('Time')" :label="col.label" :min-width="col.minWidth"> <el-table-column v-if="col.prop.endsWith('Time')" :label="col.label"
:min-width="col.minWidth">
<template #default="scope"> <template #default="scope">
{{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }} {{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-else-if="col.prop === 'status'" :prop="col.prop" :label="col.label" <el-table-column v-else-if="col.prop === 'status'" :prop="col.prop" :label="col.label"
:min-width="col.minWidth"> :min-width="col.minWidth">
<template #default="scope"> <template #default="scope">
{{taskStatus.find(r => r.value === scope.row.status)?.label || '--'}} {{ taskStatus.find(r => r.value === scope.row.status)?.label || '--' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-else-if="col.prop === 'mode'" :prop="col.prop" :label="col.label" <el-table-column v-else-if="col.prop === 'mode'" :prop="col.prop" :label="col.label"
:min-width="col.minWidth"> :min-width="col.minWidth">
<template #default="scope"> <template #default="scope">
{{taskMode.find(r => r.value === scope.row.mode)?.label || '--'}} {{ taskMode.find(r => r.value === scope.row.mode)?.label || '--' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-else :prop="col.prop" :label="col.label" :min-width="col.minWidth" /> <el-table-column v-else :prop="col.prop" :label="col.label" :min-width="col.minWidth"/>
</template> </template>
<el-table-column label="操作" width="210" align="center"> <el-table-column label="操作" width="210" align="center">
<template #default="scope"> <template #default="scope">
<EdfsButton size="small" link type="primary" inner-text="详情" @click="onDetail(scope.row)" /> <EdfsButton size="small" link type="primary" inner-text="详情"
<EdfsButton size="small" link type="danger" v-if="[0, 1].includes(scope.row.mode)" inner-text="取消任务" @click="onDetail(scope.row)"/>
@click="onCancel(scope.row.id)" /> <EdfsButton size="small" link type="danger" v-if="[0, 1].includes(scope.row.mode)"
inner-text="取消任务"
@click="onCancel(scope.row.id)"/>
</template> </template>
</el-table-column> </el-table-column>
</EdfsTable> </EdfsTable>
</EdfsWrap> </EdfsWrap>
</div> </div>
<InfoDrawer ref="InfoDrawerRef" /> <InfoDrawer ref="InfoDrawerRef" @task-finish="onTaskFinish"/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { cancelTask, getTaskInfo, getTaskList, type TaskInfo, type TaskList } from '@/api/module/taks' import {
cancelTask,
getTaskInfo,
getTaskList,
type TaskInfo,
type TaskList
} from '@/api/module/taks'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
import EdfsWrap from "@/components/Edfs-wrap.vue";
import EdfsTable from "@/components/Edfs-table/index.vue";
import EdfsButton from "@/components/Edfs-button.vue";
import dayjs from 'dayjs' import dayjs from 'dayjs'
import InfoDrawer from './infoDrawer.vue' import InfoDrawer from './infoDrawer.vue'
@ -113,15 +127,25 @@ function handleJump(page: number) {
} }
const InfoDrawerRef = ref<typeof InfoDrawer>() const InfoDrawerRef = ref<typeof InfoDrawer>()
function onDetail(row: TaskList) { function onDetail(row: TaskList) {
InfoDrawerRef.value?.open(row) InfoDrawerRef.value?.open(row)
} }
const onCancel = async (id: string) => { const onCancel = async (id: string) => {
await message.delConfirm(`是否确认取消该任务?`) await message.delConfirm(`是否确认取消该任务?`)
const res = await cancelTask(id) const res = await cancelTask(id)
if (res.code !== 0) return if (res.code !== 0) return
await getList() await getList()
} }
function onTaskFinish(sn: string, status: -1 | 0 | 1 | 2 | 3) {
const curTask = list.value.findIndex(item => item.id === sn)
if (curTask !== -1) {
list.value[curTask].status = status
}
}
onMounted(() => { onMounted(() => {
getList() getList()
}) })

70
src/views/taskList/infoDrawer.vue

@ -1,15 +1,26 @@
<template> <template>
<div class="fault-rule-drawer"> <div class="fault-rule-drawer">
<el-drawer v-model="isShowDrawer" title="任务详情" direction="rtl" size="50%" modal-class="model-dev-opn" <el-drawer v-model="isShowDrawer" title="任务详情" direction="rtl" size="50%"
:before-close="handleBeforeClose"> modal-class="model-dev-opn"
:before-close="handleBeforeClose">
<main class="wh-full" v-loading="loading"> <main class="wh-full" v-loading="loading">
<template v-for="detail in detailList"> <template v-for="detail in detailList">
<el-descriptions border :title="`${detail.sn}任务详情`"> <el-descriptions border :title="`${detail.sn}任务详情`">
<el-descriptions-item :label-width="60" label="状态"> <el-tag size="small">{{statusList.find(r => r.value === <el-descriptions-item :label-width="60" label="状态">
detail.status)?.label || '--' <el-tag size="small">{{
}}</el-tag></el-descriptions-item> statusList.find(r => r.value ===
<el-descriptions-item :label-width="100" label="总数数据量">{{ detail.total }}</el-descriptions-item> detail.status)?.label || '--'
<el-descriptions-item :label-width="110" label="已完成数据量">{{ detail.finish }}</el-descriptions-item> }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item :label-width="100" label="总数任务量">{{
detail.total
}}
</el-descriptions-item>
<el-descriptions-item :label-width="110" label="已完任务量">{{
detail.finish
}}
</el-descriptions-item>
<el-descriptions-item :label-width="60" label="信息"> <el-descriptions-item :label-width="60" label="信息">
{{ detail?.info ? detail.info : '暂无信息' }} {{ detail?.info ? detail.info : '暂无信息' }}
</el-descriptions-item> </el-descriptions-item>
@ -17,8 +28,9 @@
<template v-if="detail.total === 0"> <template v-if="detail.total === 0">
<span>暂无进度</span> <span>暂无进度</span>
</template> </template>
<el-progress v-else style="width: 95%;" :percentage="Math.floor((detail.finish / detail.total) * 100)" <el-progress v-else style="width: 95%;"
:text-inside="true" :stroke-width="20" /> :percentage="Math.floor((detail.finish / detail.total) * 100)"
:text-inside="true" :stroke-width="20"/>
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</template> </template>
@ -28,11 +40,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getSubTopic, type PubMsgData } from '@/utils/zmq' import { getSubTopic, type SubMsgData } from '@/utils/zmq'
import ZMQWorker from '@/composables/useZMQJsonWorker' import ZMQWorker from '@/composables/useZMQJsonWorker'
import { getTaskInfo, type TaskInfo, type TaskList } from '@/api/module/taks' import { getTaskInfo, type TaskInfo, type TaskList } from '@/api/module/taks'
import { useMessage } from '@/composables/useMessage' import { useMessage } from '@/composables/useMessage'
const emit = defineEmits<{ 'task-finish': [string, -1 | 0 | 1 | 2 | 3] }>()
const message = useMessage() const message = useMessage()
const worker = ZMQWorker.getInstance() const worker = ZMQWorker.getInstance()
const isShowDrawer = defineModel<boolean>() const isShowDrawer = defineModel<boolean>()
@ -50,40 +63,57 @@ async function onDetail(row: TaskList) {
} }
loading.value = false loading.value = false
} }
const curentTaskId = ref('')
const currentTaskId = ref('')
async function open(row: TaskList) { async function open(row: TaskList) {
isShowDrawer.value = true isShowDrawer.value = true
curentTaskId.value = row.id currentTaskId.value = row.id
await onDetail(row) await onDetail(row)
worker.subscribe(getSubTopic('server', 'event', 'task'), zmqTaskCb) worker.subscribe(getSubTopic('server', 'event', 'task'), zmqTaskCb)
} }
const statusList = [ const statusList = [
{ label: '未开始', value: 0 }, {
{ label: '进行中', value: 1 }, value: -1,
{ label: '成功', value: 2 }, label: '执行失败'
{ label: '失败', value: -1 }, }, {
label: '等待执行',
value: 0
}, {
label: '执行中',
value: 1
}, {
label: '已取消',
value: 2
}, {
label: '执行成功',
value: 3
}
] ]
function zmqTaskCb(msg: PubMsgData) { function zmqTaskCb(msg: SubMsgData) {
const { feedback, result, id } = msg const { feedback } = msg
const taskId = feedback[0] const taskId = feedback[0]
const deviceSN = feedback[1] const deviceSN = feedback[1]
const deviceStatus = feedback[2] || '未知状态' const deviceStatus = feedback[2] || '未知状态'
const finish = feedback[3] || 0 const finish = feedback[3] || 0
const total = feedback[4] || 0 const total = feedback[4] || 0
if (curentTaskId.value !== taskId) return if (currentTaskId.value !== taskId) return
const detail = detailList.value.find(item => item.sn === deviceSN) const detail = detailList.value.find(item => item.sn === deviceSN)
if (!detail) return if (!detail) return
detail.status = deviceStatus detail.status = deviceStatus
detail.finish = finish detail.finish = finish
detail.total = total detail.total = total
if (detail.finish === detail.finish) {
emit('task-finish', deviceSN, deviceStatus)
}
} }
function handleBeforeClose(done: () => void) { function handleBeforeClose(done: () => void) {
isShowDrawer.value = false isShowDrawer.value = false
curentTaskId.value = '' currentTaskId.value = ''
done() done()
} }

12
src/views/testG6/index.vue

@ -41,6 +41,18 @@ onMounted(() => {
nodes: graphData.getNodes(), nodes: graphData.getNodes(),
edges: graphData.getEdges() edges: graphData.getEdges()
}, },
plugins: [
{
type: 'contextmenu',
enable: (e: any) => e.targetType === 'node',
getItems: () => {
return [{ name: '查看详情', value: 'detail' }];
},
onClick: (value: string, item: HTMLElement, current: any) => {
console.log('展示节点详情', current.config.context.model.getNodeData(current.config.id));
},
},
],
behaviors: ['drag-canvas', 'zoom-canvas'], behaviors: ['drag-canvas', 'zoom-canvas'],
}); });
graph.render(); graph.render();

122
vite.config.ts

@ -1,6 +1,6 @@
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
import UnoCSS from 'unocss/vite' import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite' import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools' import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite' import AutoImport from 'unplugin-auto-import/vite'
@ -9,68 +9,74 @@ import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vueJsx from '@vitejs/plugin-vue-jsx' import vueJsx from '@vitejs/plugin-vue-jsx'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
// Vite 配置文件 // Vite 配置文件
export default defineConfig({ export default defineConfig(({ mode }) => {
plugins: [ const env = loadEnv(mode, process.cwd())
vue(), console.log(env)
vueJsx(), console.log(env.PROD)
vueDevTools(), return {
UnoCSS(), plugins: [
Icons({ vue(),
autoInstall: true, vueJsx(),
}), vueDevTools(),
AutoImport({ UnoCSS(),
imports: ['vue', 'vue-router'], Icons({
resolvers: [ElementPlusResolver()], autoInstall: true,
dts: 'global.types/auto-imports.d.ts', }),
}), AutoImport({
Components({ imports: ['vue', 'vue-router'],
dirs: ['src/components'], resolvers: [ElementPlusResolver()],
extensions: ['vue'], dts: 'global.types/auto-imports.d.ts',
dts: 'global.types/components.d.ts', }),
resolvers: [ElementPlusResolver()], Components({
}), dirs: ['src/components'],
], extensions: ['vue'],
resolve: { dts: 'global.types/components.d.ts',
alias: { resolvers: [ElementPlusResolver()],
'@': fileURLToPath(new URL('./src', import.meta.url)), }),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
}, },
},
build: { build: {
minify: 'terser', outDir: env.VITE_APP_ENV === 'cloud' ? 'dist-cloud' : 'dist-local',
terserOptions: { minify: 'terser',
compress: { terserOptions: {
drop_console: true, compress: {
drop_debugger: true, drop_console: true,
drop_debugger: true,
},
}, },
}, },
}, css: {
css: { preprocessorOptions: {
preprocessorOptions: { scss: {
scss: { additionalData: '@use "@/assets/styles/mixins.scss" as *;',
additionalData: '@use "@/assets/styles/mixins.scss" as *;', },
}, },
}, },
}, define: {
define: { 'process.env': {}
'process.env': {} },
},
// 开发服务器配置 // 开发服务器配置
server: { server: {
// 启动时自动打开浏览器 // 启动时自动打开浏览器
// 开发服务器端口 // 开发服务器端口
port: 3000, port: 3000,
// 允许局域网访问 // 允许局域网访问
host: '0.0.0.0', host: '0.0.0.0',
proxy: { proxy: {
'/remoteServer': { '/remoteServer': {
target: 'http://192.168.1.199:8080/', target: env.VITE_BASE_URL,
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
ws: true, ws: true,
rewrite: path => path.replace(/^\/remoteServer/, ''), rewrite: path => path.replace(/^\/remoteServer/, ''),
}, },
} }
}, },
}
}) })
Loading…
Cancel
Save