|
@@ -1,41 +1,227 @@
|
|
|
<template>
|
|
|
<div id="index">
|
|
|
<el-row>
|
|
|
- <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
|
|
|
- <el-col :span="24" class="one"> 系统首页 </el-col>
|
|
|
+ <el-col :span="24" class="one">
|
|
|
+ <el-button type="primary" @click="toAdd">添加</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-table :data="list" row-key="_id" border>
|
|
|
+ <el-table-column align="center" label="菜单名称" prop="name"></el-table-column>
|
|
|
+ <el-table-column align="center" label="父级菜单" prop="parent_name"></el-table-column>
|
|
|
+ <el-table-column align="center" label="图标" width="80">
|
|
|
+ <template #default="scope"><span :class="['iconfont', scope.row.icon]"></span></template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="顺序" sortable prop="order_num" width="80"></el-table-column>
|
|
|
+ <el-table-column align="center" label="路由地址" prop="path"></el-table-column>
|
|
|
+ <el-table-column align="center" label="组件地址" prop="component"></el-table-column>
|
|
|
+ <el-table-column align="center" label="菜单类型" prop="type">
|
|
|
+ <template #default="scope">{{ getDict('type', scope.row) }} </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="是否启用" prop="is_use">
|
|
|
+ <template #default="scope">{{ getDict('is_use', scope.row) }} </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="备注" prop="remark"> </el-table-column>
|
|
|
+ <el-table-column align="center" label="操作">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-link :underline="false" type="primary" size="mini" @click="toUpdate(scope.row)" style="margin-right: 10px">修改</el-link>
|
|
|
+ <el-link :underline="false" type="primary" size="mini" @click="toAddNext(scope.row)" style="margin-right: 10px">添加下一级</el-link>
|
|
|
+ <el-link :underline="false" type="danger" size="mini" @click="toDelete(scope.row)">删除</el-link>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
+ <el-dialog v-model="dialog" title="菜单信息" :destroy-on-close="false" @close="toClose">
|
|
|
+ <el-tabs v-model="tab" type="border-card">
|
|
|
+ <el-tab-pane label="基本信息" name="basic">
|
|
|
+ <el-form label-position="left" label-width="120px">
|
|
|
+ <el-form-item label="菜单名称">
|
|
|
+ <el-input v-model="form.name" placeholder="请填写菜单名称"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="菜单类型">
|
|
|
+ <el-select v-model="form.type" placeholder="请选择菜单类型">
|
|
|
+ <el-option v-for="(i, index) in typeList" :key="`t${index}`" :label="i.label" :value="i.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="父级菜单">
|
|
|
+ <el-select v-model="form.parent_id" placeholder="" :disabled="false">
|
|
|
+ <el-option v-for="(i, index) in getOneDimensionList()" :key="`m${index}`" :label="i.name" :value="i._id"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <template v-if="form.type === '1' || form.type === '2'">
|
|
|
+ <el-form-item label="路由地址">
|
|
|
+ <el-input v-model="form.path" placeholder="请填写路由地址"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="组件地址">
|
|
|
+ <el-input v-model="form.component" placeholder="请填写组件地址"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+ <el-form-item label="顺序">
|
|
|
+ <el-input-number v-model="form.order_num"></el-input-number>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="图标">
|
|
|
+ <el-select v-model="form.icon" clearable filterable placeholder="请选择图标">
|
|
|
+ <el-option v-for="item in iconList" :key="item.label" :label="item.label" :value="item.label">
|
|
|
+ <span style="float: left" :class="['iconfont', item.label]"></span>
|
|
|
+ <span style="float: right; color: #8492a6; font-size: 13px">{{ item.label }}</span>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否启用">
|
|
|
+ <el-select v-model="form.is_use" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in is_useList" :key="item.value" :label="item.label" :value="item.value">
|
|
|
+ {{ item.label }}
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注">
|
|
|
+ <el-input v-model="form.remark" placeholder="请输入备注" type="textarea" :autosize="{ minRows: 5, maxRows: 5 }"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ <el-row type="flex" justify="space-around" style="margin-top: 10px">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-button @click="toSave(form)" size="small" type="primary">保存</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
// 基础
|
|
|
+import _ from 'lodash';
|
|
|
import type { Ref } from 'vue';
|
|
|
import { onMounted, ref } from 'vue';
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
|
|
// 接口
|
|
|
-// import { ToolsStore } from '@/stores/tool';
|
|
|
-// import type { IQueryResult } from '@/util/types.util';
|
|
|
-// const toolsAxios = ToolsStore();
|
|
|
+import { MenusStore } from '@/stores/basic/menus'; // 菜单
|
|
|
+import { DictDataStore } from '@/stores/basic/dictData'; // 字典表
|
|
|
+import type { IQueryResult } from '@/util/types.util';
|
|
|
+const menusAxios = MenusStore();
|
|
|
+const dictAxios = DictDataStore();
|
|
|
|
|
|
+let list: Ref<any> = ref([]);
|
|
|
+// 表单
|
|
|
+let form: Ref<any> = ref({});
|
|
|
+const tab: Ref<any> = ref('basic');
|
|
|
+// 字典表
|
|
|
+const is_useList: Ref<any> = ref([]);
|
|
|
+const iconList: Ref<any> = ref([]);
|
|
|
+const typeList: Ref<any> = ref([]);
|
|
|
// 加载中
|
|
|
const loading: Ref<any> = ref(false);
|
|
|
-
|
|
|
+// 弹框
|
|
|
+const dialog: Ref<any> = ref(false);
|
|
|
// 请求
|
|
|
onMounted(async () => {
|
|
|
loading.value = true;
|
|
|
- search();
|
|
|
+ await searchOther();
|
|
|
+ await search();
|
|
|
loading.value = false;
|
|
|
});
|
|
|
const search = async () => {
|
|
|
- // let res: IQueryResult = await toolsAxios.dataCount();
|
|
|
- // if (res.errcode == '0') {
|
|
|
- // info.value = res.data;
|
|
|
- // }
|
|
|
+ const res: IQueryResult = await menusAxios.query();
|
|
|
+ if (res.errcode == '0') list.value = res.data;
|
|
|
+};
|
|
|
+const getDict = (model: string, row: any) => {
|
|
|
+ let word = '';
|
|
|
+ if (model == 'type') {
|
|
|
+ const r = typeList.value.find((f) => f.value === row.type);
|
|
|
+ if (r) word = r.label;
|
|
|
+ return word;
|
|
|
+ } else {
|
|
|
+ const r = is_useList.value.find((f) => f.value === row.type);
|
|
|
+ if (r) word = r.label;
|
|
|
+ return word;
|
|
|
+ }
|
|
|
+};
|
|
|
+// 添加
|
|
|
+const toAdd = () => {
|
|
|
+ dialog.value = true;
|
|
|
+};
|
|
|
+// 保存
|
|
|
+const toUpdate = (row: any) => {
|
|
|
+ form.value = { parent_id: row._id };
|
|
|
+ dialog.value = true;
|
|
|
+};
|
|
|
+// 修改
|
|
|
+const toAddNext = (row: any) => {
|
|
|
+ form.value = _.cloneDeep(row);
|
|
|
+ dialog.value = true;
|
|
|
+};
|
|
|
+// 添加下一级
|
|
|
+const toSave = async (data: any) => {
|
|
|
+ let res: IQueryResult;
|
|
|
+ if (data._id) res = await menusAxios.update(data);
|
|
|
+ else res = await menusAxios.create(data);
|
|
|
+ if (res.errcode == 0) {
|
|
|
+ ElMessage({ type: `success`, message: `维护信息成功` });
|
|
|
+ toClose();
|
|
|
+ }
|
|
|
+};
|
|
|
+// 删除
|
|
|
+const toDelete = (data: any) => {
|
|
|
+ ElMessageBox.confirm('删除该菜单吗', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+ .then(async () => {
|
|
|
+ let res: IQueryResult = await menusAxios.del(data._id);
|
|
|
+ if (res.errcode == 0) {
|
|
|
+ ElMessage({ type: `success`, message: `删除成功` });
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => { });
|
|
|
+};
|
|
|
+// 获取一维(平面)的菜单数据
|
|
|
+const getOneDimensionList = () => {
|
|
|
+ let dup = _.cloneDeep(list.value);
|
|
|
+ let arr = getAllChild(dup);
|
|
|
+ return arr;
|
|
|
+};
|
|
|
+// 获取所有的子菜单
|
|
|
+const getAllChild = (children: any) => {
|
|
|
+ let arr = [];
|
|
|
+ for (const i of children) {
|
|
|
+ const { children, ...others } = i;
|
|
|
+ arr.push(others);
|
|
|
+ if (children) {
|
|
|
+ const marr = getAllChild(children);
|
|
|
+ arr.push(...marr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return arr;
|
|
|
+};
|
|
|
+// 关闭弹框
|
|
|
+const toClose = () => {
|
|
|
+ form.value = {};
|
|
|
+ tab.value = 'basic';
|
|
|
+ dialog.value = false;
|
|
|
+};
|
|
|
+// 查询其他信息
|
|
|
+const searchOther = async () => {
|
|
|
+ let res: IQueryResult;
|
|
|
+ // 是否启用
|
|
|
+ res = await dictAxios.query({ type: 'is_use', is_use: '0' });
|
|
|
+ if (res.errcode == '0') is_useList.value = res.data;
|
|
|
+ // 图标
|
|
|
+ res = await dictAxios.query({ type: 'info_icon', is_use: '0' });
|
|
|
+ if (res.errcode == '0') iconList.value = res.data;
|
|
|
+ // 菜单类型
|
|
|
+ res = await dictAxios.query({ type: 'menus_type', is_use: '0' });
|
|
|
+ if (res.errcode == '0') typeList.value = res.data;
|
|
|
};
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
.main {
|
|
|
padding: 2px;
|
|
|
+
|
|
|
+ .one {
|
|
|
+ padding: 20px 0;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|