chenrui 4 年之前
父節點
當前提交
979a2b84ec

+ 0 - 28
src/api/dealerProductType.js

@@ -1,28 +0,0 @@
-import { axios } from '@/utils/request'
-
-//  产品类别列表  无分页
-export const dealerProductTypeQuery = (params) => {
-  const url = `/dealerProductType/query`
-  return axios({
-    url: url,
-    data: params,
-    method: 'post'
-  })
-}
-
-// 新增/编辑产品类别
-export const dealerProductTypeSave = params => {
-  return axios({
-    url: '/dealerProductType/save',
-    data: params,
-    method: 'post'
-  })
-}
-
-// 删除产品类别
-export const dealerProductTypeDel = params => {
-  return axios({
-    url: `/dealerProductType/delete/${params.id}`,
-    method: 'get'
-  })
-}

+ 86 - 0
src/api/menu.js

@@ -0,0 +1,86 @@
+import { axios } from '@/utils/request'
+
+// 获取菜单树数据
+export const getMenuList = params => {
+  const url = `/menu/findAll`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 保存
+export const saveMenu = params => {
+  const url = `/menu/save`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 删除
+export const deleteMenu = params => {
+  const url = `/menu/delete/${params.id}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}
+
+// 获取门店菜单树数据
+export const getMdMenuList = params => {
+  const url = `/mdmenu/findAll`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 门店菜单保存
+export const saveMdMenu = params => {
+  const url = `/mdmenu/save`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+// 门店菜单删除
+export const deleteMdMenu = params => {
+  const url = `/mdmenu/delete/${params.id}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}
+
+// 获取运营菜单树数据
+export const getYyMenuList = params => {
+  const url = `/yymenu/findAll`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 运营菜单保存
+export const saveYyMenu = params => {
+  const url = `/yymenu/save`
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+// 运营菜单删除
+export const deleteYyMenu = params => {
+  const url = `/yymenu/delete/${params.id}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}

+ 177 - 169
src/config/router.config.js

@@ -7,202 +7,210 @@ import {
   PageView
 } from '@/layouts'
 
-export const asyncRouterMap = [{
-  path: '/',
-  name: 'index',
-  component: BasicLayout,
-  meta: {
-    title: '首页'
-  },
-  redirect: '/home',
-  children: [{
-    path: '/home',
-    name: 'home',
-    redirect: '/home',
-    component: PageView,
-    meta: {
-      title: '首页',
-      icon: 'home'
-    },
-    hideChildrenInMenu: true,
-    children: [{
-      path: '/home',
-      name: 'home',
-      component: () => import(/* webpackChunkName: "home" */ '@/views/Home'),
-      meta: {
-        title: '首页',
-        icon: 'home',
-        hide: true
-      }
-    }
-    ]
-  },
+export const asyncRouterMap = [
   {
-    path: '/changePwd',
-    name: 'changePwd',
-    component: () => import(/* webpackChunkName: "home" */ '@/views/user/ChangePwd'),
+    path: '/',
+    name: 'index',
+    component: BasicLayout,
     meta: {
-      title: '修改密码',
-      icon: 'home'
-    },
-    hidden: true
-  },
-  // 产品管理
-  {
-    path: '/productManagement',
-    redirect: '/productManagement/productCategory',
-    component: PageView,
-    meta: {
-      title: '产品管理',
-      icon: 'shop'
-      // permission: 'M_shop'
+      title: '首页'
     },
+    redirect: '/home',
     children: [
       {
-        path: '/productManagement/productCategory',
-        redirect: '/productManagement/productCategory/list',
-        name: 'productCategory',
-        component: RouteView,
+        path: '/home',
+        name: 'home',
+        redirect: '/home',
+        component: PageView,
         meta: {
-          title: '产品类别管理',
-          icon: 'shopping'
-          // permission: 'M_goodsManage_list'
+          title: '首页',
+          icon: 'home'
         },
         hideChildrenInMenu: true,
+        children: [{
+          path: '/home',
+          name: 'home',
+          component: () => import(/* webpackChunkName: "home" */ '@/views/Home'),
+          meta: {
+            title: '首页',
+            icon: 'home',
+            hide: true
+          }
+        }]
+      },
+      {
+        path: '/changePwd',
+        name: 'changePwd',
+        component: () => import(/* webpackChunkName: "home" */ '@/views/user/ChangePwd'),
+        meta: {
+          title: '修改密码',
+          icon: 'home'
+        },
+        hidden: true
+      },
+      {
+        path: '/menusAuth',
+        redirect: '/bnSetting/menusAuth',
+        component: PageView,
+        meta: {
+          title: '菜单管理',
+          icon: 'bars',
+          permission: 'M_menusAuth_0'
+        },
         children: [
           {
-            path: '/productManagement/productCategory/list',
-            name: 'productCategoryList',
-            component: () => import(/* webpackChunkName: "shop" */ '@/views/productManagement/productCategory/list.vue'),
+            path: '/menusAuth/storeMenus',
+            name: 'storeMenus',
+            component: () => import(/* webpackChunkName: "bnSetting" */ '@/views/bnSetting/menu/storeMenus.vue'),
             meta: {
-              title: '产品类别列表',
-              icon: 'shopping',
-              hidden: true
-              // permission: 'M_goodsManage_list'
+              title: '连锁菜单管理',
+              icon: 'shop',
+              permission: 'M_menusAuth_lsMenus'
+            }
+          },
+          // {
+          //   path: '/menusAuth/adminMenus',
+          //   name: 'adminMenus',
+          //   component: () => import(/* webpackChunkName: "bnSetting" */ '@/views/bnSetting/menu/adminMenus.vue'),
+          //   meta: {
+          //     title: 'boss菜单管理',
+          //     icon: 'appstore',
+          //     // permission: 'M_menusAuth_adminMenus'
+          //   }
+          // },
+          {
+            path: '/menusAuth/menu',
+            name: 'powerMenu',
+            component: () => import(/* webpackChunkName: "auth" */ '@/views/power/menu/menu.vue'),
+            meta: {
+              title: 'IT菜单管理',
+              icon: 'profile',
+              permission: 'M_menusAuth_menu'
+            }
+          }
+        ]
+      },
+      // auth
+      {
+        path: '/auth',
+        redirect: '/auth/userList',
+        component: PageView,
+        meta: {
+          title: '权限管理',
+          icon: 'lock'
+          // permission: 'M_auth_0'
+        },
+        children: [
+          {
+            path: '/auth/userList',
+            name: 'powerUserList',
+            component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
+            meta: {
+              title: '用户管理',
+              icon: 'user'
+              // permission: 'M_auth_userList'
+            }
+          },
+          {
+            path: '/auth/roleList',
+            name: 'powerRoleList',
+            component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
+            meta: {
+              title: '角色管理',
+              icon: 'solution'
+              // permission: 'M_auth_roleList'
+            }
+          }
+        ]
+      },
+      {
+        path: '/setting',
+        redirect: '/setting/userList',
+        component: PageView,
+        meta: {
+          title: '系统设置',
+          icon: 'setting'
+          // permission: 'M_setting_0'
+        },
+        children: [
+          {
+            path: '/setting/dataDictionary',
+            name: 'powerDD',
+            component: () => import(/* webpackChunkName: "setting" */
+              '@/views/power/dataDictionary/dataDictionary.vue'),
+            meta: {
+              title: '数据字典管理',
+              icon: 'database'
+              // permission: 'M_sys_dataDictionary'
+            }
+          },
+          // {
+          //   path: '/setting/register',
+          //   name: 'powerRegister',
+          //   component: () => import(/* webpackChunkName: "setting" */ '@/views/power/register/register.vue'),
+          //   meta: {
+          //     title: '参数管理',
+          //     icon: 'key',
+          //     permission: 'M_sys_register'
+          //   }
+          // },
+          {
+            path: '/setting/OperateJournal',
+            name: 'powerOperateJournal',
+            component: () => import(/* webpackChunkName: "setting" */
+              '@/views/power/OperateJournal/OperateJournal.vue'),
+            meta: {
+              title: '操作日志',
+              icon: 'read'
+              // permission: 'M_operateJournal'
             }
           }
         ]
       }
     ]
   },
-  // auth
-  {
-    path: '/auth',
-    redirect: '/auth/userList',
-    component: PageView,
-    meta: {
-      title: '权限管理',
-      icon: 'lock',
-      permission: 'M_auth_0'
-    },
-    children: [{
-      path: '/auth/userList',
-      name: 'powerUserList',
-      component: () => import(/* webpackChunkName: "auth" */ '@/views/power/user/userList.vue'),
-      meta: {
-        title: '用户管理',
-        icon: 'user',
-        permission: 'M_auth_userList'
-      }
-    },
-    {
-      path: '/auth/roleList',
-      name: 'powerRoleList',
-      component: () => import(/* webpackChunkName: "auth" */ '@/views/power/role/roleList.vue'),
-      meta: {
-        title: '角色管理',
-        icon: 'solution',
-        permission: 'M_auth_roleList'
-      }
-    }
-    ]
-  },
   {
-    path: '/setting',
-    redirect: '/setting/userList',
-    component: PageView,
-    meta: {
-      title: '系统设置',
-      icon: 'setting',
-      permission: 'M_setting_0'
-    },
-    children: [{
-      path: '/setting/dataDictionary',
-      name: 'powerDD',
-      component: () => import(/* webpackChunkName: "setting" */
-        '@/views/power/dataDictionary/dataDictionary.vue'),
-      meta: {
-        title: '数据字典管理',
-        icon: 'database',
-        permission: 'M_sys_dataDictionary'
-      }
-    },
-    // {
-    //   path: '/setting/register',
-    //   name: 'powerRegister',
-    //   component: () => import(/* webpackChunkName: "setting" */ '@/views/power/register/register.vue'),
-    //   meta: {
-    //     title: '参数管理',
-    //     icon: 'key',
-    //     permission: 'M_sys_register'
-    //   }
-    // },
-    {
-      path: '/setting/OperateJournal',
-      name: 'powerOperateJournal',
-      component: () => import(/* webpackChunkName: "setting" */
-        '@/views/power/OperateJournal/OperateJournal.vue'),
-      meta: {
-        title: '操作日志',
-        icon: 'read',
-        permission: 'M_operateJournal'
-      }
-    }
-    ]
+    path: '*',
+    redirect: '/404',
+    hidden: true
   }
-  ]
-},
-{
-  path: '*',
-  redirect: '/404',
-  hidden: true
-}
 ]
 
 /**
  * 基础路由
  * @type { *[] }
  */
-export const constantRouterMap = [{
-  path: '/user',
-  component: UserLayout,
-  redirect: '/user/login',
-  hidden: true,
-  children: [{
-    path: 'login',
-    name: 'login',
-    component: () => import(/* webpackChunkName: "user" */ '@/views/user/Login')
-  },
-  {
-    path: 'register',
-    name: 'register',
-    component: () => import(/* webpackChunkName: "user" */ '@/views/user/Register')
-  },
+export const constantRouterMap = [
   {
-    path: 'register-result',
-    name: 'registerResult',
-    component: () => import(/* webpackChunkName: "user" */ '@/views/user/RegisterResult')
+    path: '/user',
+    component: UserLayout,
+    redirect: '/user/login',
+    hidden: true,
+    children: [
+      {
+        path: 'login',
+        name: 'login',
+        component: () => import(/* webpackChunkName: "user" */ '@/views/user/Login')
+      },
+      {
+        path: 'register',
+        name: 'register',
+        component: () => import(/* webpackChunkName: "user" */ '@/views/user/Register')
+      },
+      {
+        path: 'register-result',
+        name: 'registerResult',
+        component: () => import(/* webpackChunkName: "user" */ '@/views/user/RegisterResult')
+      },
+      {
+        path: 'recover',
+        name: 'recover',
+        component: undefined
+      }
+    ]
   },
   {
-    path: 'recover',
-    name: 'recover',
-    component: undefined
+    path: '/404',
+    component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
   }
-  ]
-},
-{
-  path: '/404',
-  component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
-}
-
 ]

+ 1 - 2
src/layouts/BasicLayout.vue

@@ -113,8 +113,7 @@ export default {
     } else {
       // 没有权限时只显示首页
       const noqx = asyncRouterMap.find((item) => item.path === '/').children
-      // this.menus = [noqx.find(item => item.path === '/home')]
-      this.menus = noqx
+      this.menus = [noqx.find(item => item.path === '/home')]
     }
     this.collapsed = !this.sidebarOpened
   },

+ 8 - 10
src/permission.js

@@ -78,16 +78,14 @@ router.beforeEach((to, from, next) => {
       }
     }
   } else {
-    console.log(111111)
-    next()
-    // // 未登录
-    // if (whiteList.includes(to.name)) {
-    //   // 在免登录白名单,直接进入
-    //   next()
-    // } else {
-    //   next({ path: '/user/login', query: { redirect: to.fullPath } })
-    //   NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
-    // }
+    // 未登录
+    if (whiteList.includes(to.name)) {
+      // 在免登录白名单,直接进入
+      next()
+    } else {
+      next({ path: '/user/login', query: { redirect: to.fullPath } })
+      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
+    }
   }
 })
 

+ 1 - 2
src/utils/request.js

@@ -38,9 +38,8 @@ const err = (error) => {
 // request interceptor
 service.interceptors.request.use(config => {
   const token = store.getters.token
-  config.headers['App-Type'] = 9 // 平台类型
   if (token) {
-    config.headers['authorization'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
+    config.headers['access-token'] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
   }
   return config
 }, err)

+ 461 - 0
src/views/bnSetting/menu/adminMenus.vue

@@ -0,0 +1,461 @@
+<template>
+  <a-card :bordered="false">
+    <a-row :gutter="24">
+      <a-button style="margin-right: 10px;" type="primary" icon="plus" @click="addChild">添加子菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: #19be6b;color: #fff;" type="" icon="plus" @click="addTitle">添加顶部菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: red;color: #fff;" type="" icon="delete" @click="delect()">删除</a-button>
+
+    </a-row>
+    <a-row :gutter="24">
+      <!-- 左侧菜单树列表 -->
+      <a-col :span="8">
+        <a-row :gutter="24" class="textCount">
+          <a-icon type="info-circle" style="color: #1890FF;margin-right: 10px;" />
+          <span>当前选择:<span style="color: #40a9ff;font-weight: 600;">{{ selectedMenu }}</span><span v-if="selectedKeys.length" class="imgSize" @click="cancelSel">取消选择</span></span>
+        </a-row>
+
+        <a-row :gutter="24" >
+          <a-input-search placeholder="输入搜索菜单名搜索" style="width: 100%" @change="onChange" />
+          <a-tree
+            @expand="onExpand"
+            :treeData="getMenus"
+            :expandedKeys="expandedKeys"
+            :autoExpandParent="autoExpandParent"
+            @select="onSelect"
+            :selectedKeys="selectedKeys"
+            showIcon
+          >
+            <template slot="title" slot-scope="{title}">
+              <span v-if="title.indexOf(searchValue) > -1">
+                {{ title.substr(0, title.indexOf(searchValue)) }}
+                <span style="color: #f50">{{ searchValue }}</span>
+                {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
+              </span>
+              <span v-else>{{ title }}</span>
+            </template>
+            <a-icon slot="file" type="file" />
+            <a-icon slot="pushpin" type="pushpin" />
+          </a-tree>
+        </a-row>
+      </a-col>
+      <!-- 右侧 -->
+      <a-col :span="16" >
+        <a-form :form="form" @submit="handleSubmit">
+          <!-- 类型 -->
+          <a-form-item label="类型" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <div v-if="!formData.type||formData.type=='0'">
+              <a-icon type="file" style="margin-right: 10px;" /><span >页面菜单</span>
+            </div>
+            <div v-if="formData.type=='1'">
+              <a-icon type="pushpin" style="margin-right: 10px;" /><span >操作按钮</span>
+            </div>
+          </a-form-item>
+
+          <!-- 名称 -->
+          <a-form-item label="名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入名称(最多30个字符)"
+              v-decorator="['formData.name', {
+                initialValue: formData.name,
+                getValueFromEvent: $filterEmpty,
+                rules: [{ required: true, message: '请输入名称!' }] }]"
+            />
+          </a-form-item>
+          <!-- 路由英文名 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路由英文名"
+              v-decorator="['formData.routeName', {
+                initialValue: formData.routeName,
+                rules: [{ required: true, message: '请输入路由英文名!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 路径 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路径"
+              v-decorator="['formData.routePath', {
+                initialValue: formData.routePath,
+                rules: [{ required: true, message: '请输入路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 请求路径 -->
+          <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入请求路径"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [{ required: true, message: '请输入请求路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端权限编码 -->
+          <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端权限编码"
+              v-decorator="[
+                'formData.code',
+                {
+                  initialValue: formData.code,
+                  rules: [{ required: true, message: '请输入前端权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 后台权限编码 -->
+          <a-form-item label="后台权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入后台权限编码"
+              v-decorator="[
+                'formData.permission',
+                {
+                  initialValue: formData.permission,
+                  rules: [{ required: formData.isLeaf, message: '请输入后台权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 图标 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0' " label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入图标名称"
+              v-decorator="['formData.icon', {
+                initialValue: formData.icon,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端组件 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端组件路径"
+              v-decorator="['formData.componentPath', {
+                initialValue: formData.componentPath,
+                rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 第三方链接 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入第三方链接地址"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 排序值 -->
+          <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input-number
+              style="width: 100%;"
+              type="number"
+              placeholder="请输入排序值(0~999999)"
+              v-decorator="['formData.sort', {
+                initialValue: formData.sort,
+                rules: [] }]"
+              :max="999999"
+              :min="0"
+            />
+          </a-form-item>
+          <!-- 状态 -->
+          <a-form-item label="启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-radio-group
+              name="radioGroup"
+              v-decorator="[
+                'formData.status',
+                {
+                  initialValue: formData.status,
+                  rules: [{ required: true, message: '请选择状态!' }] },
+              ]"
+            >
+              <a-radio :value="1">是</a-radio>
+              <a-radio :value="0">否</a-radio>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+            <a-button type="primary" @click="handleSubmit()">
+              保存
+            </a-button>
+            <a-button :style="{ marginLeft: '8px' }" @click="clear">
+              重置
+            </a-button>
+          </a-form-item>
+        </a-form>
+
+      </a-col>
+    </a-row>
+    <childModal parentType="admin" :visible="showChildModal" @refresh="getYyMenuList" :data="parentData" @close="showChildModal = false"></childModal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import childModal from './childModal.vue'
+import { getYyMenuList, saveYyMenu, deleteYyMenu } from '@/api/menu.js'
+
+export default {
+  name: 'Menu',
+  components: {
+    STable, VSelect, childModal
+  },
+  props: {},
+  data () {
+    return {
+      treeData: [],
+      dataList: [],
+      searchValue: '',
+      expandedKeys: [],
+      autoExpandParent: true,
+      selectedKeys: [],
+      selectedMenu: '', // 选择的树节点名
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'menu' }),
+      showChildModal: false,
+      parentData: {}, // 父级菜单
+      formData: {
+        id: '',
+        name: '',
+        routePath: '',
+        icon: '',
+        routeName: '',
+        componentPath: '',
+        urlPath: '',
+        code: '',
+        permission: '',
+        sort: '',
+        type: '0',
+        isLeaf: true,
+        status: '' // 活动状态
+      }
+    }
+  },
+  computed: {
+    getMenus () {
+      this.generateList(this.treeData)
+      return this.treeData
+    }
+  },
+  methods: {
+    onExpand (expandedKeys) {
+      // console.log('onExpand', expandedKeys)
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+
+    onSelect (selectedKeys, info) {
+      console.log('onSelect', info)
+      this.selectedKeys = selectedKeys
+      if (info.selected) {
+        const data = info.selectedNodes[0].data.props
+        const isLeaf = data.dataRef.children
+        // this.formData = Object.assign({}, this.formData, info.selectedNodes[0].data.props)
+        this.formData = {
+          id: data.id,
+          name: data.name,
+          routePath: data.routePath,
+          icon: data.icon,
+          routeName: data.routeName,
+          componentPath: data.componentPath,
+          urlPath: data.urlPath,
+          code: data.code,
+          permission: data.permission,
+          sort: data.sort,
+          type: data.type,
+          status: data.status,
+          isLeaf: !(isLeaf && isLeaf.length)
+        }
+
+        this.selectedMenu = this.formData.name
+        this.formData.status = Number(this.formData.status)
+      } else {
+        this.selectedMenu = ''
+        this.clear()
+      }
+    },
+    generateList (data) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        const key = node.title
+        this.dataList.push({ key, title: key })
+        node.scopedSlots = { title: 'title' }
+        node.slots = { icon: node.type == '0' ? 'file' : 'pushpin' }
+
+        if (node.children) {
+          this.generateList(node.children)
+        }
+      }
+    },
+    getParentKey (key, tree) {
+      let parentKey
+      for (let i = 0; i < tree.length; i++) {
+        const node = tree[i]
+        if (node.children) {
+          if (node.children.some(item => item.title == key)) {
+            parentKey = node.key
+          } else if (this.getParentKey(key, node.children)) {
+            parentKey = this.getParentKey(key, node.children)
+          }
+        }
+      }
+      return parentKey
+    },
+    onChange (e) {
+      const value = e.target.value
+      const expandedKeys = this.dataList
+        .map(item => {
+          if (item.title.indexOf(value) > -1) {
+            return this.getParentKey(item.title, this.treeData)
+          }
+          return null
+        })
+        .filter((item, i, self) => item && self.indexOf(item) === i)
+      Object.assign(this, {
+        expandedKeys,
+        searchValue: value,
+        autoExpandParent: true
+      })
+    },
+    // 获取菜单树列表
+    getYyMenuList () {
+      getYyMenuList().then(res => {
+        console.log(res, 'res1111111')
+        if (res.status == 200) {
+          this.treeData = res.data
+          console.log(this.treeData, 'this.treeData')
+        }
+      })
+    },
+    // 添加子节点
+    addChild () {
+      if (!this.selectedMenu) {
+        return this.$message.warning('请先选择一个父级菜单')
+      } else if (this.formData.type == '1') {
+        return this.$message.warning('请选择一个页面级菜单')
+      }
+      this.showChildModal = true
+      this.parentData = this.formData
+    },
+    // 添加顶部菜单
+    addTitle () {
+      this.showChildModal = true
+      this.parentData = {}
+    },
+
+    //  取消选择
+    cancelSel () {
+      this.selectedKeys = []
+      this.selectedMenu = ''
+      this.clear()
+    },
+    // 清空列表
+    clear () {
+      this.form.resetFields()
+      this.formData.id = ''
+      this.formData.name = ''
+      this.formData.routePath = ''
+      this.formData.icon = ''
+      this.formData.routeName = ''
+      this.formData.componentPath = ''
+      this.formData.urlPath = ''
+      this.formData.sort = ''
+      this.formData.type = ''
+      this.formData.status = ''
+      this.formData.code = ''
+      this.formData.permission = ''
+      this.formData.isLeaf = true
+    },
+
+    // 删除数据
+    delect () {
+      if (!this.selectedKeys.length) {
+        return this.$message.warning('您还未选择要删除的数据')
+      }
+      const _this = this
+      console.log(_this.formData.id, '_this.formData.id')
+      this.$confirm({
+        title: '警告',
+        content: `确定要删除您选择的 ${_this.formData.name} 的数据吗?`,
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          deleteYyMenu({
+            id: _this.formData.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success('删除成功')
+              _this.getYyMenuList()
+            }
+          }).catch(() => {
+            _this.$message.success('删除失败, 请稍后重试')
+          })
+        }
+      })
+    },
+
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          console.log(values.formData, ' formData.type222222222')
+          saveYyMenu(Object.assign({ id: this.formData.id }, values.formData)).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              _this.getYyMenuList()
+              _this.clear()
+            } else {
+              // this.$message.warning(res.message)
+            }
+          })
+        }
+      })
+    },
+    handleCancel () {
+      this.clear()
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'menu' })
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getYyMenuList()
+    })
+  },
+  watch: {
+
+  }
+}
+</script>
+
+<style>
+  .menu-box::-webkit-scrollbar{
+    width: 6px;
+    height: 6px ;
+  }
+
+  .menu-box::-webkit-scrollbar-thumb{
+    width: 6px;
+    height: 6px ;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 0 2px #d1d1d1;
+    background: #e4e4e4;
+  }
+
+  .textCount{
+    border: 1px solid #91d5ff;
+    background-color: #e6f7ff;
+    border-radius: 5px;
+    padding: 5px 10px 5px 20px;
+    margin: 10px 0;
+    color: rgba(0, 0, 0, 0.85);
+  }
+  .imgSize{
+    color: #2d8cf0;
+    margin-left: 10px;
+    font-size: 14px;
+  }
+
+</style>

+ 346 - 0
src/views/bnSetting/menu/childModal.vue

@@ -0,0 +1,346 @@
+<template>
+  <div>
+    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+      <a-form :form="form" @submit="handleSubmit">
+        <!-- 上级菜单 -->
+        <a-form-item label="上级菜单" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <div >
+            <span >{{ parentTitle }}</span>
+          </div>
+
+        </a-form-item>
+        <!-- 类型 -->
+        <a-form-item label="类型" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-select
+            @change="selectChange"
+            :disabled="disabled"
+            v-decorator="[
+              'formData.type',
+              {
+                initialValue: formData.type,
+                rules: [{ required: true, message: '请选择状态!' }] },
+            ]"
+            style="width: 100%"
+            placeholder="请选择菜单类型"
+          >
+            <a-select-option :value="0">页面类型</a-select-option>
+            <a-select-option :value="1">按钮类型</a-select-option>
+          </a-select>
+        </a-form-item>
+
+        <!-- 名称 -->
+        <a-form-item label="名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入名称(最多30个字符)"
+            :maxLength="30"
+            v-decorator="['formData.name', {
+              initialValue: formData.name,
+              getValueFromEvent: $filterEmpty,
+              rules: [{ required: true, message: '请输入名称!' }] }]"
+          />
+        </a-form-item>
+        <!-- 路由英文名 -->
+        <!-- <a-form-item v-if="!formData.type" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入路由英文名"
+            v-decorator="['formData.routeName', {
+              initialValue: formData.routeName,
+              rules: [{ required: true, message: '请输入路由英文名!' }] }]"
+          />
+        </a-form-item> -->
+        <!-- 路径 -->
+        <!-- <a-form-item v-if="!formData.type" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+             <a-input placeholder="请输入路径"
+                      v-decorator="['formData.routePath', {
+                        initialValue: formData.routePath,
+                        rules: [{ required: true, message: '请输入路径!' }] }]"
+             />
+           </a-form-item> -->
+        <!-- 请求路径 -->
+        <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+             <a-input placeholder="请输入请求路径"
+                      v-decorator="['formData.urlPath', {
+                        initialValue: formData.urlPath,
+                        rules: [{ required: true, message: '请输入请求路径!' }] }]"
+             />
+           </a-form-item> -->
+        <!-- 前端权限编码 -->
+        <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入前端权限编码"
+            v-decorator="[
+              'formData.code',
+              {
+                initialValue: formData.code,
+                rules: [{ required: true, message: '请输入前端权限编码!' }] },
+            ]"
+          />
+
+        </a-form-item>
+        <!-- 后台权限编码 -->
+        <a-form-item label="后台权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入后台权限编码"
+            v-decorator="[
+              'formData.permission',
+              {initialValue: formData.permission},
+            ]"
+          />
+
+        </a-form-item>
+
+        <!-- 图标 -->
+        <!-- <a-form-item v-if="!formData.type" label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入图标名称"
+            v-decorator="['formData.icon', {
+              initialValue: formData.icon,
+              rules: [] }]"
+          />
+        </a-form-item> -->
+        <!-- 前端组件 -->
+        <!-- <a-form-item v-if="!formData.type" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入前端组件路径"
+            v-decorator="['formData.componentPath', {
+              initialValue: formData.componentPath,
+              rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
+          />
+        </a-form-item> -->
+
+        <!-- 第三方链接 -->
+        <!-- <a-form-item v-if="!formData.type" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入第三方链接地址"
+            v-decorator="['formData.urlPath', {
+              initialValue: formData.urlPath,
+              rules: [] }]"
+          />
+        </a-form-item> -->
+
+        <!-- 排序值 -->
+        <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input-number
+            style="width: 100%;"
+            type="number"
+            placeholder="请输入排序值(0~999999)"
+            v-decorator="['formData.sort', {
+              initialValue: formData.sort,
+              rules: [] }]"
+            :max="999999"
+            :min="0"
+          />
+        </a-form-item>
+        <!-- 连锁可用 -->
+        <a-form-item v-if="parentType=='store'" label="连锁可用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-radio-group
+            name="radioGroup"
+            v-decorator="[
+              'formData.chainOrgUse',
+              {
+                initialValue: formData.chainOrgUse,
+                rules: [{ required: true, message: '请选择!' }] },
+            ]"
+          >
+            <a-radio :value="1">是</a-radio>
+            <a-radio :value="0">否</a-radio>
+          </a-radio-group>
+        </a-form-item>
+        <!-- 单店可用 -->
+        <a-form-item v-if="parentType=='store'" label="单店可用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-radio-group
+            name="radioGroup"
+            v-decorator="[
+              'formData.singleOrgUse',
+              {
+                initialValue: formData.singleOrgUse,
+                rules: [{ required: true, message: '请选择!' }] },
+            ]"
+          >
+            <a-radio :value="1">是</a-radio>
+            <a-radio :value="0">否</a-radio>
+          </a-radio-group>
+        </a-form-item>
+        <!-- 状态 -->
+        <a-form-item label="启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-radio-group
+            name="radioGroup"
+            v-decorator="[
+              'formData.status',
+              {
+                initialValue: formData.status,
+                rules: [{ required: true, message: '请选择状态!' }] },
+            ]"
+          >
+            <a-radio :value="1">是</a-radio>
+            <a-radio :value="0">否</a-radio>
+          </a-radio-group>
+        </a-form-item>
+
+        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+          <a-button type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { saveYyMenu, saveMdMenu } from '@/api/menu.js'
+export default {
+  name: 'ChildModal',
+  components: {
+    STable, VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    parentType: {
+      type: String,
+      default: ''
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible,
+      titleText: '',
+      disabled: false,
+      parentTitle: '',
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'childModal' }),
+      formData: {
+        parentId: '',
+        name: '',
+        routePath: '',
+        icon: '',
+        routeName: '',
+        code: '',
+        permission: '',
+        componentPath: '',
+        urlPath: '',
+        sort: '',
+        type: undefined,
+        chainOrgUse: 1,
+        singleOrgUse: 1,
+        status: 1 // 活动状态
+      }
+    }
+  },
+  methods: {
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+
+    selectChange (val) {
+      this.formData.type = val
+      console.log(val)
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          console.log(values.formData, ' formData.type222222222')
+          const saveRequest = this.parentType == 'store' ? saveMdMenu : saveYyMenu
+          saveRequest(Object.assign(this.formData, values.formData)).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+      this.parentTitle = ''
+      this.formData.parentId = ''
+      this.formData.name = ''
+      this.formData.routePath = ''
+      this.formData.icon = ''
+      this.formData.routeName = ''
+      this.formData.componentPath = ''
+      this.formData.urlPath = ''
+      this.formData.sort = ''
+      this.formData.type = ''
+      this.formData.status = 1
+      this.formData.chainOrgUse = 1
+      this.formData.singleOrgUse = 1
+      this.formData.code = ''
+      this.formData.permission = ''
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'childModal' })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        if (this.data.id) { // 添加子菜单
+          this.titleText = '添加子菜单'
+          this.disabled = false
+          console.log(this.data, 'this.data')
+          this.formData.parentId = this.data.id
+          this.parentTitle = this.data.name
+        } else { // 添加顶菜单
+          this.titleText = '添加顶菜单'
+          this.formData.type = 0
+          this.disabled = true
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style >
+  .modalBox{
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+</style>

+ 498 - 0
src/views/bnSetting/menu/storeMenus.vue

@@ -0,0 +1,498 @@
+<template>
+  <a-card :bordered="false">
+    <a-row :gutter="24">
+      <a-button style="margin-right: 10px;" type="primary" icon="plus" @click="addChild">添加子菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: #19be6b;color: #fff;" type="" icon="plus" @click="addTitle">添加顶部菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: red;color: #fff;" type="" icon="delete" @click="delect()">删除</a-button>
+
+    </a-row>
+    <a-row :gutter="24">
+      <!-- 左侧菜单树列表 -->
+      <a-col :span="8">
+        <a-row :gutter="24" class="textCount">
+          <a-icon type="info-circle" style="color: #1890FF;margin-right: 10px;" />
+          <span>当前选择:<span style="color: #40a9ff;font-weight: 600;">{{ selectedMenu }}</span><span v-if="selectedKeys.length" class="imgSize" @click="cancelSel">取消选择</span></span>
+        </a-row>
+
+        <a-row :gutter="24" >
+          <a-input-search placeholder="输入搜索菜单名搜索" style="width: 100%" @change="onChange" />
+          <a-tree
+            @expand="onExpand"
+            :treeData="getMenus"
+            :expandedKeys="expandedKeys"
+            :autoExpandParent="autoExpandParent"
+            @select="onSelect"
+            :selectedKeys="selectedKeys"
+            showIcon
+          >
+            <template slot="title" slot-scope="{title}">
+              <span v-if="title.indexOf(searchValue) > -1">
+                {{ title.substr(0, title.indexOf(searchValue)) }}
+                <span style="color: #f50">{{ searchValue }}</span>
+                {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
+              </span>
+              <span v-else>{{ title }}</span>
+            </template>
+            <a-icon slot="file" type="file" />
+            <a-icon slot="pushpin" type="pushpin" />
+          </a-tree>
+        </a-row>
+      </a-col>
+      <!-- 右侧 -->
+      <a-col :span="16" >
+        <a-form :form="form" @submit="handleSubmit">
+          <!-- 类型 -->
+          <a-form-item label="类型" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <div v-if="!formData.type||formData.type=='0'">
+              <a-icon type="file" style="margin-right: 10px;" /><span >页面菜单</span>
+            </div>
+            <div v-if="formData.type=='1'">
+              <a-icon type="pushpin" style="margin-right: 10px;" /><span >操作按钮</span>
+            </div>
+          </a-form-item>
+
+          <!-- 名称 -->
+          <a-form-item label="名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入名称(最多30个字符)"
+              :maxLength="30"
+              v-decorator="['formData.name', {
+                initialValue: formData.name,
+                getValueFromEvent: $filterEmpty,
+                rules: [{ required: true, message: '请输入名称!' }] }]"
+            />
+          </a-form-item>
+          <!-- 路由英文名 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路由英文名"
+              v-decorator="['formData.routeName', {
+                initialValue: formData.routeName,
+                rules: [{ required: true, message: '请输入路由英文名!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 路径 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路径"
+              v-decorator="['formData.routePath', {
+                initialValue: formData.routePath,
+                rules: [{ required: true, message: '请输入路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 请求路径 -->
+          <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入请求路径"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [{ required: true, message: '请输入请求路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端权限编码 -->
+          <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端权限编码"
+              v-decorator="[
+                'formData.code',
+                {
+                  initialValue: formData.code,
+                  rules: [{ required: true, message: '请输入前端权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 后台权限编码 -->
+          <a-form-item label="后台权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入后台权限编码"
+              v-decorator="[
+                'formData.permission',
+                {
+                  initialValue: formData.permission,
+                  rules: [{ required: formData.isLeaf, message: '请输入后台权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 图标 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0' " label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入图标名称"
+              v-decorator="['formData.icon', {
+                initialValue: formData.icon,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端组件 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端组件路径"
+              v-decorator="['formData.componentPath', {
+                initialValue: formData.componentPath,
+                rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 第三方链接 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入第三方链接地址"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 排序值 -->
+          <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input-number
+              style="width: 100%;"
+              placeholder="请输入排序值(0~999999)"
+              v-decorator="['formData.sort', {
+                initialValue: formData.sort,
+                rules: [] }]"
+              :max="999999"
+              :min="0"
+            />
+          </a-form-item>
+          <!-- 连锁可用 -->
+          <a-form-item label="连锁可用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-radio-group
+              name="radioGroup"
+              v-decorator="[
+                'formData.chainOrgUse',
+                {
+                  initialValue: formData.chainOrgUse,
+                  rules: [{ required: true, message: '请选择!' }] },
+              ]"
+            >
+              <a-radio :value="1">是</a-radio>
+              <a-radio :value="0">否</a-radio>
+            </a-radio-group>
+          </a-form-item>
+          <!-- 单店可用 -->
+          <a-form-item label="单店可用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-radio-group
+              name="radioGroup"
+              v-decorator="[
+                'formData.singleOrgUse',
+                {
+                  initialValue: formData.singleOrgUse,
+                  rules: [{ required: true, message: '请选择!' }] },
+              ]"
+            >
+              <a-radio :value="1">是</a-radio>
+              <a-radio :value="0">否</a-radio>
+            </a-radio-group>
+          </a-form-item>
+          <!-- 状态 -->
+          <a-form-item label="启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-radio-group
+              name="radioGroup"
+              v-decorator="[
+                'formData.status',
+                {
+                  initialValue: formData.status,
+                  rules: [{ required: true, message: '请选择状态!' }] },
+              ]"
+            >
+              <a-radio :value="1">是</a-radio>
+              <a-radio :value="0">否</a-radio>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+            <a-button type="primary" @click="handleSubmit()">
+              保存
+            </a-button>
+            <a-button :style="{ marginLeft: '8px' }" @click="clear">
+              重置
+            </a-button>
+          </a-form-item>
+        </a-form>
+
+      </a-col>
+    </a-row>
+    <childModal parentType="store" :visible="showChildModal" @refresh="getMdMenuList" :data="parentData" @close="showChildModal = false"></childModal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import childModal from './childModal.vue'
+import { getMdMenuList, saveMdMenu, deleteMdMenu } from '@/api/menu.js'
+
+export default {
+  name: 'Menu',
+  components: {
+    STable, VSelect, childModal
+  },
+  props: {},
+  data () {
+    return {
+      treeData: [],
+      dataList: [],
+      searchValue: '',
+      expandedKeys: [],
+      autoExpandParent: true,
+      selectedKeys: [],
+      selectedMenu: '', // 选择的树节点名
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'menu' }),
+      showChildModal: false,
+      parentData: {}, // 父级菜单
+      formData: {
+        id: '',
+        name: '',
+        routePath: '',
+        icon: '',
+        routeName: '',
+        componentPath: '',
+        urlPath: '',
+        code: '',
+        permission: '',
+        sort: '',
+        type: '0',
+        isLeaf: true,
+        chainOrgUse: '',
+        singleOrgUse: '',
+        status: '' // 活动状态
+      }
+    }
+  },
+  computed: {
+    getMenus () {
+      this.generateList(this.treeData)
+      return this.treeData
+    }
+  },
+  methods: {
+    onExpand (expandedKeys) {
+      // console.log('onExpand', expandedKeys)
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+
+    onSelect (selectedKeys, info) {
+      console.log('onSelect', info)
+      this.selectedKeys = selectedKeys
+      if (info.selected) {
+        const data = info.selectedNodes[0].data.props
+        const isLeaf = data.dataRef.children
+        // this.formData = Object.assign({}, this.formData, info.selectedNodes[0].data.props)
+        this.formData = {
+          id: data.id,
+          name: data.name,
+          routePath: data.routePath,
+          icon: data.icon,
+          routeName: data.routeName,
+          componentPath: data.componentPath,
+          urlPath: data.urlPath,
+          code: data.code,
+          permission: data.permission,
+          sort: data.sort,
+          type: data.type,
+          chainOrgUse: data.chainOrgUse,
+          singleOrgUse: data.singleOrgUse,
+          status: data.status,
+          isLeaf: !(isLeaf && isLeaf.length)
+        }
+
+        this.selectedMenu = this.formData.name
+        this.formData.status = Number(this.formData.status)
+        this.formData.chainOrgUse = Number(this.formData.chainOrgUse)
+        this.formData.singleOrgUse = Number(this.formData.singleOrgUse)
+      } else {
+        this.selectedMenu = ''
+        this.clear()
+      }
+    },
+    generateList (data) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        const key = node.title
+        this.dataList.push({ key, title: key })
+        node.scopedSlots = { title: 'title' }
+        node.slots = { icon: node.type == '0' ? 'file' : 'pushpin' }
+
+        if (node.children) {
+          this.generateList(node.children)
+        }
+      }
+    },
+    getParentKey (key, tree) {
+      let parentKey
+      for (let i = 0; i < tree.length; i++) {
+        const node = tree[i]
+        if (node.children) {
+          if (node.children.some(item => item.title == key)) {
+            parentKey = node.key
+          } else if (this.getParentKey(key, node.children)) {
+            parentKey = this.getParentKey(key, node.children)
+          }
+        }
+      }
+      return parentKey
+    },
+    onChange (e) {
+      const value = e.target.value
+      const expandedKeys = this.dataList
+        .map(item => {
+          if (item.title.indexOf(value) > -1) {
+            return this.getParentKey(item.title, this.treeData)
+          }
+          return null
+        })
+        .filter((item, i, self) => item && self.indexOf(item) === i)
+      Object.assign(this, {
+        expandedKeys,
+        searchValue: value,
+        autoExpandParent: true
+      })
+    },
+    // 获取菜单树列表
+    getMdMenuList () {
+      getMdMenuList().then(res => {
+        console.log(res, 'res1111111')
+        if (res.status == 200) {
+          this.treeData = res.data
+          console.log(this.treeData, 'this.treeData')
+        }
+      })
+    },
+    // 添加子节点
+    addChild () {
+      if (!this.selectedMenu) {
+        return this.$message.warning('请先选择一个父级菜单')
+      } else if (this.formData.type == '1') {
+        return this.$message.warning('请选择一个页面级菜单')
+      }
+      this.showChildModal = true
+      this.parentData = this.formData
+    },
+    // 添加顶部菜单
+    addTitle () {
+      this.showChildModal = true
+      this.parentData = {}
+    },
+    //  取消选择
+    cancelSel () {
+      this.selectedKeys = []
+      this.selectedMenu = ''
+      this.clear()
+    },
+    // 清空列表
+    clear () {
+      this.form.resetFields()
+      this.formData.id = ''
+      this.formData.name = ''
+      this.formData.routePath = ''
+      this.formData.icon = ''
+      this.formData.routeName = ''
+      this.formData.componentPath = ''
+      this.formData.urlPath = ''
+      this.formData.sort = ''
+      this.formData.type = ''
+	    this.formData.chainOrgUse = ''
+	    this.formData.singleOrgUse = ''
+      this.formData.status = ''
+      this.formData.code = ''
+      this.formData.permission = ''
+      this.formData.isLeaf = true
+    },
+
+    // 删除数据
+    delect () {
+      if (!this.selectedKeys.length) {
+        return this.$message.warning('您还未选择要删除的数据')
+      }
+      const _this = this
+      console.log(_this.formData.id, '_this.formData.id')
+      this.$confirm({
+        title: '警告',
+        content: `确定要删除您选择的 ${_this.formData.name} 的数据吗?`,
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          deleteMdMenu({
+            id: _this.formData.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success('删除成功')
+              _this.getMdMenuList()
+            }
+          }).catch(() => {
+            _this.$message.success('删除失败, 请稍后重试')
+          })
+        }
+      })
+    },
+
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          console.log(values.formData, ' formData.type222222222')
+          saveMdMenu(Object.assign({ id: this.formData.id }, values.formData)).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              _this.getMdMenuList()
+              _this.clear()
+            } else {
+              // this.$message.warning(res.message)
+            }
+          })
+        }
+      })
+    },
+    handleCancel () {
+      this.clear()
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'menu' })
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getMdMenuList()
+    })
+  },
+  watch: {
+
+  }
+}
+</script>
+
+<style>
+  .menu-box::-webkit-scrollbar{
+    width: 6px;
+    height: 6px ;
+  }
+
+  .menu-box::-webkit-scrollbar-thumb{
+    width: 6px;
+    height: 6px ;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 0 2px #d1d1d1;
+    background: #e4e4e4;
+  }
+
+  .textCount{
+    border: 1px solid #91d5ff;
+    background-color: #e6f7ff;
+    border-radius: 5px;
+    padding: 5px 10px 5px 20px;
+    margin: 10px 0;
+    color: rgba(0, 0, 0, 0.85);
+  }
+  .imgSize{
+    color: #2d8cf0;
+    margin-left: 10px;
+    font-size: 14px;
+  }
+
+</style>

+ 162 - 0
src/views/bnSetting/menusAuth.vue

@@ -0,0 +1,162 @@
+<template>
+  <div>
+    <a-form class="form-box" style="height: 500px;overflow: auto;margin-bottom: 15px;" :form="form" @submit="handleSubmit">
+      <a-tree
+        checkable
+        @check="onCheck"
+        @expand="onExpand"
+        :autoExpandParent="autoExpandParent"
+        v-model="checkedKeys"
+        :treeData="treeData"
+      />
+    </a-form>
+    <a-form-item :wrapper-col="{ offset: 3 }">
+      <a-button type="primary" @click="handleSubmit()">
+        保存
+      </a-button>
+    </a-form-item>
+  </div>
+</template>
+
+<script>
+import { findLsMenu, saveLsMouldMenu, findDdMenu, saveDdMouldMenu } from '@/api/menuSet'
+export default {
+  name: 'MenusAuth',
+  props: {
+    types: {
+      type: String,
+      default: 'dd'
+    }
+  },
+  data () {
+    return {
+      menuIds: '',
+      treeData: [],
+      expandedKeys: [],
+      autoExpandParent: false,
+      checkedKeys: [],
+      checkedData: [],
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'menuModal' })
+    }
+  },
+  methods: {
+    tabChange (v) {
+      console.log(v)
+    },
+    // 初始化树
+    treeInit (dr) {
+      this.treeData = dr.menuList
+      this.menuIds = dr.mould.menuIds
+      if (this.menuIds) {
+        const arr = this.menuIds.split(',')
+        const temp = []
+        arr.map(item => {
+          temp.push(Number(item))
+        })
+        this.checkedData = temp
+        this.expandedKeys = temp
+        // 找出叶子节点
+        this.findLeaf(this.treeData, temp)
+      }
+    },
+    // 获取连锁树数据
+    getfindLsMenu () {
+      findLsMenu().then(res => {
+        console.log(res, '+++++++++连锁+++++++++')
+        if (res.status == 200) {
+          this.treeInit(res.data)
+        }
+      })
+    },
+    // 获取单店树数据
+    getfindDdMenu () {
+      findDdMenu().then(res => {
+        console.log(res, '+++++++++单店+++++++++')
+        if (res.status == 200) {
+          this.treeInit(res.data)
+        }
+      })
+    },
+    onExpand (expandedKeys) {
+      console.log('onExpand', expandedKeys)
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+    onCheck (checkedKeys, info) {
+      this.checkedData = [...checkedKeys, ...info.halfCheckedKeys]
+      this.checkedKeys = checkedKeys
+    },
+    // 勾选已选的菜单
+    findLeaf (data, arr) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        if (node.children) {
+          this.findLeaf(node.children, arr)
+        } else {
+          const hasNode = arr.find(item => {
+            return item == node.id
+          })
+          if (hasNode) {
+            this.checkedKeys.push(node.id)
+          }
+        }
+      }
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          // console.log(this.checkedData)
+          if (this.checkedData.length == 0) {
+            return this.$message.warning('请先选择菜单')
+          }
+          const arr = this.checkedData.join(',')
+          if (this.types == 'dd') {
+            this.ddSave({ menuIds: arr })
+          } else {
+            this.lsSave({ menuIds: arr })
+          }
+        }
+      })
+    },
+    // 保存单店
+    ddSave (pars) {
+      saveDdMouldMenu(pars).then(res => {
+        console.log(res, 'res--save')
+        if (res.status + '' === '200') {
+          this.$message.success(res.message ? res.message : '保存成功')
+        } else {
+          // this.$message.warning(res.message)
+        }
+      })
+    },
+    // 保存连锁
+    lsSave (pars) {
+      saveLsMouldMenu(pars).then(res => {
+        console.log(res, 'res--save')
+        if (res.status + '' === '200') {
+          this.$message.success(res.message ? res.message : '保存成功')
+        } else {
+          // this.$message.warning(res.message)
+        }
+      })
+    }
+  },
+  mounted () {
+    // 单店
+    if (this.types == 'dd') {
+      this.getfindDdMenu()
+    } else {
+      this.getfindLsMenu()
+    }
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'menu' })
+  }
+}
+</script>
+
+<style>
+</style>

+ 41 - 0
src/views/bnSetting/menusAuthTab.vue

@@ -0,0 +1,41 @@
+<template>
+  <div class="menusAuth-cons">
+    <a-tabs @change="tabChange" type="card">
+      <a-tab-pane tab="单店菜单设置" key="1">
+        <menusAuth types="dd"></menusAuth>
+      </a-tab-pane>
+      <a-tab-pane tab="连锁店菜单设置" key="2">
+        <menusAuth types="ls"></menusAuth>
+      </a-tab-pane>
+    </a-tabs>
+  </div>
+</template>
+
+<script>
+  import menusAuth from './menusAuth.vue'
+  export default {
+    name: 'menusAuthTab',
+    components: {
+      menusAuth
+    },
+    data() {
+      return {}
+    },
+    methods: {
+      tabChange(v) {
+        console.log(v)
+      },
+    },
+    beforeRouteEnter (to, from, next) {
+      next(vm => {
+      })
+    },
+  }
+</script>
+
+<style>
+  .menusAuth-cons{
+    background: #fff;
+    padding: 10px;
+  }
+</style>

+ 423 - 0
src/views/power/job/jobs.vue

@@ -0,0 +1,423 @@
+<template>
+  <a-card class="settlement" :bordered="false">
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline">
+        <a-row :gutter="20">
+          <a-col :md="6" :sm="24">
+            <a-form-item style="margin-bottom: 0;">
+              <a-input v-model.trim="queryParam.name" placeholder="定时器名称" allowClear/>
+            </a-form-item>
+          </a-col>
+          <a-col :md="4" :sm="24">
+            <a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+    <a-divider />
+    <div class="btns">
+      <a-button @click="addJob()" type="primary" icon="plus-circle">添加JOB</a-button>
+      <a-button @click="startJob()" type="default" icon="play-circle">启动</a-button>
+      <a-button @click="stopJob()" type="default" icon="stop">停止</a-button>
+    </div>
+
+    <s-table
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :bordered="true"
+      :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+    >
+      <span slot="action" slot-scope="text, record">
+        <template>
+          <a @click="editJob(record)">编辑</a>
+          <a-divider type="vertical" />
+          <a @click="deleteRow(record)">删除</a>
+          <a-divider type="vertical" />
+          <a @click="syncJob(record)">立即运行一次</a>
+        </template>
+      </span>
+      <span slot="isEnable" slot-scope="text, record">
+        {{ record.isEnable ? '启用' : '禁用' }}
+      </span>
+      <div slot="status" slot-scope="text, record">
+        <span v-if="record.status === 'STAT'" style="color:green">运行中</span>
+        <span v-if="record.status !== 'STAT'" style="color:red">已停止</span>
+      </div>
+    </s-table>
+
+    <a-modal
+      title="添加JOB"
+      v-model="visible"
+      :footer="null"
+      :maskClosable="false"
+      @cancel="handleCancel"
+    >
+      <a-form
+        @submit="handleSubmit"
+        :form="form"
+      >
+        <a-form-item
+          label="JOB名称"
+          :label-col="{ span: 6 }"
+          :wrapper-col="{ span: 17 }"
+        >
+          <a-input v-decorator="['formData.name',{initialValue: formData.name,rules:[{ required: true, message: '请输入JOB名称' }]}]"/>
+        </a-form-item>
+        <a-form-item
+          label="JOB分组"
+          :label-col="{ span: 6 }"
+          :wrapper-col="{ span: 17 }"
+        >
+          <a-input v-decorator="['formData.group',{initialValue: formData.group,rules:[{ required: true, message: '请输入JOB分组称' }]}]"/>
+        </a-form-item>
+        <a-form-item
+          label="JOB业务类名"
+          :label-col="{ span: 6 }"
+          :wrapper-col="{ span: 17 }"
+        >
+          <a-input v-decorator="['formData.className',{initialValue: formData.className,rules:[{ required: true, message: '请输入JOB业务类名' }]}]"/>
+        </a-form-item>
+        <a-form-item
+          label="CRON表达式"
+          :label-col="{ span: 6 }"
+          :wrapper-col="{ span: 17 }"
+        >
+          <a-input @click="openCronModal" v-model="formData.cron" @change="setCorn">
+            <a-icon slot="prefix" type="schedule" title="corn控件"/>
+            <a-icon v-if="formData.cron" slot="suffix" type="close-circle" @click="formData.cron=''" title="清空"/>
+          </a-input>
+          <JCronModal ref="innerVueCron" :data="formData.cron" @ok="setCorn"></JCronModal>
+        </a-form-item>
+        <a-form-item
+          label="是否启用"
+          :label-col="{ span: 6 }"
+          :wrapper-col="{ span: 17 }"
+        >
+          <a-switch checkedChildren="启用" unCheckedChildren="禁用" v-decorator="['formData.isEnable', { initialValue: formData.isEnable, valuePropName: 'checked' }]" />
+          <!-- <a-switch checkedChildren="启用" unCheckedChildren="禁用" :checked="formData.isEnable" @change="changeStatus"/> -->
+        </a-form-item>
+
+        <div class="jobBtns">
+          <a-button key="back" @click="handleCancel">取消</a-button>
+          <a-button htmlType="submit" :loading="loading" type="primary">
+            确定
+          </a-button>
+        </div>
+
+      </a-form>
+    </a-modal>
+
+  </a-card>
+</template>
+
+<script>
+import { STable } from '@/components'
+import { listJob, pauseJob, resumeJob, delJob, callJob, addJob } from '@/api/job.js'
+import JCronModal from '@/components/Cron/JCronModal'
+
+export default {
+  name: 'Jobs',
+  components: {
+    STable,
+    JCronModal
+  },
+  data () {
+    return {
+      showCron: false,
+      // 查询参数
+      queryParam: {
+        name: ''
+      },
+      selectedRowKeys: [],
+      visible: false,
+      loading: false,
+      formLayout: 'horizontal',
+      formData: {},
+      formBackData: {
+        name: '',
+        group: '',
+        className: '',
+        cron: '',
+        isEnable: false
+      },
+      form: this.$form.createForm(this),
+      // 表头
+      columns: [
+        {
+          title: '序号',
+          dataIndex: 'no',
+          width: '70px',
+          align: 'center'
+        },
+        {
+          title: 'JOB名称',
+          dataIndex: 'name',
+          width: '150px',
+          align: 'center'
+        },
+        {
+          title: 'JOB状态',
+          dataIndex: 'status',
+          width: '100px',
+          align: 'center',
+          scopedSlots: { customRender: 'status' }
+        },
+        {
+          title: 'JOB分组',
+          dataIndex: 'group',
+          width: '150px',
+          align: 'center'
+        },
+        {
+          title: 'JOB业务类名',
+          dataIndex: 'className',
+          width: '200px',
+          align: 'center'
+        },
+        {
+          title: 'CRON表达式',
+          dataIndex: 'cron',
+          width: '150px',
+          align: 'center'
+        },
+        {
+          title: '是否启用',
+          dataIndex: 'isEnable',
+          align: 'center',
+          width: '100px',
+          scopedSlots: { customRender: 'isEnable' }
+        },
+        {
+          title: '操作',
+          dataIndex: 'action',
+          width: '250px',
+          align: 'center',
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return listJob(Object.assign(parameter, this.queryParam)).then(res => {
+          const data = res.data
+          const no = (data.pageNo - 1) * data.pageSize
+          for (var i = 0; i < data.list.length; i++) {
+            data.list[i].no = no + i + 1
+            data.list[i].isEnable = data.list[i].isEnable + '' === '1'
+          }
+          return data
+        })
+      }
+    }
+  },
+  created () {
+
+  },
+  methods: {
+    // 打开cron 表达式弹框
+    openCronModal () {
+      this.$refs.innerVueCron.show()
+    },
+    setCorn (data) {
+      console.log('cron data', data)
+      // this.formData.cron = data
+      this.$set(this.formData, 'cron', data)
+    },
+    handleSubmit (e) {
+      e.preventDefault()
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          // 保存数据
+          let params = Object.assign(this.formData, values.formData)
+          params = Object.assign({}, params)
+          params.isEnable = params.isEnable ? 1 : 0
+          params.id = this.formData.id
+
+          if (params.cron == '' || params.cron.length == 0) {
+            this.$message.warning('请输入CRON表达式')
+            return
+          }
+
+          this.loading = true
+          addJob(params).then(res => {
+            console.log(res)
+            if (res.status + '' === '200') {
+              this.$message.success(params.id ? '修改成功' : '保存成功')
+              this.visible = false
+              this.$refs.table.refresh(true)
+            } else {
+              // this.$message.warning(res.message)
+            }
+            this.loading = false
+          })
+        }
+      })
+    },
+    // 编辑
+    editJob (record) {
+      this.visible = true
+      this.formData = Object.assign({}, {
+        id: record.id,
+        name: record.name,
+        group: record.group,
+        className: record.className,
+        cron: record.cron,
+        isEnable: record.isEnable
+      })
+    },
+    /**
+     * 删除选中的job
+     * @param params
+     */
+    deleteRow (record) {
+      const that = this
+      const h = this.$createElement
+      this.$confirm({
+        title: '提示',
+        content: h('div', {
+          style: {
+            textAlign: 'center'
+          }
+        }, [
+          h('div', '删除后,数据将无法恢复。'),
+          h('div', '确认删除吗?')
+        ]),
+        onOk () {
+          delJob({ id: record.id }).then(res => {
+            if (res.status === '200') {
+              that.$message.success('删除成功')
+              that.$refs.table.refresh()
+            }
+          })
+        }
+      })
+    },
+    /**
+     * 立即执行一次
+     * @param params
+     */
+    syncJob (record) {
+      const that = this
+      const h = this.$createElement
+      this.$confirm({
+        title: '提示',
+        content: h('div', {
+          style: {
+            textAlign: 'center'
+          }
+        }, [
+          h('div', '是否立即执行一次定时器。')
+        ]),
+        onOk () {
+          callJob({ id: record.id }).then(res => {
+            if (res.status === '200') {
+              that.$message.success('执行成功')
+              that.$refs.table.refresh()
+            }
+          })
+        }
+      })
+    },
+    handleCancel (e) {
+      this.visible = false
+      this.loading = false
+      this.formData = Object.assign({}, this.formBackData)
+      this.form.resetFields()
+    },
+    addJob () {
+      this.formData = Object.assign({}, this.formBackData)
+      this.form.resetFields()
+      this.visible = true
+    },
+    /**
+     * 批量启动
+     */
+    startJob () {
+      const _this = this
+      const checkIds = this.selectedRowKeys
+      if (checkIds.length) {
+        // 调用后台启动方法
+        resumeJob({
+          ids: checkIds
+        }).then(res => {
+          if (res.status === '200') {
+            _this.$message.success('操作成功')
+          } else {
+            _this.$message.info(res.message)
+          }
+          _this.$refs.table.refresh()
+        })
+      } else {
+        this.$message.info('请选择需要启动的服务')
+      }
+    },
+    /**
+     * 批量停止
+     */
+    stopJob () {
+      const _this = this
+      const h = this.$createElement
+      const checkIds = this.selectedRowKeys
+      if (checkIds.length) {
+        this.$confirm({
+          title: '提示',
+          content: h('div', {
+            style: {
+              textAlign: 'center'
+            }
+          }, [
+            h('div', '您确定停止所选的服务吗?')
+          ]),
+          onOk () {
+            pauseJob({
+              'ids': checkIds
+            }).then(res => {
+              if (res.status === '200') {
+                _this.$message.success('操作成功')
+              } else {
+                _this.$message.info(res.message)
+              }
+              _this.$refs.table.refresh()
+            })
+          }
+        })
+      } else {
+        this.$message.info('请选择需要停止的服务')
+      }
+    },
+    /**
+     * 获取选中的列表
+     * @returns {Array}
+     */
+    onSelectChange (selectedRowKeys) {
+      this.selectedRowKeys = selectedRowKeys
+    }
+  }
+}
+</script>
+<style>
+  .jobBtns{
+    text-align: center;
+    padding-top: 20px;
+  }
+  .jobBtns button{
+    margin: 0 10px;
+  }
+  .ant-modal-footer{
+    text-align: center;
+  }
+  .ant-modal-body .ant-form-item{
+    margin-bottom: 10px;
+  }
+  .btns{
+    padding-bottom: 15px;
+  }
+  .btns button{
+    margin-right: 15px;
+  }
+  .ant-table-thead > tr > th, .ant-table-tbody > tr > td{
+    word-break: break-all;
+  }
+</style>

+ 306 - 0
src/views/power/menu/childModal.vue

@@ -0,0 +1,306 @@
+<template>
+  <div>
+    <a-modal class="modalBox" :title="titleText" v-model="isshow" @cancle="cancel">
+      <a-form :form="form" @submit="handleSubmit">
+        <!-- 上级菜单 -->
+        <a-form-item label="上级菜单" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <div >
+            <span >{{ parentTitle }}</span>
+          </div>
+
+        </a-form-item>
+        <!-- 类型 -->
+        <a-form-item label="类型" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-select
+            @change="selectChange"
+            :disabled="disabled"
+            v-decorator="[
+              'formData.type',
+              {
+                initialValue: formData.type,
+                rules: [{ required: true, message: '请选择状态!' }] },
+            ]"
+            style="width: 100%"
+            placeholder="请选择菜单类型"
+          >
+            <a-select-option :value="0">页面类型</a-select-option>
+            <a-select-option :value="1">按钮类型</a-select-option>
+          </a-select>
+        </a-form-item>
+
+        <!-- 名称 -->
+        <a-form-item label="名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入名称(最多30个字符)"
+            v-decorator="['formData.name', {
+              initialValue: formData.name,
+              getValueFromEvent: $filterEmpty,
+              rules: [{ required: true, message: '请输入名称!' }] }]"
+          />
+        </a-form-item>
+        <!-- 路由英文名 -->
+        <!-- <a-form-item v-if="!formData.type" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入路由英文名"
+            v-decorator="['formData.routeName', {
+              initialValue: formData.routeName,
+              rules: [{ required: true, message: '请输入路由英文名!' }] }]"
+          />
+        </a-form-item> -->
+        <!-- 路径 -->
+        <!-- <a-form-item v-if="!formData.type" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+             <a-input placeholder="请输入路径"
+                      v-decorator="['formData.routePath', {
+                        initialValue: formData.routePath,
+                        rules: [{ required: true, message: '请输入路径!' }] }]"
+             />
+           </a-form-item> -->
+        <!-- 请求路径 -->
+        <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+             <a-input placeholder="请输入请求路径"
+                      v-decorator="['formData.urlPath', {
+                        initialValue: formData.urlPath,
+                        rules: [{ required: true, message: '请输入请求路径!' }] }]"
+             />
+           </a-form-item> -->
+        <!-- 前端权限编码 -->
+        <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入前端权限编码"
+            v-decorator="[
+              'formData.code',
+              {
+                initialValue: formData.code,
+                rules: [{ required: true, message: '请输入前端权限编码!' }] },
+            ]"
+          />
+
+        </a-form-item>
+        <!-- 后台权限编码 -->
+        <a-form-item label="后台权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入后台权限编码"
+            v-decorator="[
+              'formData.permission',
+              {initialValue: formData.permission},
+            ]"
+          />
+
+        </a-form-item>
+
+        <!-- 图标 -->
+        <!-- <a-form-item v-if="!formData.type" label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入图标名称"
+            v-decorator="['formData.icon', {
+              initialValue: formData.icon,
+              rules: [] }]"
+          />
+        </a-form-item> -->
+        <!-- 前端组件 -->
+        <!-- <a-form-item v-if="!formData.type" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入前端组件路径"
+            v-decorator="['formData.componentPath', {
+              initialValue: formData.componentPath,
+              rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
+          />
+        </a-form-item> -->
+
+        <!-- 第三方链接 -->
+        <!-- <a-form-item v-if="!formData.type" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input
+            placeholder="请输入第三方链接地址"
+            v-decorator="['formData.urlPath', {
+              initialValue: formData.urlPath,
+              rules: [] }]"
+          />
+        </a-form-item> -->
+
+        <!-- 排序值 -->
+        <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-input-number
+            style="width: 100%;"
+            type="number"
+            placeholder="请输入排序值(0~999999)"
+            v-decorator="['formData.sort', {
+              initialValue: formData.sort,
+              rules: [] }]"
+            :max="999999"
+            :min="0"
+          />
+        </a-form-item>
+        <!-- 状态 -->
+        <a-form-item label="启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+          <a-radio-group
+            name="radioGroup"
+            v-decorator="[
+              'formData.status',
+              {
+                initialValue: formData.status,
+                rules: [{ required: true, message: '请选择状态!' }] },
+            ]"
+          >
+            <a-radio :value="1">是</a-radio>
+            <a-radio :value="0">否</a-radio>
+          </a-radio-group>
+        </a-form-item>
+
+        <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+          <a-button type="primary" @click="handleSubmit()">
+            保存
+          </a-button>
+          <a-button :style="{ marginLeft: '8px' }" @click="handleCancel()">
+            取消
+          </a-button>
+        </a-form-item>
+      </a-form>
+
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import { saveMenu } from '@/api/menu.js'
+export default {
+  name: 'ChildModal',
+  components: {
+    STable, VSelect
+  },
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      isshow: this.visible,
+      titleText: '',
+      disabled: false,
+      parentTitle: '',
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'childModal' }),
+      formData: {
+        parentId: '',
+        name: '',
+        routePath: '',
+        icon: '',
+        routeName: '',
+        code: '',
+        permission: '',
+        componentPath: '',
+        urlPath: '',
+        sort: '',
+        type: undefined,
+        status: 1 // 活动状态
+      }
+    }
+  },
+  methods: {
+    cancel (e) {
+      this.clear()
+      this.$emit('close')
+    },
+
+    selectChange (val) {
+      this.formData.type = val
+      console.log(val)
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          console.log(values.formData, ' formData.type222222222')
+          saveMenu(Object.assign(this.formData, values.formData)).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              this.$emit('refresh')
+              setTimeout(function () {
+                _this.cancel()
+              }, 300)
+            } else {
+              // this.$message.warning(res.message)
+            }
+          })
+        }
+      })
+    },
+    // 取消
+    handleCancel () {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '确定取消吗?',
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          _this.clear()
+          _this.cancel()
+        }
+      })
+    },
+    clear () {
+      this.form.resetFields()
+      this.parentTitle = ''
+      this.formData.parentId = ''
+      this.formData.name = ''
+      this.formData.routePath = ''
+      this.formData.icon = ''
+      this.formData.routeName = ''
+      this.formData.componentPath = ''
+      this.formData.urlPath = ''
+      this.formData.sort = ''
+      this.formData.type = ''
+      this.formData.status = 1
+      this.formData.code = ''
+      this.formData.permission = ''
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'childModal' })
+  },
+  watch: {
+    visible (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (newValue) {
+        if (this.data.id) { // 添加子菜单
+          this.titleText = '添加子菜单'
+          this.disabled = false
+          console.log(this.data, 'this.data')
+          this.formData.parentId = this.data.id
+          this.parentTitle = this.data.name
+        } else { // 添加顶菜单
+          this.titleText = '添加顶菜单'
+          this.formData.type = 0
+          this.disabled = true
+        }
+      } else {
+        this.cancel()
+      }
+    }
+  }
+}
+</script>
+
+<style >
+  .modalBox{
+  }
+  .ant-modal-footer {
+    display: none;
+  }
+</style>

+ 462 - 0
src/views/power/menu/menu.vue

@@ -0,0 +1,462 @@
+<template>
+  <a-card :bordered="false">
+    <a-row :gutter="24">
+      <a-button style="margin-right: 10px;" type="primary" icon="plus" @click="addChild">添加子菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: #19be6b;color: #fff;" type="" icon="plus" @click="addTitle">添加顶部菜单</a-button>
+      <a-button style="margin-right: 10px;background-color: red;color: #fff;" type="" icon="delete" @click="delect()">删除</a-button>
+
+    </a-row>
+    <a-row :gutter="24">
+      <!-- 左侧菜单树列表 -->
+      <a-col :span="8">
+        <a-row :gutter="24" class="textCount">
+          <a-icon type="info-circle" style="color: #1890FF;margin-right: 10px;" />
+          <span>当前选择:<span style="color: #40a9ff;font-weight: 600;">{{ selectedMenu }}</span><span v-if="selectedKeys.length" class="imgSize" @click="cancelSel">取消选择</span></span>
+        </a-row>
+
+        <a-row :gutter="24" >
+          <a-input-search placeholder="输入搜索菜单名搜索" style="width: 100%" @change="onChange" />
+          <a-tree
+            @expand="onExpand"
+            :treeData="getMenus"
+            :expandedKeys="expandedKeys"
+            :autoExpandParent="autoExpandParent"
+            @select="onSelect"
+            :selectedKeys="selectedKeys"
+            showIcon
+          >
+            <template slot="title" slot-scope="{title}">
+              <span v-if="title.indexOf(searchValue) > -1">
+                {{ title.substr(0, title.indexOf(searchValue)) }}
+                <span style="color: #f50">{{ searchValue }}</span>
+                {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
+              </span>
+              <span v-else>{{ title }}</span>
+            </template>
+            <a-icon slot="file" type="file" />
+            <a-icon slot="pushpin" type="pushpin" />
+          </a-tree>
+        </a-row>
+      </a-col>
+      <!-- 右侧 -->
+      <a-col :span="16" >
+        <a-form :form="form" @submit="handleSubmit">
+          <!-- 类型 -->
+          <a-form-item label="类型" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <div v-if="!formData.type||formData.type=='0'">
+              <a-icon type="file" style="margin-right: 10px;" /><span >页面菜单</span>
+            </div>
+            <div v-if="formData.type=='1'">
+              <a-icon type="pushpin" style="margin-right: 10px;" /><span >操作按钮</span>
+            </div>
+          </a-form-item>
+
+          <!-- 名称 -->
+          <a-form-item label="名称" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入名称(最多30个字符)"
+              :maxLength="30"
+              v-decorator="['formData.name', {
+                initialValue: formData.name,
+                getValueFromEvent: $filterEmpty,
+                rules: [{ required: true, message: '请输入名称!' }] }]"
+            />
+          </a-form-item>
+          <!-- 路由英文名 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路由英文名" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路由英文名"
+              v-decorator="['formData.routeName', {
+                initialValue: formData.routeName,
+                rules: [{ required: true, message: '请输入路由英文名!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 路径 -->
+          <!-- <a-form-item v-if="!formData.type||formData.type=='0'" label="路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入路径"
+              v-decorator="['formData.routePath', {
+                initialValue: formData.routePath,
+                rules: [{ required: true, message: '请输入路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 请求路径 -->
+          <!-- <a-form-item v-if="formData.type==1" label="请求路径" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入请求路径"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [{ required: true, message: '请输入请求路径!' }] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端权限编码 -->
+          <a-form-item label="前端权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端权限编码"
+              v-decorator="[
+                'formData.code',
+                {
+                  initialValue: formData.code,
+                  rules: [{ required: true, message: '请输入前端权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 后台权限编码 -->
+          <a-form-item label="后台权限编码" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入后台权限编码"
+              v-decorator="[
+                'formData.permission',
+                {
+                  initialValue: formData.permission,
+                  rules: [{ required: formData.isLeaf, message: '请输入后台权限编码!' }] },
+              ]"
+            />
+          </a-form-item>
+          <!-- 图标 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0' " label="图标" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入图标名称"
+              v-decorator="['formData.icon', {
+                initialValue: formData.icon,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+          <!-- 前端组件 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="前端组件" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入前端组件路径"
+              v-decorator="['formData.componentPath', {
+                initialValue: formData.componentPath,
+                rules: [{ required: true, message: '请输入前端组件路径!' }] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 第三方链接 -->
+          <!-- <a-form-item v-if="!formData.type ||formData.type=='0'" label="第三方链接" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input
+              placeholder="请输入第三方链接地址"
+              v-decorator="['formData.urlPath', {
+                initialValue: formData.urlPath,
+                rules: [] }]"
+            />
+          </a-form-item> -->
+
+          <!-- 排序值 -->
+          <a-form-item label="排序值" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-input-number
+              style="width: 100%;"
+              type="number"
+              placeholder="请输入排序值(0~999999)"
+              v-decorator="['formData.sort', {
+                initialValue: formData.sort,
+                rules: [] }]"
+              :max="999999"
+              :min="0"
+            />
+          </a-form-item>
+          <!-- 状态 -->
+          <a-form-item label="启用" :label-col="{ span: 5 }" :wrapper-col="{ span: 14 }">
+            <a-radio-group
+              name="radioGroup"
+              v-decorator="[
+                'formData.status',
+                {
+                  initialValue: formData.status,
+                  rules: [{ required: true, message: '请选择状态!' }] },
+              ]"
+            >
+              <a-radio :value="1">是</a-radio>
+              <a-radio :value="0">否</a-radio>
+            </a-radio-group>
+          </a-form-item>
+
+          <a-form-item :wrapper-col="{ span: 12, offset: 5 }">
+            <a-button type="primary" @click="handleSubmit()">
+              保存
+            </a-button>
+            <a-button :style="{ marginLeft: '8px' }" @click="clear">
+              重置
+            </a-button>
+          </a-form-item>
+        </a-form>
+
+      </a-col>
+    </a-row>
+    <childModal :visible="showChildModal" @refresh="getMenuList" :data="parentData" @close="showChildModal = false"></childModal>
+  </a-card>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import childModal from './childModal.vue'
+import { getMenuList, saveMenu, deleteMenu } from '@/api/menu.js'
+
+export default {
+  name: 'Menu',
+  components: {
+    STable, VSelect, childModal
+  },
+  props: {},
+  data () {
+    return {
+      treeData: [],
+      dataList: [],
+      searchValue: '',
+      expandedKeys: [],
+      autoExpandParent: true,
+      selectedKeys: [],
+      selectedMenu: '', // 选择的树节点名
+      formLayout: 'horizontal',
+      form: this.$form.createForm(this, { name: 'menu' }),
+      showChildModal: false,
+      parentData: {}, // 父级菜单
+      formData: {
+        id: '',
+        name: '',
+        routePath: '',
+        icon: '',
+        routeName: '',
+        componentPath: '',
+        urlPath: '',
+        code: '',
+        permission: '',
+        sort: '',
+        type: '0',
+        isLeaf: true,
+        status: '' // 活动状态
+      }
+    }
+  },
+  computed: {
+    getMenus () {
+      this.generateList(this.treeData)
+      return this.treeData
+    }
+  },
+  methods: {
+    onExpand (expandedKeys) {
+      // console.log('onExpand', expandedKeys)
+      this.expandedKeys = expandedKeys
+      this.autoExpandParent = false
+    },
+
+    onSelect (selectedKeys, info) {
+      console.log('onSelect', info)
+      this.selectedKeys = selectedKeys
+      if (info.selected) {
+        const data = info.selectedNodes[0].data.props
+        const isLeaf = data.dataRef.children
+        // this.formData = Object.assign({}, this.formData, info.selectedNodes[0].data.props)
+        this.formData = {
+          id: data.id,
+          name: data.name,
+          routePath: data.routePath,
+          icon: data.icon,
+          routeName: data.routeName,
+          componentPath: data.componentPath,
+          urlPath: data.urlPath,
+          code: data.code,
+          permission: data.permission,
+          sort: data.sort,
+          type: data.type,
+          status: data.status,
+          isLeaf: !(isLeaf && isLeaf.length)
+        }
+
+        this.selectedMenu = this.formData.name
+        this.formData.status = Number(this.formData.status)
+      } else {
+        this.selectedMenu = ''
+        this.clear()
+      }
+    },
+    generateList (data) {
+      for (let i = 0; i < data.length; i++) {
+        const node = data[i]
+        const key = node.title
+        this.dataList.push({ key, title: key })
+        node.scopedSlots = { title: 'title' }
+        node.slots = { icon: node.type == '0' ? 'file' : 'pushpin' }
+
+        if (node.children) {
+          this.generateList(node.children)
+        }
+      }
+    },
+    getParentKey (key, tree) {
+      let parentKey
+      for (let i = 0; i < tree.length; i++) {
+        const node = tree[i]
+        if (node.children) {
+          if (node.children.some(item => item.title == key)) {
+            parentKey = node.key
+          } else if (this.getParentKey(key, node.children)) {
+            parentKey = this.getParentKey(key, node.children)
+          }
+        }
+      }
+      return parentKey
+    },
+    onChange (e) {
+      const value = e.target.value
+      const expandedKeys = this.dataList
+        .map(item => {
+          if (item.title.indexOf(value) > -1) {
+            return this.getParentKey(item.title, this.treeData)
+          }
+          return null
+        })
+        .filter((item, i, self) => item && self.indexOf(item) === i)
+      Object.assign(this, {
+        expandedKeys,
+        searchValue: value,
+        autoExpandParent: true
+      })
+    },
+    // 获取菜单树列表
+    getMenuList () {
+      getMenuList().then(res => {
+        console.log(res, 'res1111111')
+        if (res.status == 200) {
+          this.treeData = res.data
+          console.log(this.treeData, 'this.treeData')
+        }
+      })
+    },
+    // 添加子节点
+    addChild () {
+      if (!this.selectedMenu) {
+        return this.$message.warning('请先选择一个父级菜单')
+      } else if (this.formData.type == '1') {
+        return this.$message.warning('请选择一个页面级菜单')
+      }
+      this.showChildModal = true
+      this.parentData = this.formData
+    },
+    // 添加顶部菜单
+    addTitle () {
+      this.showChildModal = true
+      this.parentData = {}
+    },
+
+    //  取消选择
+    cancelSel () {
+      this.selectedKeys = []
+      this.selectedMenu = ''
+      this.clear()
+    },
+    // 清空列表
+    clear () {
+      this.form.resetFields()
+      this.formData.id = ''
+      this.formData.name = ''
+      this.formData.routePath = ''
+      this.formData.icon = ''
+      this.formData.routeName = ''
+      this.formData.componentPath = ''
+      this.formData.urlPath = ''
+      this.formData.sort = ''
+      this.formData.type = ''
+      this.formData.status = ''
+      this.formData.code = ''
+      this.formData.permission = ''
+      this.formData.isLeaf = true
+    },
+
+    // 删除数据
+    delect () {
+      if (!this.selectedKeys.length) {
+        return this.$message.warning('您还未选择要删除的数据')
+      }
+      const _this = this
+      console.log(_this.formData.id, '_this.formData.id')
+      this.$confirm({
+        title: '警告',
+        content: `确定要删除您选择的 ${_this.formData.name} 的数据吗?`,
+        okText: '确定',
+        cancelText: '取消',
+        onOk () {
+          deleteMenu({
+            id: _this.formData.id
+          }).then(res => {
+            if (res.status == 200) {
+              _this.$message.success('删除成功')
+              _this.getMenuList()
+            }
+          }).catch(() => {
+            _this.$message.success('删除失败, 请稍后重试')
+          })
+        }
+      })
+    },
+
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.form.validateFields((err, values) => {
+        if (!err) {
+          console.log(values.formData, ' formData.type222222222')
+          saveMenu(Object.assign({ id: this.formData.id }, values.formData)).then(res => {
+            console.log(res, 'res--save')
+            if (res.status + '' === '200') {
+              this.$message.success(res.message ? res.message : '保存成功')
+              _this.getMenuList()
+              _this.clear()
+            } else {
+              // this.$message.warning(res.message)
+            }
+          })
+        }
+      })
+    },
+    handleCancel () {
+      this.clear()
+    }
+
+  },
+  mounted () {
+  },
+  beforeCreate () {
+    this.form = this.$form.createForm(this, { name: 'menu' })
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {
+      vm.getMenuList()
+    })
+  },
+  watch: {
+
+  }
+}
+</script>
+
+<style>
+  .menu-box::-webkit-scrollbar{
+    width: 6px;
+    height: 6px ;
+  }
+
+  .menu-box::-webkit-scrollbar-thumb{
+    width: 6px;
+    height: 6px ;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 0 2px #d1d1d1;
+    background: #e4e4e4;
+  }
+
+  .textCount{
+    border: 1px solid #91d5ff;
+    background-color: #e6f7ff;
+    border-radius: 5px;
+    padding: 5px 10px 5px 20px;
+    margin: 10px 0;
+    color: rgba(0, 0, 0, 0.85);
+  }
+  .imgSize{
+    color: #2d8cf0;
+    margin-left: 10px;
+    font-size: 14px;
+  }
+
+</style>

+ 0 - 146
src/views/productManagement/productCategory/editModal.vue

@@ -1,146 +0,0 @@
-<template>
-  <a-modal
-    centered
-    class="productCategoryEdit-modal"
-    :footer="null"
-    :maskClosable="false"
-    :title="modalTit"
-    v-model="isShow"
-    @cancle="isShow=false"
-    :width="800">
-    <!-- 表单 -->
-    <div>
-      <a-form-model
-        id="productCategoryEdit-form"
-        ref="ruleForm"
-        :model="form"
-        :rules="rules"
-        :label-col="formItemLayout.labelCol"
-        :wrapper-col="formItemLayout.wrapperCol"
-      >
-        <a-form-model-item label="所属类别" v-if="parentType">
-          {{ parentType }}
-        </a-form-model-item>
-        <a-form-model-item label="产品类别名称" prop="productTypeName">
-          <a-input v-model.trim="form.productTypeName" id="productCategory-name" :maxLength="30" allowClear placeholder="请输入产品类别名称(最多30个字符)" />
-        </a-form-model-item>
-      </a-form-model>
-      <div class="btn-cont">
-        <a-button type="primary" id="product-category-edit-modal-save" @click="handleSave">保存</a-button>
-        <a-button id="product-category-edit-modal-back" @click="isShow = false" style="margin-left: 15px;">返回列表</a-button>
-      </div>
-    </div>
-  </a-modal>
-</template>
-
-<script>
-import { STable } from '@/components'
-import { dealerProductTypeSave } from '@/api/dealerProductType'
-export default {
-  name: 'productCategoryEditModal',
-  components: { STable },
-  props: {
-    openModal: { //  弹框显示状态
-      type: Boolean,
-      default: false
-    },
-    itemId: {
-      type: [Number, String],
-      default: ''
-    },
-    nowData: {
-      type: Object,
-      default: null
-    }
-  },
-  computed: {
-    modalTit () {
-      return (this.itemId ? '编辑' : '新增') + '产品类别'
-    }
-  },
-  data () {
-    return {
-      isShow: this.openModal, //  是否打开弹框
-      formItemLayout: {
-        labelCol: { span: 6 },
-        wrapperCol: { span: 16 }
-      },
-      form: {
-        productTypeName: '', // 产品类别名称
-      },
-      rules: {
-        productTypeName: [
-          { required: true, message: '请输入产品类别名称', trigger: 'blur' }
-        ],
-      },
-      parentType: '',  //  父级分类
-    }
-  },
-  methods: {
-    //  保存
-    handleSave(){
-      const _this = this
-      _this.$refs.ruleForm.validate(valid => {
-        if (valid) {
-          const formData = JSON.parse(JSON.stringify(_this.form))
-          formData.id = _this.itemId ? _this.itemId : null
-          formData.psn = _this.nowData && _this.nowData.psn ? _this.nowData.psn : null
-          dealerProductTypeSave(formData).then(res => {
-            if (res.status == 200) {
-              _this.$message.success(res.message)
-              _this.$emit('ok')
-              _this.isShow = false
-            }
-          })
-        } else {
-          return false
-        }
-      })
-    },
-  },
-  watch: {
-    //  父页面传过来的弹框状态
-    openModal (newValue, oldValue) {
-      this.isShow = newValue
-    },
-    //  重定义的弹框状态
-    isShow (newValue, oldValue) {
-      if (!newValue) {
-        this.$emit('close')
-      }else{
-        //  获取父级分类 名称
-        if(this.nowData && this.nowData.namePaths){
-          let namePathsArr = []
-          namePathsArr = this.nowData.namePaths.split(',')
-          this.parentType = ''
-          namePathsArr.map((item, index) => {
-            this.parentType += item + ' > '
-          })
-          this.parentType = this.parentType ? this.parentType.substr(0, this.parentType.length - 3) : ''
-        }else{
-          this.parentType = ''
-        }
-      }
-    },
-    itemId (newValue, oldValue) {
-      if (this.isShow && newValue) {
-        this.form.productTypeName = this.nowData && this.nowData.productTypeName ? this.nowData.productTypeName : ''
-      }else{
-        this.form.productTypeName = ''
-      }
-    }
-  }
-}
-</script>
-
-<style lang="less">
-  .productCategoryEdit-modal{
-    .ant-modal-body {
-    	padding: 40px 40px 24px;
-    }
-    .btn-cont {
-    	text-align: center;
-    	margin: 35px 0 10px;
-    }
-  }
-</style>

+ 0 - 170
src/views/productManagement/productCategory/list.vue

@@ -1,170 +0,0 @@
-<template>
-  <a-card :bordered="false" class="productCategoryList-wrap">
-    <!-- 操作按钮 -->
-    <div class="table-operator">
-      <a-button id="productCategoryList-add" type="primary" @click="handleAdd()" style="margin-top: 18px;">新增一级分类</a-button>
-    </div>
-    <!-- 列表 -->
-    <s-table
-      class="sTable"
-      ref="table"
-      size="default"
-      :rowKey="(record) => record.id"
-      :columns="columns"
-      :data="loadData"
-      :showPagination="false"
-      :defaultExpandedRowKeys="defaultExpandedRowKeys"
-      bordered>
-      <!-- 操作 -->
-      <template slot="action" slot-scope="text, record">
-        <a-button
-          v-if="record.productTypeLevel<3"
-          type="link"
-          size="small"
-          icon="plus"
-          class="btn-add-s"
-          id="productCategory-addSubItem"
-          @click="handleAdd(record)">新增子级</a-button>
-        <a-button
-          v-if="record.pid != 0"
-          type="link"
-          size="small"
-          icon="edit"
-          class="btn-edit-s"
-          id="productCategory-edit"
-          @click="handleEdit(record)">编辑</a-button>
-        <a-button
-          v-if="record.pid != 0"
-          type="link"
-          size="small"
-          icon="delete"
-          class="btn-del-s"
-          id="productCategory-del"
-          @click="handleDel(record)">删除</a-button>
-      </template>
-    </s-table>
-    <!-- 新增/编辑产品类别 -->
-    <product-category-edit-modal :openModal="openModal" :nowData="nowData" :itemId="itemId" @ok="handleOk" @close="closeModal" />
-  </a-card>
-</template>
-
-<script>
-import { dealerProductTypeQuery, dealerProductTypeDel } from '@/api/dealerProductType'
-import { STable } from '@/components'
-import productCategoryEditModal from './editModal.vue'
-export default {
-  components: { STable, productCategoryEditModal },
-  data () {
-    return {
-      formItemLayout: {
-        labelCol: { span: 6 },
-        wrapperCol: { span: 16 }
-      },
-      columns: [
-        { title: '产品类别名称', dataIndex: 'productTypeName', width: 200, align: 'left' },
-        { title: '首字母', dataIndex: 'sss', width: 150, align: 'center' },
-        { title: '创建时间', dataIndex: 'createDate', width: 150, align: 'center' },
-        { title: '操作', scopedSlots: { customRender: 'action' }, width: 150, align: 'center' }
-      ],
-      // 加载数据方法 必须为 Promise 对象
-      loadData: parameter => {
-        this.disabled = true
-        return dealerProductTypeQuery({}).then(res => {
-          //  递归去除空children
-          this.recursionFun(res.data)
-          this.defaultExpandedRowKeys[0] = res.data[0].id
-          return res.data
-        })
-      },
-      defaultExpandedRowKeys: [], //  树形数据默认展开项
-      openModal: false,  //  新增编辑  弹框
-      itemId: '',  //  当前id
-      nowData: null  //  当前记录数据
-    }
-  },
-  methods: {
-    //  新增子级
-    handleAdd (row) {
-      this.itemId = null
-      if(row){  //  新增子级
-        let nowData = row
-        nowData.psn = nowData && nowData.productTypeSn ? nowData.productTypeSn : null
-        this.nowData = nowData
-      }else{  //  最高级
-        this.nowData = null
-      }
-      this.openModal = true
-    },
-    //  编辑
-    handleEdit (row) {
-      this.itemId = row && row.id ? row.id : null
-      let nowData = row
-      nowData.psn = nowData && nowData.productTypeSn ? nowData.productTypeSn : null
-      this.nowData = nowData
-      this.openModal = true
-    },
-    //  关闭弹框
-    closeModal(){
-      this.itemId = ''
-      this.openModal = false
-    },
-    //  新增/编辑  成功
-    handleOk(){
-      this.$refs.table.refresh(true)
-    },
-    //  删除
-    handleDel (item) {
-      const _this = this
-      _this.nowId = item.id
-      _this.$confirm({
-        title: '提示',
-        centered: true,
-        content: '删除后原数据不可恢复,是否删除?',
-        onOk () {
-          dealerProductTypeDel({ id: _this.nowId }).then(res => {
-            if (res.status == 200) {
-              _this.$message.success(res.message)
-              _this.$refs.table.refresh()
-            }
-          })
-        }
-      })
-    },
-    //  递归函数
-    recursionFun (data) {
-      if (data) {
-        data.map((item, index) => {
-          if (item.children && item.children.length == 0) {
-            delete item.children
-          } else {
-            this.recursionFun(item.children)
-          }
-        })
-      }
-    }
-  }
-}
-</script>
-
-<style lang="less">
-  .productCategoryList-wrap{
-    // 表格
-    .s-table{
-      .btn-edit-s{
-        color: #1891ff;
-        margin: 0 5px;
-      }
-      .btn-del-s{
-        color: #ff4d4f;
-      }
-      .btn-edit-s.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger), .btn-edit-s.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger){
-        color: #1891ff;
-        border-color: #1891ff;
-      }
-      .btn-del-s.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger), .btn-del-s.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger){
-        color: #ff4d4f;
-        border-color: #ff4d4f;
-      }
-    }
-  }
-</style>

+ 1 - 1
vue.config.js

@@ -108,7 +108,7 @@ const vueConfig = {
     // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
     proxy: {
       '/api': {
-        target: 'http://192.168.0.119:8503/qpls-md',
+        target: 'http://192.168.16.103:8501/qpls-it',
         // target: 'http://it.test.zyucgj.com/zyit',
         // target: 'https://it.test.qiubcar.com/zyit',
         ws: false,