kailong321200875 1 жил өмнө
parent
commit
47016a535f

+ 5 - 0
mock/menu/index.ts

@@ -173,6 +173,7 @@ export default [
                     id: toAnyString(),
                     meta: {
                       title: '综合示例-弹窗',
+                      currentPermission: ['edit', 'add'],
                       permission: ['edit', 'add', 'delete']
                     }
                   },
@@ -184,6 +185,7 @@ export default [
                     id: toAnyString(),
                     meta: {
                       title: '综合示例-页面',
+                      currentPermission: ['edit', 'add'],
                       permission: ['edit', 'add', 'delete']
                     }
                   },
@@ -200,6 +202,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
+                      currentPermission: ['delete', 'add'],
                       permission: ['edit', 'add', 'delete']
                     }
                   },
@@ -216,6 +219,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
+                      currentPermission: ['delete', 'add'],
                       permission: ['edit', 'add', 'delete']
                     }
                   },
@@ -232,6 +236,7 @@ export default [
                       hidden: true,
                       showMainRoute: true,
                       activeMenu: '/example/example-page',
+                      currentPermission: ['delete', 'edit'],
                       permission: ['edit', 'add', 'delete']
                     }
                   }

+ 36 - 0
mock/role/index.ts

@@ -1,5 +1,7 @@
 import config from '@/config/axios/config'
 import { MockMethod } from 'vite-plugin-mock'
+import Mock from 'mockjs'
+import { toAnyString } from '@/utils'
 
 const { code } = config
 
@@ -527,6 +529,24 @@ const testList: string[] = [
   '/error/500-demo'
 ]
 
+const List: any[] = []
+
+const roleNames = ['超级管理员', '管理员', '普通用户', '游客', '测试用户']
+
+for (let i = 0; i < 5; i++) {
+  List.push(
+    Mock.mock({
+      id: toAnyString(),
+      // timestamp: +Mock.Random.date('T'),
+      roleName: roleNames[i],
+      role: '@first',
+      status: Mock.Random.integer(0, 1),
+      createTime: '@datetime',
+      remark: '@cword(10, 15)'
+    })
+  )
+}
+
 export default [
   // 列表接口
   {
@@ -542,5 +562,21 @@ export default [
         }
       }
     }
+  },
+  {
+    url: '/role/table',
+    method: 'get',
+    timeout,
+    response: () => {
+      return {
+        data: {
+          code: code,
+          data: {
+            list: List,
+            total: 5
+          }
+        }
+      }
+    }
   }
 ] as MockMethod[]

+ 5 - 0
src/api/role/index.ts

@@ -0,0 +1,5 @@
+import request from '@/config/axios'
+
+export const getRoleListApi = () => {
+  return request.get({ url: '/role/table' })
+}

+ 1 - 1
src/components/Form/src/helper/index.ts

@@ -146,7 +146,7 @@ export const initModel = (schema: FormSchema[], formModel: Recordable) => {
   schema.map((v) => {
     if (v.remove) {
       delete model[v.field]
-    } else if (v.component && v.component !== 'Divider') {
+    } else if (v.component !== 'Divider') {
       // const hasField = Reflect.has(model, v.field)
       const hasField = get(model, v.field)
       // 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值

+ 6 - 0
src/locales/en.ts

@@ -523,6 +523,12 @@ export default {
     canTo: 'Can to',
     name: 'Name'
   },
+  role: {
+    roleName: 'Role name',
+    role: 'Role',
+    // 菜单分配
+    menu: 'Menu allocation'
+  },
   inputPasswordDemo: {
     title: 'InputPassword',
     inputPasswordDes: 'Secondary packaging of Input components based on ElementPlus'

+ 5 - 0
src/locales/zh-CN.ts

@@ -517,6 +517,11 @@ export default {
     canTo: '是否可跳转',
     name: '组件名称'
   },
+  role: {
+    roleName: '角色名称',
+    role: '角色',
+    menu: '菜单分配'
+  },
   inputPasswordDemo: {
     title: '密码输入框',
     inputPasswordDes: '基于 ElementPlus 的 Input 组件二次封装'

+ 1 - 1
src/views/Authorization/Department/components/Write.vue

@@ -34,7 +34,7 @@ const submit = async () => {
     console.log(err)
   })
   if (valid) {
-    const formData = getFormData()
+    const formData = await getFormData()
     return formData
   }
 }

+ 22 - 22
src/views/Authorization/Menu/components/Write.vue

@@ -64,27 +64,27 @@ const formSchema = reactive<FormSchema[]>([
     label: t('menu.activeMenu'),
     component: 'Input'
   },
-  {
-    field: 'meta.permission',
-    label: t('menu.permission'),
-    component: 'CheckboxGroup',
-    componentProps: {
-      options: [
-        {
-          label: 'add',
-          value: 'add'
-        },
-        {
-          label: 'edit',
-          value: 'edit'
-        },
-        {
-          label: 'delete',
-          value: 'delete'
-        }
-      ]
-    }
-  },
+  // {
+  //   field: 'meta.permission',
+  //   label: t('menu.permission'),
+  //   component: 'CheckboxGroup',
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         label: 'add',
+  //         value: 'add'
+  //       },
+  //       {
+  //         label: 'edit',
+  //         value: 'edit'
+  //       },
+  //       {
+  //         label: 'delete',
+  //         value: 'delete'
+  //       }
+  //     ]
+  //   }
+  // },
   {
     field: 'meta.hidden',
     label: t('menu.hidden'),
@@ -137,7 +137,7 @@ const submit = async () => {
     console.log(err)
   })
   if (valid) {
-    const formData = getFormData()
+    const formData = await getFormData()
     return formData
   }
 }

+ 162 - 87
src/views/Authorization/Role/Role.vue

@@ -1,91 +1,166 @@
-<script setup lang="ts">
-// import { ContentWrap } from '@/components/ContentWrap'
-// import { useI18n } from '@/hooks/web/useI18n'
-// import { Table } from '@/components/Table'
-// import { getUserListApi } from '@/api/login'
-// import { UserType } from '@/api/login/types'
-// import { ref, h } from 'vue'
-// import { ElButton } from 'element-plus'
-// import { TableColumn, TableSlotDefault } from '@/types/table'
-
-// interface Params {
-//   pageIndex?: number
-//   pageSize?: number
-// }
-
-// const { t } = useI18n()
-
-// const columns: TableColumn[] = [
-//   {
-//     field: 'index',
-//     label: t('userDemo.index'),
-//     type: 'index'
-//   },
-//   {
-//     field: 'username',
-//     label: t('userDemo.username')
-//   },
-//   {
-//     field: 'password',
-//     label: t('userDemo.password')
-//   },
-//   {
-//     field: 'role',
-//     label: t('userDemo.role')
-//   },
-//   {
-//     field: 'remark',
-//     label: t('userDemo.remark'),
-//     formatter: (row: UserType) => {
-//       return h(
-//         'span',
-//         row.username === 'admin' ? t('userDemo.remarkMessage1') : t('userDemo.remarkMessage2')
-//       )
-//     }
-//   },
-//   {
-//     field: 'action',
-//     label: t('userDemo.action')
-//   }
-// ]
-
-// const loading = ref(true)
-
-// let tableDataList = ref<UserType[]>([])
-
-// const getTableList = async (params?: Params) => {
-//   const res = await getUserListApi({
-//     params: params || {
-//       pageIndex: 1,
-//       pageSize: 10
-//     }
-//   })
-//   // .catch(() => {})
-//   // .finally(() => {
-//   //   loading.value = false
-//   // })
-//   if (res) {
-//     tableDataList.value = res.data.list
-//     loading.value = false
-//   }
-// }
-
-// getTableList()
-
-// const actionFn = (data: TableSlotDefault) => {
-//   console.log(data)
-// }
+<script setup lang="tsx">
+import { reactive, ref, unref } from 'vue'
+import { getRoleListApi } from '@/api/role'
+import { useTable } from '@/hooks/web/useTable'
+import { useI18n } from '@/hooks/web/useI18n'
+import { Table, TableColumn } from '@/components/Table'
+import { ElButton, ElTag } from 'element-plus'
+import { Search } from '@/components/Search'
+import { FormSchema } from '@/components/Form'
+import { ContentWrap } from '@/components/ContentWrap'
+import Write from './components/Write.vue'
+import { Dialog } from '@/components/Dialog'
+
+const { t } = useI18n()
+
+const { tableRegister, tableState, tableMethods } = useTable({
+  fetchDataApi: async () => {
+    const res = await getRoleListApi()
+    return {
+      list: res.data.list || [],
+      total: res.data.total
+    }
+  }
+})
+
+const { dataList, loading, total } = tableState
+const { getList } = tableMethods
+
+const tableColumns = reactive<TableColumn[]>([
+  {
+    field: 'index',
+    label: t('userDemo.index'),
+    type: 'index'
+  },
+  {
+    field: 'roleName',
+    label: t('role.roleName')
+  },
+  {
+    field: 'role',
+    label: t('role.role')
+  },
+  {
+    field: 'status',
+    label: t('menu.status'),
+    slots: {
+      default: (data: any) => {
+        return (
+          <>
+            <ElTag type={data[0].row.status === 0 ? 'danger' : 'success'}>
+              {data[0].row.status === 1 ? t('userDemo.enable') : t('userDemo.disable')}
+            </ElTag>
+          </>
+        )
+      }
+    }
+  },
+  {
+    field: 'createTime',
+    label: t('tableDemo.displayTime')
+  },
+  {
+    field: 'remark',
+    label: t('userDemo.remark')
+  },
+  {
+    field: 'action',
+    label: t('userDemo.action'),
+    width: 240,
+    slots: {
+      default: (data: any) => {
+        const row = data[0].row
+        return (
+          <>
+            <ElButton type="primary" onClick={() => action(row, 'edit')}>
+              {t('exampleDemo.edit')}
+            </ElButton>
+            <ElButton type="danger">{t('exampleDemo.del')}</ElButton>
+          </>
+        )
+      }
+    }
+  }
+])
+
+const searchSchema = reactive<FormSchema[]>([
+  {
+    field: 'roleName',
+    label: t('role.roleName'),
+    component: 'Input'
+  }
+])
+
+const searchParams = ref({})
+const setSearchParams = (data: any) => {
+  searchParams.value = data
+  getList()
+}
+
+const dialogVisible = ref(false)
+const dialogTitle = ref('')
+
+const currentRow = ref()
+const actionType = ref('')
+
+const writeRef = ref<ComponentRef<typeof Write>>()
+
+const saveLoading = ref(false)
+
+const action = (row: any, type: string) => {
+  dialogTitle.value = t(type === 'edit' ? 'exampleDemo.edit' : 'exampleDemo.detail')
+  actionType.value = type
+  currentRow.value = row
+  dialogVisible.value = true
+}
+
+const AddAction = () => {
+  dialogTitle.value = t('exampleDemo.add')
+  currentRow.value = undefined
+  dialogVisible.value = true
+  actionType.value = ''
+}
+
+const save = async () => {
+  const write = unref(writeRef)
+  const formData = await write?.submit()
+  if (formData) {
+    saveLoading.value = true
+    setTimeout(() => {
+      saveLoading.value = false
+      dialogVisible.value = false
+    }, 1000)
+  }
+}
 </script>
 
 <template>
-  <div>role</div>
-  <!-- <ContentWrap :title="t('userDemo.title')" :message="t('userDemo.message')">
-    <Table :columns="columns" :data="tableDataList" :loading="loading" :selection="false">
-      <template #action="data">
-        <ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
-          {{ t('tableDemo.action') }}
-        </ElButton>
-      </template>
-    </Table>
-  </ContentWrap> -->
+  <ContentWrap>
+    <Search :schema="searchSchema" @reset="setSearchParams" @search="setSearchParams" />
+    <div class="mb-10px">
+      <ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
+    </div>
+    <Table
+      :columns="tableColumns"
+      default-expand-all
+      node-key="id"
+      :data="dataList"
+      :loading="loading"
+      :pagination="{
+        total
+      }"
+      @register="tableRegister"
+    />
+  </ContentWrap>
+
+  <Dialog v-model="dialogVisible" :title="dialogTitle">
+    <Write v-if="actionType !== 'detail'" ref="writeRef" :current-row="currentRow" />
+
+    <template #footer>
+      <ElButton v-if="actionType !== 'detail'" type="primary" :loading="saveLoading" @click="save">
+        {{ t('exampleDemo.save') }}
+      </ElButton>
+      <ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
+    </template>
+  </Dialog>
 </template>

+ 160 - 0
src/views/Authorization/Role/components/Write.vue

@@ -0,0 +1,160 @@
+<script setup lang="tsx">
+import { Form, FormSchema } from '@/components/Form'
+import { useForm } from '@/hooks/web/useForm'
+import { PropType, reactive, watch, ref, unref } from 'vue'
+import { useValidator } from '@/hooks/web/useValidator'
+import { useI18n } from '@/hooks/web/useI18n'
+import { ElTree, ElCheckboxGroup, ElCheckbox } from 'element-plus'
+import { getMenuListApi } from '@/api/menu'
+import { filter } from '@/utils/tree'
+
+const { t } = useI18n()
+
+const { required } = useValidator()
+
+const props = defineProps({
+  currentRow: {
+    type: Object as PropType<any>,
+    default: () => null
+  }
+})
+
+const treeRef = ref<typeof ElTree>()
+
+const formSchema = ref<FormSchema[]>([
+  {
+    field: 'roleName',
+    label: t('role.roleName'),
+    component: 'Input'
+  },
+  {
+    field: 'role',
+    label: t('role.role'),
+    component: 'Input'
+  },
+  {
+    field: 'status',
+    label: t('menu.status'),
+    component: 'Select',
+    componentProps: {
+      options: [
+        {
+          label: t('userDemo.disable'),
+          value: 0
+        },
+        {
+          label: t('userDemo.enable'),
+          value: 1
+        }
+      ]
+    }
+  },
+  {
+    field: 'menu',
+    label: t('role.menu'),
+    colProps: {
+      span: 24
+    },
+    formItemProps: {
+      slots: {
+        default: (formData: any) => {
+          console.log(formData)
+          return (
+            <>
+              <div class="flex w-full">
+                <div class="flex-1">
+                  <ElTree
+                    ref={treeRef}
+                    show-checkbox
+                    node-key="id"
+                    highlight-current
+                    data={treeData.value}
+                    onNode-click={nodeClick}
+                  >
+                    {{
+                      default: (data) => {
+                        return <span>{data.data.meta.title}</span>
+                      }
+                    }}
+                  </ElTree>
+                </div>
+                <div class="flex-1">
+                  {unref(currentTreeData) && unref(currentTreeData)?.meta?.permission ? (
+                    <ElCheckboxGroup v-model={unref(currentTreeData).meta.currentPermission}>
+                      {unref(currentTreeData)?.meta?.permission.map((v: string) => {
+                        return <ElCheckbox label={v} />
+                      })}
+                    </ElCheckboxGroup>
+                  ) : null}
+                </div>
+              </div>
+            </>
+          )
+        }
+      }
+    }
+  }
+])
+
+const currentTreeData = ref()
+const nodeClick = (treeData: any) => {
+  currentTreeData.value = treeData
+}
+
+const rules = reactive({
+  roleName: [required()],
+  role: [required()],
+  status: [required()]
+})
+
+const { formRegister, formMethods } = useForm()
+const { setValues, getFormData, getElFormExpose } = formMethods
+
+const treeData = ref([])
+const getMenuList = async () => {
+  const res = await getMenuListApi()
+  if (res) {
+    treeData.value = res.data.list
+  }
+}
+getMenuList()
+
+const submit = async () => {
+  const elForm = await getElFormExpose()
+  const valid = await elForm?.validate().catch((err) => {
+    console.log(err)
+  })
+  if (valid) {
+    const formData = await getFormData()
+    const checkedKeys = [
+      ...(unref(treeRef)?.getCheckedKeys() || []),
+      ...(unref(treeRef)?.getHalfCheckedKeys() || [])
+    ]
+    const data = filter(unref(treeData), (item: any) => {
+      return checkedKeys.includes(item.id)
+    })
+    formData.menu = data || []
+    return formData
+  }
+}
+
+watch(
+  () => props.currentRow,
+  (currentRow) => {
+    if (!currentRow) return
+    setValues(currentRow)
+  },
+  {
+    deep: true,
+    immediate: true
+  }
+)
+
+defineExpose({
+  submit
+})
+</script>
+
+<template>
+  <Form :rules="rules" @register="formRegister" :schema="formSchema" />
+</template>

+ 1 - 1
src/views/Authorization/User/components/Write.vue

@@ -36,7 +36,7 @@ const submit = async () => {
     console.log(err)
   })
   if (valid) {
-    const formData = getFormData()
+    const formData = await getFormData()
     return formData
   }
 }

+ 1 - 1
src/views/Example/Dialog/components/Write.vue

@@ -36,7 +36,7 @@ const submit = async () => {
     console.log(err)
   })
   if (valid) {
-    const formData = getFormData()
+    const formData = await getFormData()
     return formData
   }
 }

+ 1 - 1
src/views/Example/Page/components/Write.vue

@@ -120,7 +120,7 @@ const submit = async () => {
     console.log(err)
   })
   if (valid) {
-    const formData = getFormData()
+    const formData = await getFormData()
     return formData
   }
 }