Commit dd2396a7 authored by 孙浩然's avatar 孙浩然

web后端维护

parent fc866840
......@@ -7,7 +7,15 @@ import type { addMenuDto, delMenuDto, getMenuListDto } from '@/types/BiMenu';
* @returns
*/
const addMenu = (data: addMenuDto) =>
request('/bi-manager/menu/addMenu', 'get', data);
request('/bi-manager/menu/addMenu', 'post', data);
/**
* 新增菜单
* @param addMenuDto
* @returns
*/
const editMenu = (data: addMenuDto) =>
request('/bi-manager/menu/editMenu', 'post', data);
/**
* 删除菜单
......@@ -15,7 +23,7 @@ const addMenu = (data: addMenuDto) =>
* @returns
*/
const delMenu = (data: delMenuDto) =>
request('/bi-manager/menu/delMenu', 'get', data);
request('/bi-manager/menu/delMenu', 'post', data);
/**
* 查询
......@@ -23,6 +31,6 @@ const delMenu = (data: delMenuDto) =>
* @returns
*/
const getMenuList = (data: getMenuListDto) =>
request('/bi-manager/menu/getMenuList', 'get', data);
request('/bi-manager/menu/getMenuList', 'post', data);
export default { addMenu, delMenu, getMenuList };
export default { addMenu, editMenu, delMenu, getMenuList };
......@@ -15,6 +15,7 @@ import './styles/themes/dark.scss';
import './styles/index.scss';
import 'uno.css';
import './styles/vxetheme.scss';
import './styles/common.scss';
const app = createApp(App);
......
.page-container {
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.w100 {
width: 100%;
}
.flex-content-x {
flex: 1;
overflow-x: auto;
position: relative;
}
.flex-content-y {
flex: 1;
overflow-y: auto;
position: relative;
}
.card {
padding: 8px;
background-color: #fff;
border-radius: 5px;
overflow: hidden;
}
/* 横向flex布局 */
.flex-start-start {
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
.flex-start-center {
display: flex;
justify-content: flex-start;
align-items: center;
}
.flex-start-end {
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
.flex-center-center {
display: flex;
justify-content: center;
align-items: center;
}
.flex-center-start {
display: flex;
justify-content: center;
align-items: flex-start;
}
.flex-center-end {
display: flex;
justify-content: center;
align-items: flex-end;
}
.flex-end-start {
display: flex;
justify-content: flex-end;
align-items: flex-start;
}
.flex-end-center {
display: flex;
justify-content: flex-end;
align-items: center;
}
.flex-end-end {
display: flex;
justify-content: flex-end;
align-items: flex-end;
}
.flex-spacebetween-center {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-spacebetween-start {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.flex-spacebetween-end {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.flex-spacearound-start {
display: flex;
justify-content: space-around;
align-items: flex-start;
}
.flex-spacearound-center {
display: flex;
justify-content: space-around;
align-items: center;
}
.flex-spacearound-end {
display: flex;
justify-content: space-around;
align-items: flex-end;
}
.flex-column {
display: flex;
flex-direction: column;
}
.w100 {
width: 100%;
}
.h100{
height: 100%;
}
.flex-1 {
flex: 1;
}
// 间距
.margin10 {
margin: 10px;
}
.margin_bottom10 {
margin-bottom: 10px;
}
.margin_top10 {
margin-top: 10px;
}
.margin_left10 {
margin-left: 10px;
}
.margin_right10 {
margin-right: 10px;
}
.padding10 {
padding: 10px;
}
.margin_bottom8 {
margin-bottom: 8px;
}
<template>
<ele-modal
v-model="modalVisible"
:title="modalTitle"
width="600px"
position="center"
@close="handleCancel"
>
<ele-loading :loading="pageLoading">
<ele-card>
<pro-form
ref="ProFormRef"
label-width="auto"
:model="form"
:items="items"
:footer="false"
:grid="{ span: 24 }"
@updateValue="setFieldValue"
/>
</ele-card>
</ele-loading>
<template #footer>
<el-button type="primary" plain @click="handleCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
</ele-modal>
</template>
<script lang="ts" setup>
// tools
import { useFormData } from '@/utils/use-form-data';
import { addMenuDto } from '@/types/BiMenu';
import { tryit } from 'radash';
import { EleMessage } from 'ele-admin-plus';
import menuApi from '@/api/menuApi';
const modalVisible = ref(false);
const useType = ref<'add' | 'edit'>('add');
const pageLoading = ref(false);
const modalTitle = computed(() => {
return useType.value === 'add' ? '添加菜单' : '编辑菜单';
});
/** 表单数据 */
const [form, resetFields, , setFieldValue] = useFormData<addMenuDto>({
menuType: '0', // 类型:0web端,1移动端
pid: '', // 父级ID
menuName: '', // 菜单名称
menuUrl: '', // 菜单链接
menuId: '', // 菜单ID
isJoint: 0, // 是否需要拼接参数 1拼,0不拼
status: 0, // 状态:0开启,1关闭
sort:0, // 排序
});
// 打开
const curInfo = ref<addMenuDto>();
const open = (type: 'add' | 'edit' = 'add', info?: addMenuDto) => {
useType.value = type;
modalVisible.value = true;
if(info){
curInfo.value = info;
Object.assign(form, info);
}
// if (type === 'edit') {
// curInfo.value = info;
// Object.assign(form, info);
// }
};
defineExpose({
open: open as (type: 'add' | 'edit', info?: addThemeDTO) => void
});
onMounted(() => {
getMenuList(); // 获取菜单列表
});
const menuList = ref([]);
const getMenuList = async () => {
pageLoading.value = true;
let params = {
menuType: '0'
};
const [err, ret] = await tryit(menuApi.getMenuList)(params);
if (err) {
console.error(err);
return;
}
if (ret.code === 200) {
menuList.value = ret.data.map((item) => {
return {
label: item.menuName,
value: item.menuId
};
});
}
pageLoading.value = false;
};
/** 表单项 */
const items = computed<Array<ProFormItemProps>>(() => [
{
label: '上级菜单',
prop: 'pid',
type: 'select',
options: menuList.value
},
{
label: '菜单名称',
prop: 'menuName',
type: 'input',
required: true
},
{
label: '菜单链接',
prop: 'menuUrl',
type: 'input',
required: true
},
{
label: '排序',
prop: 'sort',
type: 'inputNumber',
required: true
},
// {
// label: '关联角色',
// prop: 'roleIds',
// type: 'multipleSelect',
// options: roleList.value,
// required: true
// },
{
label: '是否需要拼参数',
prop: 'isJoint',
type: 'radio',
options: [
{ label: '不拼', value: 0 },
{ label: '', value: 1 }
],
required: true
},
{
label: '是否开启',
prop: 'status',
type: 'radio',
options: [
{ label: '开启', value: 0 },
{ label: '关闭', value: 1 }
],
required: true
}
]);
/** 提交 */
const ProFormRef = ref<FormInstance>();
const emits = defineEmits(['reload']);
const onSubmit = () => {
ProFormRef.value?.validate(async (valid) => {
if (!valid) {
EleMessage.warning('请填写必填项');
return;
}
ElMessageBox.confirm(
`确定要${useType.value === 'add' ? '保存' : '修改'}?`,
'提示',
{
type: 'warning'
}
).then(async () => {
pageLoading.value = true;
const apiObj = {
add: menuApi.addMenu,
edit: menuApi.editMenu
};
let params = {
...form,
pid: form.pid === '' ? 0 : form.pid
};
const [, ret] = await tryit(apiObj[useType.value!])(params);
if (ret?.code === 200) {
EleMessage.success(useType.value === 'add' ? '添加成功' : '修改成功');
emits('reload');
handleClose();
}
pageLoading.value = false;
});
});
};
// 关闭
const handleClose = () => {
modalVisible.value = false;
resetFields();
};
// 点击取消
const handleCancel = () => {
handleClose();
};
</script>
......@@ -6,35 +6,56 @@
<template #toolbar_slot>
<div class="p-l-4px flex flex-content-start">
<FcCardTip title="菜单维护" />
<el-button class="m-l-4px" type="primary" plain size="small">
<el-button class="m-l-4px" type="primary" plain size="small" @click="toggleExpand">
收起/展开
</el-button>
<el-button type="success" size="small">添加菜单</el-button>
<el-button type="success" size="small" @click="handleAdd"
>添加菜单</el-button
>
</div>
</template>
<!-- 菜单名称 -->
<template #menuName_slot="{ row }">
<div class="menuName_text flex-start-center">
<span> {{ row.menuName }}</span>
<el-icon color="#114dfc" size="16px" class="m-l-4px">
<el-icon
color="#114dfc"
size="18px"
class="m-l-4px"
@click="handleAddByNext(row)"
>
<CirclePlus />
</el-icon>
</div>
</template>
<!-- 操作 -->
<template #option_slot>
<el-link type="primary">编辑</el-link>
<template #option_slot="{ row }">
<el-link type="primary" @click="handleEdit(row)">编辑</el-link>
<el-divider direction="vertical" />
<el-link type="warning">页面预览</el-link>
<el-divider direction="vertical" />
<el-link type="danger">删除</el-link>
<el-link type="danger" @click="handleDelete(row)">删除</el-link>
</template>
<!-- 展开插槽 -->
<template #expand_slot>
<vxe-grid v-bind="expandGridOptions" />
<template #expand_slot="{ row }">
<vxe-grid v-bind="expandGridOptions" :data="row.menuChildren">
<!-- 操作 -->
<template #option_slot="{ row }">
<el-link type="primary" @click="handleEdit(row)">编辑</el-link>
<el-divider direction="vertical" />
<el-link type="warning">页面预览</el-link>
<el-divider direction="vertical" />
<el-link type="danger" @click="handleDelete(row)">删除</el-link>
</template>
</vxe-grid>
</template>
</vxe-grid>
</div>
<!-- 新增/编辑弹窗 -->
<addMenu ref="AddMenuRef" @reload="getMenuList"></addMenu>
</ele-loading>
</template>
......@@ -43,6 +64,16 @@
import { FcCardTip } from '@fancy-design/coms';
import { CirclePlus } from '@element-plus/icons-vue';
import { VxeGridProps } from 'vxe-table';
import { tryit } from 'radash';
import { EleMessage } from 'ele-admin-plus';
import menuApi from '@/api/menuApi';
import addMenu from './components/AddMenu.vue';
onMounted(() => {
getMenuList(); // 获取菜单列表
});
const xGrid = ref()
const pageLoading = ref(false);
const gridOptions = reactive<VxeGridProps>({
......@@ -81,18 +112,19 @@
slots: { content: 'expand_slot', default: 'menuName_slot' }
},
{
field: 'url',
field: 'menuUrl',
title: 'URL地址'
},
{
field: '操作',
fixed: 'right',
title: '操作',
width: 200,
slots: { default: 'option_slot' }
}
],
pagerConfig: {
enabled: true,
enabled: false,
pageSize: 10,
pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000]
},
......@@ -123,7 +155,7 @@
title: '菜单名称'
},
{
field: 'url',
field: 'menuUrl',
title: 'URL地址'
},
{
......@@ -131,9 +163,96 @@
fixed: 'right',
title: 'Role',
sortable: true,
editRender: { name: 'input', attrs: { placeholder: '请输入角色' } }
width: 200,
slots: { default: 'option_slot' }
}
],
data: [{ menuName: '首页', url: 'www.ce.com' }]
data: []
});
// 获取菜单列表
const getMenuList = async () => {
pageLoading.value = true;
let parmas = {
menuType: '0'
};
const [err, ret] = await tryit(menuApi.getMenuList)(parmas);
if (err) {
console.error(err);
return;
}
if (ret?.code === 200) {
gridOptions.data = ret.data;
}
pageLoading.value = false;
};
// 添加菜单
const AddMenuRef = ref();
const handleAdd = () => {
AddMenuRef.value.open();
};
// 编辑菜单
const handleEdit = (row) => {
row.pid = row.pid == 0 ? '' : row.pid; // pid特殊处理
AddMenuRef.value.open('edit', row); // 传递菜单信息
};
// 添加子集
const handleAddByNext = (row) => {
let obj = {
pid: row.menuId
};
AddMenuRef.value.open('add', obj); // 传递父菜单信息
};
// 删除菜单
const handleDelete = async (row) => {
ElMessageBox.confirm(`确定要删除此菜单吗?`, '提示', {
type: 'warning'
}).then(async (res) => {
let params = {
menuId: row.menuId,
menuType: '0',
pid: row.pid
};
const [err, ret] = await tryit(menuApi.delMenu)(params);
if (err) {
console.error(err);
return;
}
if (ret?.code === 200) {
EleMessage.success('删除成功');
getMenuList(); // 重新获取菜单列表
}
});
};
// 展开/收起
const toggleExpand = () => {
console.log("🚀 ~ handleUnfold ~ xGrid.value:", xGrid.value)
// xGrid.value.setRowExpand();
}
</script>
<style lang="scss" scoped>
.menuName_text {
display: inline-block;
:deep() {
.el-icon {
cursor: pointer;
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment