菜单管理

This commit is contained in:
zhaoyz 2024-04-24 19:35:24 +08:00
parent 198b34f732
commit 15c9b35f1b
8 changed files with 442 additions and 307 deletions

55
src/api/menu.ts Normal file
View File

@ -0,0 +1,55 @@
import request from "@/utils/request";
const getMenuTreeUrl = "/admin/menu/tree";
const menuUrl = "/admin/menu";
export function getMenuTree(menuName?: string, parent?: string, type?: string) {
return new Promise((resolve, reject) => {
const params: any = [];
if (parent) {
params.push("parent=" + parent);
}
if (menuName) {
params.push("menuName=" + menuName);
}
if (type) {
params.push("type=" + type);
}
request.get(getMenuTreeUrl + (params.length > 0 ? "?" + params.join("&") : ""))
.then((res) => {
resolve(res.data);
}).catch(err => {
reject(err);
})
})
}
export function saveMenu(menu: any) {
return new Promise((resolve, reject) => {
request.post(menuUrl, menu).then((res: any) => {
resolve(res.data);
}).catch(err => {
reject(err);
})
})
}
export function updateMenu(menu: any) {
return new Promise((resolve, reject) => {
request.put(menuUrl, menu).then((res: any) => {
resolve(res);
}).catch(err => {
reject(err);
})
})
}
export function deleteById(id: string) {
return new Promise((resolve) => {
request.delete(menuUrl + "/" + id).then((res: any) => {
resolve(res.data);
}).catch(err => {
resolve(err);
})
})
}

View File

@ -20,7 +20,6 @@ function getLogList() {
logManageApi.getPage(0, 100).then((res: any) => { logManageApi.getPage(0, 100).then((res: any) => {
if (res.code == 0) { if (res.code == 0) {
activities.value = res.data.records; activities.value = res.data.records;
console.log(activities.value)
} }
}) })
} }

View File

@ -77,7 +77,6 @@ const userInfo = useLoginStore().getlogin()
const hospitals = ref([] as any) const hospitals = ref([] as any)
getHospitalsData().then((res: any) => { getHospitalsData().then((res: any) => {
hospitals.value = res hospitals.value = res
// console.log(res)
}) })
const menus = [] as any const menus = [] as any

View File

