zhengnaiwen_citu пре 7 месеци
родитељ
комит
7461fef281

+ 1 - 1
src/components/MButton/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-button v-bind="$attrs" :type="type" v-on="$listeners">
+  <el-button v-bind="$attrs" :type="text ? 'text' : type" v-on="$listeners">
     <template v-if="text">
       <el-link :underline="false" :type="type" text>
         <slot></slot>

+ 15 - 0
src/components/MCard/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <el-card v-bind="$attrs" v-on="$listeners">
+    <slot></slot>
+  </el-card>
+</template>
+
+<script>
+export default {
+  name: 'm-card'
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 65 - 1
src/components/MDialog/index.vue

@@ -11,8 +11,8 @@
   >
     <slot></slot>
     <span slot="footer">
-      <el-button @click="show = false">取 消</el-button>
       <el-button type="primary" @click="sure">确 定</el-button>
+      <el-button @click="show = false">取 消</el-button>
     </span>
   </el-dialog>
 </template>
@@ -20,11 +20,75 @@
 <script>
 export default {
   name: 'm-dialog',
+  props: {
+    // draggable: {
+    //   type: Boolean,
+    //   default: true
+    // }
+  },
   data () {
     return {
       show: false
     }
   },
+  // directives: {
+  //   'drag-dialog': {
+  //     bind (el, binding, vnode) {
+  //       if (!binding.value) return
+
+  //       const dialogHeaderEl = el.querySelector('.el-dialog__header')
+  //       const dragDom = el.querySelector('.el-dialog')
+
+  //       console.log(dragDom)
+
+  //       dialogHeaderEl.style.cursor = 'move'
+  //       dragDom.style.position = 'fixed'
+  //       dragDom.style.marginLeft = (document.clientWidth - dragDom.clientWidth) / 2 + 'px'
+
+  //       let isDragging = false
+  //       // let offsetX = 0
+  //       // let offsetY = 0
+
+  //       dialogHeaderEl.onmousedown = (e) => {
+  //         isDragging = true
+
+  //         // 计算鼠标按下时相对于对话框左上角的偏移量
+  //         // const rect = dragDom.getBoundingClientRect()
+  //         const clientX = e.clientX
+  //         const clientY = e.clientY
+
+  //         document.onmousemove = (e) => {
+  //           if (!isDragging) return
+
+  //           // 计算新的对话框位置
+  //           let left = e.clientX - clientX
+  //           let top = e.clientY - clientY
+
+  //           // 限制拖拽范围
+  //           const screenWidth = document.body.clientWidth
+  //           const screenHeight = document.body.clientHeight
+  //           const dragDomWidth = dragDom.offsetWidth
+  //           const dragDomHeight = dragDom.offsetHeight
+
+  //           if (left < 0) left = 0
+  //           if (left > screenWidth - dragDomWidth) left = screenWidth - dragDomWidth
+  //           if (top < 0) top = 0
+  //           if (top > screenHeight - dragDomHeight) top = screenHeight - dragDomHeight
+
+  //           // 更新对话框位置
+  //           dragDom.style.left = `${left}px`
+  //           dragDom.style.top = `${top}px`
+  //         }
+
+  //         document.onmouseup = () => {
+  //           isDragging = false
+  //           document.onmousemove = null
+  //           document.onmouseup = null
+  //         }
+  //       }
+  //     }
+  //   }
+  // },
   methods: {
     open () {
       this.show = true

+ 8 - 3
src/components/MForm/index.vue

@@ -85,8 +85,16 @@ export default {
     }
   },
   watch: {
+    value: {
+      handler (val) {
+        console.log('changeValue', val)
+        this.query = val
+      },
+      deep: true
+    },
     query: {
       handler (val) {
+        console.log('changeQuery', val)
         this.$emit('input', val)
       },
       deep: true
@@ -99,9 +107,6 @@ export default {
     }, {})
   },
   methods: {
-    setValue () {
-      this.query = { ...this.value }
-    },
     resetFields () {
       this.$refs.formRef.resetFields()
     },

+ 12 - 5
src/components/MSearch/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-card  shadow="never">
+  <m-card>
     <el-form :inline="true" :model="form" ref="form" label-width="80px" size="small" :show-message="false" inline-message>
       <el-form-item
         v-for="(item, index) in items"
@@ -42,12 +42,16 @@
         <slot name="button"></slot>
       </el-form-item>
     </el-form>
-  </el-card>
+  </m-card>
 </template>
 
 <script>
+import MCard from '@/components/MCard'
 export default {
   name: 'm-search',
+  components: {
+    MCard
+  },
   props: {
     items: {
       type: Array,
@@ -64,6 +68,12 @@ export default {
     }
   },
   watch: {
+    value: {
+      handler (newVal) {
+        this.form = newVal
+      },
+      deep: true
+    },
     form: {
       handler (newVal) {
         this.$emit('input', newVal)
@@ -72,9 +82,6 @@ export default {
     }
   },
   methods: {
-    setValue () {
-      this.form = { ...this.value }
-    },
     onSubmit () {
       this.$emit('search', this.form)
     },

+ 4 - 3
src/components/MTable/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-card  shadow="never">
+  <m-card>
     <el-table
       ref="table"
       :data="items"
@@ -30,14 +30,15 @@
       >
       </el-pagination>
     </div>
-  </el-card>
+  </m-card>
 </template>
 
 <script>
+import MCard from '@/components/MCard'
 import MTableColumn from './MTableColumn.vue'
 export default {
   name: 'm-table',
-  components: { MTableColumn },
+  components: { MTableColumn, MCard },
   props: {
     items: {
       type: Array,

+ 0 - 2
src/directives/index.js

@@ -1,9 +1,7 @@
-import loading from './loading' // 防抖
 import permission from './permission' // 权限
 
 // 自定义指令
 const directives = {
-  loading,
   permission
 }
 

+ 0 - 45
src/directives/loading/index.js

@@ -1,45 +0,0 @@
-import Vue from 'vue'
-import pageLoading from './loading.vue'
-
-const Mask = Vue.extend(pageLoading)
-
-const toggleLoading = (el, binding) => {
-  // el拿到loading挂载的元素,binding.value判断是否显示loading
-  if (binding.value) {
-    Vue.nextTick(() => {
-      el.instance.loadingShow = true
-      insertDom(el, el, binding)
-    })
-  } else {
-    el.instance.loadingShow = false
-  }
-}
-
-const insertDom = (parent, el) => {
-  parent.appendChild(el.mask)
-}
-
-export default {
-  bind: function (el, binding) {
-    const mask = new Mask({
-      el: document.createElement('div'),
-      data () { }
-    })
-    el.instance = mask
-    el.mask = mask.$el
-    el.maskStyle = {
-      position: 'relation'
-    }
-    el.style.position = 'relative'
-    binding.value && toggleLoading(el, binding)
-  },
-  update: function (el, binding) {
-    if (binding.oldValue !== binding.value) {
-      toggleLoading(el, binding)
-    }
-  },
-  unbind: function (el, binding) {
-    el.instance && el.instance.$destroy()
-    el = null
-  }
-}

+ 0 - 88
src/directives/loading/loading.vue

@@ -1,88 +0,0 @@
-<template>
-    <div class="loading-container" v-show="loadingShow">
-        <div class="loading">
-            <span></span>
-            <span></span>
-            <span></span>
-            <span></span>
-        </div>
-    </div>
-</template>
-
-<script>
-export default {
-  name: 'loading-page',
-  data () {
-    return {
-      loadingShow: false
-    }
-  }
-}
-</script>
-
-<style scoped lang="scss">
-    .loading-container{
-        position: absolute;
-        top: 0;
-        left: 0;
-        bottom: 0;
-        right: 0;
-        z-index: var(--zIndex-snackbar);
-        background: rgba(255, 255, 255, 0.7);
-        display: flex;
-        align-items: center;
-        justify-content: center;
-    }
-    .loading{
-        width: 40px;
-        display: flex;
-        justify-content: space-between;
-    }
-    .loading span{
-        display: inline-block;
-        width: 5px;
-        height: 100%;
-        border-radius: 4px;
-        background: #42A5F5;
-        -webkit-animation: load 1s ease infinite;
-        animation: load 1s ease infinite;
-    }
-    @-webkit-keyframes load{
-        0%,100%{
-            height: 20px;
-            // background: lightgreen;
-        }
-        50%{
-            height: 50px;
-            margin: -15px 0;
-            // background: lightblue;
-        }
-    }
-    @keyframes load{
-        0%,100%{
-            height: 20px;
-            // background: lightgreen;
-        }
-        50%{
-            height: 50px;
-            margin: -15px 0;
-            // background: lightblue;
-        }
-    }
-    .loading span:nth-child(2){
-        -webkit-animation-delay:0.2s;
-        animation-delay:0.2s;
-    }
-    .loading span:nth-child(3){
-        -webkit-animation-delay:0.4s;
-        animation-delay:0.4s;
-    }
-    .loading span:nth-child(4){
-        -webkit-animation-delay:0.6s;
-        animation-delay:0.6s;
-    }
-    .loading span:nth-child(5){
-        -webkit-animation-delay:0.8s;
-        animation-delay:0.8s;
-    }
-</style>

+ 154 - 47
src/views/systemManage/roleManage/index.vue

@@ -1,13 +1,14 @@
 <template>
-  <div>
+  <div class="pa-3 white">
     <m-search :items="searchItems" v-model="searchValues" class="mb-3" @search="search" @reset="search">
       <template #button>
-        <el-button type="primary" icon="el-icon-plus" @click="handleAdd">
+        <el-button type="primary" icon="el-icon-plus" @click="onAdd">
           新增
         </el-button>
       </template>
     </m-search>
     <MTable
+      v-loading="loading"
       :items="items"
       :headers="headers"
       :page-size="pageInfo.size"
@@ -19,24 +20,46 @@
         {{ dateFormat(scope.row.createTime) }}
       </template>
       <template #actions="scope">
-        <el-button type="text">
-          <el-link :underline="false" type="primary" text @click="handleClick(scope.row)">数据权限</el-link>
-        </el-button>
-        <el-button type="text">
-          <el-link :underline="false" type="primary" text @click="handleClick(scope.row)">编辑</el-link>
-        </el-button>
-        <el-button type="text">
-          <el-link :underline="false" type="danger" text @click="handleClick(scope.row)">删除</el-link>
-        </el-button>
+        <m-button type="primary" text @click="onEdit(scope.row)">编辑</m-button>
+        <m-button type="primary" text @click="onMenu(scope.row)">菜单权限</m-button>
+        <m-button type="primary" text @click="onPermission(scope.row)">数据权限</m-button>
+        <m-button type="danger" text @click="onDelete(scope.row)">删除</m-button>
       </template>
     </MTable>
-    <MDialog ref="dialog" :title="isEdit ? '编辑角色' : '新增角色'" @sure="handleSave">
-      <MForm></MForm>
+    <MDialog ref="dialog" :title="itemData.id ? '编辑角色' : '新增角色'" @sure="handleSave">
+      <MForm ref="roleForm" :items="roleFormItems" v-model="roleFormValue"></MForm>
+    </MDialog>
+    <MDialog ref="menuDialog" title="菜单权限编辑" @sure="handleSaveMenu">
+      <MForm ref="menuForm">
+        <el-form-item label="角色名称">
+          <el-tag>{{ itemData.roleName }}</el-tag>
+        </el-form-item>
+        <el-form-item label="菜单权限" required>
+          <m-card shadow="never">
+            <el-tree
+              ref="menuTree"
+              :data="menuData"
+              show-checkbox
+              node-key="id"
+              :props="{
+                children: 'children',
+                label: 'label'
+              }"
+            >
+            </el-tree>
+          </m-card>
+        </el-form-item>
+      </MForm>
+    </MDialog>
+    <MDialog ref="dataDialog" title="数据权限编辑" @sure="handleSaveData">
+      <MForm ref="roleForm" :items="roleFormItems" v-model="roleFormValue"></MForm>
     </MDialog>
   </div>
 </template>
 
 <script>
+import MCard from '@/components/MCard'
+import MButton from '@/components/MButton'
 import MForm from '@/components/MForm'
 import MTable from '@/components/MTable'
 import MDialog from '@/components/MDialog'
@@ -50,11 +73,11 @@ import {
   saveDataPermission
 } from '@/api/menu'
 import { dateFormat } from '@/utils/date'
-// import UserEdit from './components/userEdit'
-// import DataPermission from './components/DataPermission'
 export default {
   name: 'role-manage-role',
   components: {
+    MCard,
+    MButton,
     MForm,
     MTable,
     MDialog,
@@ -62,6 +85,25 @@ export default {
   },
   data () {
     return {
+      itemData: {},
+      roleFormItems: [
+        {
+          label: '角色名称',
+          prop: 'roleName',
+          type: 'input',
+          rules: [
+            { required: true, message: '请输入角色名称', trigger: 'blur' }
+          ]
+        }
+      ],
+      roleFormValue: {
+        roleName: null
+      },
+      menuFormItems: [
+        {
+          label: '角色名称'
+        }
+      ],
       searchValues: {
         roleName: null
       },
@@ -72,9 +114,7 @@ export default {
           type: 'input'
         }
       ],
-      roles: [],
-      isEdit: false,
-      itemData: {},
+      menuData: [],
       itemDataPermission: {},
       show: false,
       showMenu: false,
@@ -90,9 +130,17 @@ export default {
         current: 1
       },
       orders: [],
-      loading: true
+      loading: false
     }
   },
+  // computed: {
+  //   defaultCheckedKeys () {
+  //     if (Object.keys(this.itemData).length === 0) {
+  //       return []
+  //     }
+  //     return this.itemData.menuIds.split(',').map(e => +e)
+  //   }
+  // },
   created () {
     this.getMenu()
   },
@@ -100,75 +148,134 @@ export default {
     async getMenu () {
       try {
         const { data } = await getMenuTree({})
-        this.roles = data.routes
+        this.menuData = data.routes
         this.initPage()
       } catch (error) {
         this.$message.error(error)
       }
     },
     async initPage () {
-      this.loading = false
+      this.loading = true
       try {
         const { data } = await getRoleList({ ...this.pageInfo, orders: this.orders, entity: this.searchValues })
         this.items = data.records
         this.total = data.total
       } catch (error) {
         this.$message.error(error)
+      } finally {
+        this.loading = false
       }
     },
-    async handleEdit (item) {
+    async getDetails (roleId) {
       try {
-        const { data } = await getRoleDetails({ roleId: item.id })
+        const { data } = await getRoleDetails({ roleId })
         this.itemData = data
-        this.isEdit = true
-        this.show = true
+        Object.assign(this.itemData, data)
+        return data
       } catch (error) {
         this.$message.error(error)
       }
     },
-    async handleAdd () {
-      this.isEdit = false
+    onAdd () {
+      this.roleFormValue = {
+        roleName: null
+      }
+      this.itemData = {}
+      this.$refs.dialog.open()
+    },
+    async onEdit (item) {
+      const data = await this.getDetails(item.id)
+      if (!data) {
+        return
+      }
+      this.roleFormValue = {
+        roleName: data.roleName
+      }
+      this.itemData = data
       this.$refs.dialog.open()
     },
+    async onMenu (item) {
+      const data = await this.getDetails(item.id)
+      if (!data) {
+        return
+      }
+      this.itemData = data
+      this.$refs.menuDialog.open()
+      this.$nextTick(() => {
+        this.$refs.menuTree.setCheckedKeys(data.menuIds.split(',').map(e => +e))
+      })
+    },
+    async onPermission (item) {
+      const data = await this.getDetails(item.id)
+      if (!data) {
+        return
+      }
+      this.itemData = data
+      this.$refs.dataDialog.open()
+    },
+    onDelete (item) {
+      this.$confirm('是否确定删除该选项', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(async () => {
+        try {
+          await deleteRole({ id: item.id })
+          this.$message.success('删除成功')
+          this.initPage()
+        } catch (error) {
+          this.$message.error(error)
+        }
+      }).catch(_ => {})
+    },
     handleData (item) {
       this.itemDataPermission = item
       this.showMenu = true
     },
-    handleDelete (ids) {
-      // console.log(ids)
-      // if (Array.isArray(ids)) return
-      if (Array.isArray(ids) && ids.length === 0) return this.$message.warning('请选择删除的选项')
-      // console.log(ids)
-      // if (ids) return
-      this.$confirm('提示', '是否确定删除该选项').then(async () => {
+    handleSave () {
+      this.$refs.roleForm.validate(async (valid) => {
+        if (!valid) {
+          return
+        }
+        const obj = {
+          ...this.roleFormValue,
+          menuIds: '-9999'
+        }
         try {
-          await deleteRole({ id: ids })
-          this.$message.success('删除成功')
+          await saveRole(obj)
+          this.$message.success(this.itemData.id ? '编辑成功' : '添加成功')
+          this.$refs.dialog.close()
           this.initPage()
         } catch (error) {
           this.$message.error(error)
         }
       })
     },
-    async handleSave () {
-      const obj = this.$refs.edit.getValue()
-      if (this.isEdit) obj.id = this.itemData.id
+    async handleSaveMenu () {
+      const menuIds = this.$refs.menuTree.getCheckedKeys(true)
+      if (!menuIds.length) {
+        this.$message.warning('请选择菜单')
+        return
+      }
+      const obj = {
+        id: this.itemData.id,
+        menuIds: menuIds.join(',')
+      }
       try {
         await saveRole(obj)
-        this.$message.success(this.isEdit ? '编辑成功' : '添加成功')
-        this.$refs.dialog.closest()
+        this.$message.success('保存成功')
+        this.$refs.menuDialog.close()
         this.initPage()
       } catch (error) {
         this.$message.error(error)
       }
     },
-    async handleSaveMenu () {
-      const obj = this.$refs.dataPermission.getValue()
-      if (!obj) {
-        return
-      }
+    async handleSaveData () {
       try {
-        await saveDataPermission(obj)
+        await saveDataPermission({
+          roleId: this.itemData.id
+          // menuIds: menuIds.join(',')
+        })
         this.$message.success('保存成功')
         this.showMenu = false
         this.initPage()