123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- <template>
- <div class="mainBox">
- <!--搜索功能 start------------------------------------------------------------>
- <div class="layerBoxNoBg">
- <div>
- <el-button type="primary" @click="openWindow">添加菜单</el-button>
- </div>
- <div>
-
- </div>
- </div>
- <!--搜索功能 end------------------------------------------------------------>
- <!--表格内容 start------------------------------------------------------------>
- <div class="layerBox">
- <tableTitle :name="tableDivTitle"/>
- <el-row>
- <template>
- <!--设置default-expand-all将展开全部-->
- <el-table :data="tableData" style="width: 100%;margin-bottom: 20px;" row-key="id" border default-expand :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
- <el-table-column
- prop="id"
- label="id"
- sortable
- width="180">
- </el-table-column>
- <el-table-column
- prop="label"
- label="菜单名称"
- sortable
- width="180">
- </el-table-column>
- <el-table-column
- prop="url"
- label="路由地址">
- </el-table-column>
- <el-table-column fixed="right" label="操作" width="200" header-align="center">
- <template slot-scope="scope">
- <div class="listBtnBox">
- <div class="listDeleteBtn" @click="deleteRow(scope.row.id)"><i class="el-icon-delete"></i>移除</div>
- <div class="listEditBtn" @click="editRow(scope.row)"><i class="el-icon-edit-outline"></i>编辑</div>
- </div>
- </template>
- </el-table-column>
- </el-table>
- </template>
- </el-row>
- </div>
- <!--表格内容 end------------------------------------------------------------>
- <!--弹出框 start------------------------------------------------------------>
- <el-dialog :title="editId ? '编辑菜单' : '添加菜单'" :visible.sync="windowStatus" :close-on-click-modal="false">
- <el-form :model="form" ref="form" :rules="formRules" label-position="left">
- <div class="formDiv">
- <el-form-item label="菜单名称" :label-width="formLabelWidth" prop="label" class="custom-align-right">
- <el-input v-model="form.label" autocomplete="off" placeholder="请输入菜单名称"></el-input>
- </el-form-item>
- <el-form-item label="是否为顶级菜单" :label-width="formLabelWidth" class="custom-align-right">
- <el-radio v-model="radio" label="1">是</el-radio>
- <el-radio v-model="radio" label="2">否</el-radio>
- </el-form-item>
- <el-form-item label="菜单路由" :label-width="formLabelWidth" prop="url" class="custom-align-right" v-if="radio === '2'">
- <el-input v-model="form.url" autocomplete="off" placeholder="请输入菜单路由"></el-input>
- </el-form-item>
- <el-form-item label="父级菜单名称" :label-width="formLabelWidth" prop="pid_arr" class="custom-align-right" v-if="radio === '2'">
- <el-cascader :key="parentKey" v-model="form.pid_arr" :props="{checkStrictly:true}" :options="pidArrData" clearable></el-cascader>
- </el-form-item>
- <el-form-item label="默认图标" :label-width="formLabelWidth" prop="icon" class="custom-align-right" v-if="radio == '1'">
- <!--图片上传组件 start ------------------------------------------------------------>
- <div class="uploaderBox">
- <div class="avatar-upload-container" @mouseenter="hovering = true" @mouseleave="hovering = false">
- <!-- 上传组件 -->
- <el-upload class="avatar-uploader" action="#" :show-file-list="false" :before-upload="beforeAvatarUpload">
- <!-- 预览图片 -->
- <img v-if="iconSrc" :src="iconSrc" class="avatar">
- <div v-else class="chooseImgDiv">
- <div>
- <img src="@/assets/public/upload/noImage.png">
- <div>选择图片</div>
- </div>
- </div>
- </el-upload>
- <!-- 删除按钮,当鼠标悬浮时显示 -->
- <div v-if="hovering && iconSrc" class="delete-button" @click="handleDelete">
- <i class="el-icon-delete"></i>
- </div>
- </div>
- </div>
- <!--图片上传组件 end ------------------------------------------------------------>
- </el-form-item>
- <el-form-item label="选中时图标" :label-width="formLabelWidth" prop="selected_icon" class="custom-align-right" v-if="radio == '1'">
- <!--图片上传组件 start ------------------------------------------------------------>
- <div class="uploaderBox">
- <div class="avatar-upload-container" @mouseenter="hoveringTwo = true" @mouseleave="hoveringTwo = false">
- <!-- 上传组件 -->
- <el-upload class="avatar-uploader" action="#" :show-file-list="false" :before-upload="beforeAvatarUploadTwo">
- <!-- 预览图片 -->
- <img v-if="iconSrcSelect" :src="iconSrcSelect" class="avatar">
- <div v-else class="chooseImgDiv">
- <div>
- <img src="@/assets/public/upload/noImage.png">
- <div>选择图片</div>
- </div>
- </div>
- </el-upload>
- <!-- 删除按钮,当鼠标悬浮时显示 -->
- <div v-if="hoveringTwo && iconSrcSelect" class="delete-button" @click="handleDeleteTwo">
- <i class="el-icon-delete"></i>
- </div>
- </div>
- </div>
- <!--图片上传组件 end ------------------------------------------------------------>
- </el-form-item>
- <el-form-item label="权重" :label-width="formLabelWidth" prop="sort" class="custom-align-right">
- <el-input v-model="form.sort" autocomplete="off" placeholder="请输入权重"></el-input>
- </el-form-item>
- </div>
- </el-form>
- <div slot="footer" class="dialog-footer">
- <div>
- <el-button @click="closeWindow">取 消</el-button>
- <el-button type="primary" @click="editToServe" v-if="editBtn==true">编辑</el-button>
- <el-button type="primary" @click="addToServe" v-else>提交</el-button>
- </div>
- </div>
- </el-dialog>
- <!--弹出框 end------------------------------------------------------------>
- </div>
- </template>
- <script>
- //表格标题
- import openWindow from '@/utils/open-window';
- import tableTitle from './components/tableTitle';
- //引入公用样式
- import '@/styles/global.less';
- export default {
- components: {
- tableTitle,//表格标题
- },
- data() {
- //0.全局操作 start ------------------------------------------------------------>
- const validateEmpty = (rule,value,callback) => {
- if (value.length == 0) {
- callback(new Error('该项不能为空!'))
- } else {
- callback()
- }
- }
- const validateArray = (rule,value,callback) => {
- if (value.length == 0) {
- callback(new Error('该项不能为空!'))
- } else {
- callback()
- }
- }
- //0.全局操作 end ------------------------------------------------------------>
- return {
- //1.列表和分页相关 start ------------------------------------------------------------>
- tableDivTitle:"菜单列表",
- tableData: [],//内容列表
- editId:"",//编辑id
- radio: '2',//是否为顶级菜单 1=是 2=否
- //分页相关 end ------------------------------------------------------------>
- //2.弹出框设置 start ------------------------------------------------------------>
- //是否显示弹出窗口
- windowStatus:false,
- formLabelWidth: '120px',
- editBtn:false,//当显示编辑按钮的时候,就不显示提交
- //弹出框设置 end ------------------------------------------------------------>
- //3.弹出框中的表单设置 start ------------------------------------------------------------>
- form: {
- label:"",//菜单名称
- url:"",//菜单路由地址
- icon:"",//默认图标
- selected_icon:"",//选中时图标
- sort:"",//权重
- pid_arr:[]//父级id
- },
- //通过api获的的菜单列表
- parentKey:0,
- pidArrData:[],
- //3.1 上传默认图标
- iconSrc:'',//默认图标缩略图
- hovering: false,//显示删除图标
- iconSrcSelect:'',//选中时图标缩略图
- hoveringTwo: false,//显示删除图标
- //3.2 表单验证规则
- formRules: {
- label:[{required:true,trigger:'blur',validator:validateEmpty}],
- url:[{required:true,trigger:'blur',validator:validateEmpty}],
- icon:[{required:true,trigger:'blur',validator:validateEmpty}],
- selected_icon:[{required:true,trigger:'blur',validator:validateEmpty}],
- sort:[{required:true,trigger:'blur',validator:validateEmpty}],
- pid_arr:[{required:true,trigger:'blur',validator:validateArray}],
- },
- //弹出框中的表单设置 end ------------------------------------------------------------>
- }
- },
- methods: {
- //1.列表和分页相关 start ------------------------------------------------------------>
- //1.1 开始请求列表信息方法
- getData(){
- this.$store.dispatch('menu/getMenuList').then(res=> {
- this.tableData = res.data
- console.log(this.tableData)
- //格式化以后放入级联选择器
- let arrData = this.transformData(res.data)
- this.pidArrData = arrData;
- }).catch(() => {
- this.$message({
- type: 'warning',
- message: '网络错误,请重试!'
- });
- })
- },
- //1.2格式化菜单列表
- transformData(arrData) {
- let that = this;
- return arrData.map(item => {
- // 创建一个新的对象,替换键名
- let newItem = {
- label: item.label,
- value: item.id,
- };
- // 如果有 children,则递归处理 children 数组
- if (item.children && item.children.length > 0) {
- newItem.children = that.transformData(item.children);
- }
- return newItem;
- });
- },
- //1.2 删除内容
- deleteRow(id){
- this.$confirm('此操作将永久删除该条数据, 是否继续?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- console.log("当前删除:" + id)
- this.$store.dispatch('menu/delMenu',{id:id}).then(res=> {
- this.getData();
- if(res.code==200){
- this.$message({
- type: 'success',
- message: '删除成功!'
- });
- this.getData();
- }else{
- this.$message({
- type: 'warning',
- message: '请先移除子菜单!'
- });
- }
- }).catch(() => {
- this.$message({
- type: 'warning',
- message: '网络错误,请重试!'
- });
- })
- }).catch(() => {
- this.$message({
- type: 'warning',
- message: '已取消删除'
- });
- });
- },
- //1.3 回显数据
- editRow(data){
- this.editId = data.id;
- console.log(data)
- this.openWindow();
- this.form.label = data.label;
- this.form.url = data.url;
- this.form.icon = data.icon;
- this.form.selected_icon = data.selected_icon;
- this.form.sort = data.sort;
- //回显父级
- if(data.pid==0){
- //如果是顶级菜单
- this.radio = "1";//是顶级菜单
- }else{
- this.radio = "2";//不是顶级菜单
- //如果不是顶级菜单 显示到选择器中
- this.parentKey += 1;
- console.log(this.pidArrData)
- console.log(data.pid)
- this.form.pid_arr = [data.pid];
- }
-
- //回显示icon
- this.iconSrc = data.icon;
- this.iconSrcSelect = data.selected_icon;
- //显示编辑按钮
- this.editBtn = true;
- },
- //提交
- addToServe(){
- //先判断是不是顶级菜单
- if(this.radio=="1"){
- //如果是顶级菜单
- this.form.pid_arr = [0];
- }
- //执行验证
- this.$refs.form.validate(valid => {
- if (valid) {
- this.$store.dispatch('menu/addMenu',this.form).then(res=> {
- if(res.code==200){
- this.$message({
- type: 'success',
- message: '成功添加路由!'
- });
- this.getData();
- this.closeWindow();
- }
- }).catch(() => {
- this.$message({
- type: 'warning',
- message: '网络错误!'
- });
- });
- }
- })
- },
- //修改
- editToServe(){
- this.$refs.form.validate(valid => {
- if (valid) {
- let data = this.form;
- data.id = this.editId;
- this.$store.dispatch('menu/updateMenu',data).then(res=> {
- if(res.code==200){
- this.$message({
- type: 'success',
- message: '路由状态已修改!'
- });
- this.getData();
- this.closeWindow();
- }
- }).catch(() => {
- this.$message({
- type: 'warning',
- message: '操作已取消!'
- });
- });
- }
- })
- },
- //列表和分页相关 end ------------------------------------------------------------>
- //2.弹出框设置 start ------------------------------------------------------------>
- //2.1 打开弹出框
- openWindow() {
- this.windowStatus = true;
- this.clearToServe();
- //显示添加按钮
- this.editBtn = false;
- },
- //2.2 关闭弹出框
- closeWindow(){
- this.windowStatus = false;
- this.clearToServe();
- },
- //2.3 清理弹出框
- clearToServe(){
- this.form.label = "";
- this.form.url = "";
- this.form.icon = "";
- this.form.selected_icon = "";
- this.form.sort = "";
- this.form.pid_arr = [];
- //this.pidArrData=[];
- this.iconSrc = "";
- this.hovering = false;
- this.iconSrcSelect = "";
- this.hoveringTwo = false;
- this.editBtn = false;
- },
- //弹出框设置 end ------------------------------------------------------------>
- //3.添加菜单 start ------------------------------------------------------------>
- //3.1 上传默认图标
- beforeAvatarUpload(file) {
- const isJPG = file.type === 'image/jpeg';
- const isPNG = file.type === 'image/png';
- const isLt2M = file.size / 1024 / 1024 < 2;
- if (!isJPG && !isPNG) {
- this.$message.error('上传图片只能是 JPG 或 PNG 格式!');
- return false;
- }
- if (!isLt2M) {
- this.$message.error('上传图片大小不能超过 2MB!');
- return false;
- }
- const formData = new FormData();
- formData.append('file', file);
- this.$store.dispatch('pool/uploadFile',formData).then(res=> {
- this.iconSrc = res.data.imgUrl;//显示缩略图
- this.form.icon = res.data.imgUrl;//提供表单地址
- console.log(res.data.imgUrl)
- }).catch(() => {
- this.$message({
- type: 'info',
- message: '网络错误,请重试!'
- });
- })
- // 阻止默认的上传行为
- return false;
- },
- handleDelete() {
- // 删除图片
- this.form.icon = ''; //清空选中的图片
- this.iconSrc = ''; // 清空图片 URL
- },
- //3.2 上传选中时图标
- beforeAvatarUploadTwo(file) {
- const isJPG = file.type === 'image/jpeg';
- const isPNG = file.type === 'image/png';
- const isLt2M = file.size / 1024 / 1024 < 2;
- if (!isJPG && !isPNG) {
- this.$message.error('上传图片只能是 JPG 或 PNG 格式!');
- return false;
- }
- if (!isLt2M) {
- this.$message.error('上传图片大小不能超过 2MB!');
- return false;
- }
- const formData = new FormData();
- formData.append('file', file);
- this.$store.dispatch('pool/uploadFile',formData).then(res=> {
- this.iconSrcSelect = res.data.imgUrl;//显示缩略图
- this.form.selected_icon = res.data.imgUrl;//提供表单地址
- // 确保 Vue 能够检测到变化
- this.$forceUpdate();
- }).catch(() => {
- this.$message({
- type: 'info',
- message: '网络错误,请重试!'
- });
- })
- // 阻止默认的上传行为
- return false;
- },
- handleDeleteTwo() {
- // 删除图片
- this.form.selected_icon = ''; //清空选中的图片
- this.iconSrcSelect = ''; // 清空图片 URL
- },
- //添加菜单 end ------------------------------------------------------------>
-
- },
- mounted(){
- //1.获得初始数据
- this.getData();
- }
- }
- </script>
- <style scoped lang="less">
- .layerBoxNoBg {
- padding:30px 0 0 0;
- }
- //执行v-deep穿透scope选择器 start------------------------------------------------------------>*/
- ::v-deep .custom-form-item > .el-form-item__label {
- line-height: 140px !important;
- }
- ::v-deep .custom-textarea .el-textarea__inner {
- resize: none; /* 禁止用户拖拽调整大小 */
- }
- ::v-deep .custom-align-right .el-form-item__label {
- text-align: right; /* 设置标签文字右对齐 */
- }
- //执行v-deep穿透scope选择器 end------------------------------------------------------------>*/
- </style>
|