@ -1,40 +1,44 @@
<template> <template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100"> <el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
<el-form-item label="类型" prop="type"> <el-form-item label="类型" prop="type">
<el-radio-group v-model="formData.type" :disabled="type === 'edit'"> <el-radio-group v-model="formData.menuType" :disabled="type === 'edit'">
<el-radio label="菜单" border>菜单</el-radio> <el-radio label="0" border>菜单</el-radio>
<el-radio label="按钮" border>按钮</el-radio> <el-radio label="1" border v-if="formData.parentId != -1">按钮</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="上级菜单" prop="fatherMenu"> <el-form-item label="上级菜单" prop="parentName">
<el-select v-model="formData.fatherMenu" placeholder="请选择上级菜单" clearable> <!-- <el-select v-model="formData.parentMenu" placeholder="请选择上级菜单" clearable>
<el-option v-for="item in fatherMenuOption" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in parentMenu" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>-->
<el-input v-model="formData.parentName" readonly placeholder="请输入菜单名称"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="菜单名称" prop="menuName"> <el-form-item label="菜单名称" prop="name">
<el-input v-model="formData.menuName" placeholder="请输入菜单名称"></el-input> <el-input v-model="formData.name" placeholder="请输入菜单名称"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="图标" prop="icon"> <el-form-item label="图标" prop="icon">
<i :class="formData.icon" style="font-size: 26px;margin: 0 10px;"></i> <i :class="formData.icon" style="font-size: 26px;margin: 0 10px;"></i>
<el-button @click="isIconDialog = true">选择图标</el-button> <el-button @click="isIconDialog = true">选择图标</el-button>
</el-form-item> </el-form-item>
<el-form-item label="路由" prop="route"> <el-form-item label="路由" prop="route">
<el-input v-model="formData.route" placeholder="请输入路由"></el-input> <el-input v-model="formData.path" placeholder="请输入路由"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="order"> <el-form-item label="排序" prop="order">
<el-input class="number-input" v-model="formData.order" type="number" input-style="text-align: center;" @change="numberInputChange"> <el-input class="number-input" v-model="formData.sortOrder"
type="number" input-style="text-align: center;"
@change="numberInputChange">
<template #prepend> <template #prepend>
<el-button text icon="Minus" :disabled="formData.order <= 1" @click="formData.order--" /> <el-button text icon="Minus" :disabled="formData.sortOrder <= 1"
@click="formData.sortOrder--"/>
</template> </template>
<template #append> <template #append>
<el-button text icon="Plus" @click="formData.order++" /> <el-button text icon="Plus" @click="formData.sortOrder++"/>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="是否显示" prop="isShow"> <el-form-item label="是否显示" prop="visible">
<el-radio-group v-model="formData.isShow"> <el-radio-group v-model="formData.visible">
<el-radio :label="true" border></el-radio> <el-radio label="1" border></el-radio>
<el-radio :label="false" border></el-radio> <el-radio label="0" border></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
@ -46,7 +50,8 @@
<el-dialog v-model="isIconDialog" title="选择图标" top="20vh" width="25%"> <el-dialog v-model="isIconDialog" title="选择图标" top="20vh" width="25%">
<div class="iconfont-box"> <div class="iconfont-box">
<div class="iconfont-item" v-for="item in iconfont.glyphs" :key="item.font_class" @click="iconClick(item)"> <div class="iconfont-item" v-for="item in iconfont.glyphs"
:key="item.font_class" @click="iconClick(item)">
<i :class="'icon-' + item.font_class"></i> <i :class="'icon-' + item.font_class"></i>
</div> </div>
</div> </div>
@ -54,29 +59,26 @@
</template> </template>
<script lang='ts' setup> <script lang='ts' setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue' import {onMounted, reactive, ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import {ElMessage} from 'element-plus'
import iconfont from "@/assets/font/iconfont.json"; import iconfont from "@/assets/font/iconfont.json";
import * as menuApi from "@/api/menu";
const emit = defineEmits(['close']) const emit = defineEmits(['close', "saveOrUpdateEvent"])
const props = defineProps({ const props = defineProps({
type: String type: String
}) })
defineExpose({
const fatherMenuOption = [ resetData,
{ label: '权限管理', value: '权限管理' }, })
{ label: '患者管理', value: '患者管理' },
]
const rules = reactive({ const rules = reactive({
menuName: [ name: [
{ required: true, message: '请输入菜单名称', trigger: ['blur', 'change'] }, {required: true, message: '请输入菜单名称', trigger: ['blur', 'change']},
], ],
route: [ path: [
{ required: true, message: '请输入路由地址', trigger: ['blur', 'change'] }, {required: true, message: '请输入路由地址', trigger: ['blur', 'change']},
] ]
}) })
const formRef = ref() const formRef = ref()
const isIconDialog = ref(false) const isIconDialog = ref(false)
const formData = ref({} as any) const formData = ref({} as any)
@ -84,33 +86,45 @@ const formData = ref({} as any)
onMounted(() => { onMounted(() => {
resetData() resetData()
// console.log(iconfont.glyphs)
}) })
defineExpose({
formData,
resetData,
})
function close() { function close() {
emit('close') emit('close')
} }
function resetData() {
function resetData(menu?: any, form?: any) {
formRef.value.resetFields() formRef.value.resetFields()
if (form) {
formData.value = { formData.value = {
id: '', menuId: form.id,
type: '菜单', menuType: form.menuType,
fatherMenu: '', parentName: form.parentName,
menuName: '', parentId: form.parentId,
name: form.name,
icon: form.meta.icon,
path: form.path,
sortOrder: form.sortOrder,
visible: form.visible
}
} else {
formData.value = {
menuId: '',
menuType: '0',
parentName: menu ? menu.name : "无",
parentId: menu ? menu.id : "-1",
name: '',
icon: '', icon: '',
route: '', path: '',
order: 1, sortOrder: 1,
isShow: true visible: "1"
}
} }
} }
const numberInputChange = (e: any) => { const numberInputChange = (e: any) => {
if(!Number(e)) { if (!Number(e)) {
formData.value.order = 1 formData.value.sortOrder = 1
} }
} }
const iconClick = (e: any) => { const iconClick = (e: any) => {
@ -120,10 +134,26 @@ const iconClick = (e: any) => {
const saveData = async () => { const saveData = async () => {
await formRef.value.validate((valid: any, fields: any) => { await formRef.value.validate((valid: any, fields: any) => {
if (valid) { if (valid) {
ElMessage.success('保存成功!') const form = Object.assign({}, formData.value);
close() if (form.menuId) {
menuApi.updateMenu(form).then((res: any) => {
if (res.code == 0) {
ElMessage.success("修改成功");
emit("saveOrUpdateEvent");
} else { } else {
// console.log('error submit!', fields) ElMessage.error("修改失败");
}
})
} else {
menuApi.saveMenu(form).then((res: any) => {
if (res.code == 0) {
ElMessage.success('保存成功!');
emit("saveOrUpdateEvent");
} else {
ElMessage.error("保存失败");
}
})
}
} }
}) })
} }
@ -142,20 +172,24 @@ const saveData = async () => {
} }
} }
} }
.iconfont-box { .iconfont-box {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
.iconfont-item { .iconfont-item {
width: 50px; width: 50px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
text-align: center; text-align: center;
font-size: 30px; font-size: 30px;
&:hover { &:hover {
background: rgba($main-color, .1); background: rgba($main-color, .1);
} }
&:focus, &:active { &:focus, &:active {
background: rgba($main-color, .2); background: rgba($main-color, .2);
color: $main-color; color: $main-color;

View File

@ -10,10 +10,15 @@
<el-input v-model="formData.roleRemark" type="textarea" :rows="3" placeholder="请输入角色描述"></el-input> <el-input v-model="formData.roleRemark" type="textarea" :rows="3" placeholder="请输入角色描述"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="数据权限" prop="dataPermissions"> <el-form-item label="数据权限" prop="dataPermissions">
<el-select v-model="formData.dataPermissions" placeholder="请选择角色"> <!-- <el-select v-model="formData.dataPermissions" placeholder="请选择角色">
<el-option v-for="item in dataPermissionsOption" :key="item.value" :label="item.label" <el-option v-for="item in dataPermissionsOption" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
</el-select> </el-select>-->
<div class="tree-container">
<el-tree ref="treeRef" :key="treeKey" :props="treeProps" :data="treeData" :default-expanded-keys="expandedKey"
node-key="id"
show-checkbox @check-change="checkChange"/>
</div>
</el-form-item> </el-form-item>
<div style="text-align: right;padding-top: 0;"> <div style="text-align: right;padding-top: 0;">
@ -24,30 +29,28 @@
</template> </template>
<script lang='ts' setup> <script lang='ts' setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue' import {onMounted, reactive, ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import {ElMessage} from 'element-plus'
import {getMenuData} from '@/static-data/menu'
const emit = defineEmits(['close']) const emit = defineEmits(['close'])
const props = defineProps({ const props = defineProps({
type: String type: String
}) })
const dataPermissionsOption = [ const dataPermissionsOption = [
{ label: '全部', value: '全部' }, {label: '全部', value: '全部'},
] ]
const rules = reactive({ const rules = reactive({
roleName: [ roleName: [
{ required: true, message: '请输入角色名称', trigger: ['blur', 'change'] }, {required: true, message: '请输入角色名称', trigger: ['blur', 'change']},
], ],
roleMark: [ roleMark: [
{ required: true, message: '请输入角色标识', trigger: ['blur', 'change'] }, {required: true, message: '请输入角色标识', trigger: ['blur', 'change']},
], ],
dataPermissions: [ dataPermissions: [
{ required: true, message: '请选择数据权限', trigger: ['blur', 'change'] }, {required: true, message: '请选择数据权限', trigger: ['blur', 'change']},
] ]
}) })
const formRef = ref() const formRef = ref()
const formData = ref({ const formData = ref({
id: '', id: '',
@ -56,19 +59,27 @@ const formData = ref({
roleRemark: '', roleRemark: '',
dataPermissions: '', dataPermissions: '',
} as any) } as any)
const treeProps = {
label: 'menuName',
children: 'children'
}
const treeData = ref()
onMounted(() => { onMounted(() => {
resetData() resetData()
treeData.value = getMenuData()
}) })
defineExpose({ defineExpose({
formData, formData,
resetData, resetData,
}) })
function close() { function close() {
emit('close') emit('close')
} }
function resetData() { function resetData() {
formRef.value.resetFields() formRef.value.resetFields()
formData.value = { formData.value = {
@ -79,6 +90,7 @@ function resetData() {
dataPermissions: '', dataPermissions: '',
} }
} }
const saveData = async () => { const saveData = async () => {
await formRef.value.validate((valid: any, fields: any) => { await formRef.value.validate((valid: any, fields: any) => {
if (valid) { if (valid) {
@ -104,4 +116,11 @@ const saveData = async () => {
} }
} }
} }
.tree-container {
width: 100%;
min-height: 200px;
max-height: 500px;
overflow-y: auto;
}
</style> </style>

View File

@ -3,14 +3,14 @@
<div class="search-part" v-show="isSearch"> <div class="search-part" v-show="isSearch">
<div class="search-cell"> <div class="search-cell">
<span class="label">菜单名称</span> <span class="label">菜单名称</span>
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称"></el-input> <el-input v-model="queryParams" placeholder="请输入菜单名称"></el-input>
</div> </div>
<el-button type="primary" icon="Search" @click="queryData(queryParams)">查询</el-button> <el-button type="primary" icon="Search" @click="searchList">查询</el-button>
<el-button icon="Refresh" @click="queryParams = {}">重置</el-button> <el-button icon="Refresh" @click="resetSearch">重置</el-button>
</div> </div>
<div class="button-part" style="justify-content: space-between;"> <div class="button-part" style="justify-content: space-between;">
<div> <div>
<el-button type="primary" icon="FirstAidKit" @click="addData">新增</el-button> <el-button type="primary" icon="FirstAidKit" @click="addData()">新增</el-button>
<el-button @click="expandTable">展开/折叠</el-button> <el-button @click="expandTable">展开/折叠</el-button>
</div> </div>
<TableAbility :isDownload="false" @searchBtn="isSearch = !isSearch" @refreshBtn="initData()"></TableAbility> <TableAbility :isDownload="false" @searchBtn="isSearch = !isSearch" @refreshBtn="initData()"></TableAbility>
@ -18,62 +18,79 @@
<div class="table-part"> <div class="table-part">
<el-table ref="tableRef" :data="tableData" row-key="id" height="100%" border show-overflow-tooltip <el-table ref="tableRef" :data="tableData" row-key="id" height="100%" border show-overflow-tooltip
@row-click="tableRowClick"> @row-click="tableRowClick">
<el-table-column property="menuName" label="菜单名称" width="180" align="center" /> <el-table-column property="name" label="菜单名称" width="180" align="center"/>
<el-table-column property="order" label="排序" width="80" align="center" /> <el-table-column property="sortOrder" label="排序" width="80" align="center"/>
<el-table-column label="图标" width="80" align="center"> <el-table-column label="图标" width="80" align="center">
<template #default="scope"><i class="main-color f20" :class="scope.row.icon"></i></template> <template #default="scope"><i class="main-color f20" :class="scope.row.meta.icon"></i></template>
</el-table-column> </el-table-column>
<el-table-column property="route" label="路由" width="260" align="center" /> <el-table-column property="path" label="路由" width="260" align="center"/>
<el-table-column property="type" label="类型" width="180" align="center" /> <el-table-column property="menuType" label="类型" width="180" align="center"/>
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default="scope"> <template #default="scope">
<span @click.stop> <div @click.stop>
<el-button link icon="EditPen" @click="addData(scope.row)">新建下级</el-button>
<el-button link icon="EditPen" @click="editData(scope.row)">修改</el-button> <el-button link icon="EditPen" @click="editData(scope.row)">修改</el-button>
<el-button link icon="Delete" @click="removeData(scope.row)">删除</el-button> <el-button link icon="Delete" @click="removeData(scope.row)">删除</el-button>
</span> </div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
<div class="pagination-part">
<CommonPagination :total="100" @paginationChange="paginationChange" />
</div>
</div> </div>
<el-dialog v-model="isFormDialog" :title="formDialogTitle" width="30%"> <el-dialog v-model="isFormDialog" :title="formDialogTitle" width="30%">
<MenuForm ref="doctorFormRef" :type="formDialogTitle === '添加' ? 'add' : 'edit'" @close="isFormDialog = false" /> <MenuForm ref="menuFormRef" :type="formDialogTitle === '添加' ? 'add' : 'edit'"
@save-or-update-event="formSaveUpdateEvent" @close="isFormDialog = false"/>
</el-dialog> </el-dialog>
</template> </template>
<script lang='ts' setup> <script lang='ts' setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue' import {onMounted, ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { tableRemoveRow, exportData } from '@/utils/table-util'
import { getMenuData } from '@/static-data/menu'
import CommonPagination from '@/components/common-pagination.vue'
import MenuForm from './form/menu-form.vue' import MenuForm from './form/menu-form.vue'
import * as menuApi from "@/api/menu";
import {ElMessage, ElMessageBox} from "element-plus";
let isExpand = false // let isExpand = false //
const tableRef = ref() const tableRef = ref()
const doctorFormRef = ref() const menuFormRef = ref()
const isSearch = ref(true) const isSearch = ref(true)
const loading = ref(true) const loading = ref(true)
const isFormDialog = ref(false) const isFormDialog = ref(false)
const formDialogTitle = ref('') const formDialogTitle = ref('')
const queryParams = ref({ const queryParams = ref('')
menuName: ''
} as any)
const tableData = ref([] as any) const tableData = ref([] as any)
initData() onMounted(() => {
initData();
})
function initData() { function initData() {
loading.value = true loading.value = true;
tableData.value = [] tableData.value = [];
setTimeout(() => { getMenuTree();
tableData.value = getMenuData() }
loading.value = false
}, 200); function searchList() {
loading.value = true;
tableData.value = [];
getMenuTree(queryParams.value)
}
function resetSearch() {
queryParams.value = '';
initData();
}
function getMenuTree(name?: string) {
menuApi.getMenuTree(name).then((res: any) => {
tableData.value = res.data;
updateMenuTree(res.data, tableData.value);
})
}
function updateMenuTree(source: any[], target: any[]) {
target.forEach((row: any) => {
});
} }
const queryData = (e: any) => { const queryData = (e: any) => {
@ -93,11 +110,11 @@ const queryData = (e: any) => {
loading.value = false loading.value = false
}, 200); }, 200);
} }
const addData = () => { const addData = (menu?: any) => {
isFormDialog.value = true isFormDialog.value = true
formDialogTitle.value = '添加' formDialogTitle.value = '添加'
setTimeout(() => { setTimeout(() => {
doctorFormRef.value.resetData() menuFormRef.value.resetData(menu)
}, 0) }, 0)
} }
const expandTable = () => { const expandTable = () => {
@ -107,27 +124,41 @@ const expandTable = () => {
}) })
} }
const removeData = (e?: any) => { const removeData = (e?: any) => {
const selectRow = e || tableRef.value.getSelectionRows() ElMessageBox.confirm(
tableRemoveRow({ data: selectRow }, (res: boolean) => { '是否删除?',
if (res) { {
// console.log('', selectRow) confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true
} }
).then(() => {
menuApi.deleteById(e.id).then((res: any) => {
if (res.code == 0) {
ElMessage.success("删除成功");
initData();
} else {
ElMessage.error(res.msg ? res.msg : "删除失败");
}
})
}) })
} }
const editData = (e: any) => { const editData = (e: any) => {
isFormDialog.value = true isFormDialog.value = true
formDialogTitle.value = '修改' formDialogTitle.value = '修改'
setTimeout(() => { setTimeout(() => {
doctorFormRef.value.resetData() menuFormRef.value.resetData(null, JSON.parse(JSON.stringify(e)))
doctorFormRef.value.formData = JSON.parse(JSON.stringify(e))
}, 0) }, 0)
} }
const tableRowClick = (row: any) => { const tableRowClick = (row: any) => {
tableRef.value.toggleRowExpansion(row) tableRef.value.toggleRowExpansion(row)
} }
const paginationChange = (page: number, size: number) => {
function formSaveUpdateEvent() {
isFormDialog.value = false;
initData();
} }
</script> </script>
<style lang='scss' scoped></style> <style lang='scss' scoped></style>

View File

@ -3,7 +3,7 @@
<div class="search-part" v-show="isSearch"> <div class="search-part" v-show="isSearch">
<div class="search-cell"> <div class="search-cell">
<span class="label">角色名称</span> <span class="label">角色名称</span>
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称"></el-input> <el-input v-model="queryParams" placeholder="请输入角色名称"></el-input>
</div> </div>
<el-button type="primary" icon="Search" @click="queryData(queryParams)">查询</el-button> <el-button type="primary" icon="Search" @click="queryData(queryParams)">查询</el-button>
<el-button icon="Refresh" @click="queryParams = {}">重置</el-button> <el-button icon="Refresh" @click="queryParams = {}">重置</el-button>
@ -51,10 +51,9 @@
</template> </template>
<script lang='ts' setup> <script lang='ts' setup>
import { onMounted, reactive, ref, toRefs, watch } from 'vue' import {ref} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import {dateFormater} from '@/utils/date-util'
import { dateFormater } from '@/utils/date-util' import {exportData, tableRemoveRow} from '@/utils/table-util'
import { tableRemoveRow, exportData } from '@/utils/table-util'
import CommonPagination from '@/components/common-pagination.vue' import CommonPagination from '@/components/common-pagination.vue'
import RoleForm from './form/role-form.vue' import RoleForm from './form/role-form.vue'
import ImportDialog from '@/components/import-dialog.vue' import ImportDialog from '@/components/import-dialog.vue'
@ -68,9 +67,7 @@ const isSearch = ref(true)
const loading = ref(true) const loading = ref(true)
const isFormDialog = ref(false) const isFormDialog = ref(false)
const formDialogTitle = ref('') const formDialogTitle = ref('')
const queryParams = ref({ const queryParams = ref("")
roleName: ''
} as any)
const tableData = ref([] as any) const tableData = ref([] as any)
queryData({ roleName: '测试' }) queryData({ roleName: '测试' })
@ -127,6 +124,7 @@ const editData = (e: any) => {
const tableRowClick = (row: any) => { const tableRowClick = (row: any) => {
tableRef.value.toggleRowSelection(row) tableRef.value.toggleRowSelection(row)
} }
const paginationChange = (page: number, size: number) => { const paginationChange = (page: number, size: number) => {
} }

View File

@ -24,14 +24,14 @@ export default defineConfig({
proxy: { proxy: {
'/api': { '/api': {
//target: 'http://192.168.137.235:9999', // 目标服务器地址 //target: 'http://192.168.137.235:9999', // 目标服务器地址
target: 'http://192.168.1.110:9999', // 目标服务器地址 target: 'http://localhost:9999', // 目标服务器地址
ws: true, // 是否启用 WebSocket ws: true, // 是否启用 WebSocket
changeOrigin: true, // 是否修改请求头中的 Origin 字段 changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/api/, ''),
}, },
'/socket.io': { '/socket.io': {
//target: 'ws://192.168.137.235:9999', //target: 'ws://192.168.137.235:9999',
target: 'ws://192.168.1.110:9999', target: 'ws://localhost:9999',
ws: true, ws: true,
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/socket.io/, ''), rewrite: (path) => path.replace(/^\/socket.io/, ''),