Pārlūkot izejas kodu

管理中心调整

CzRger 3 nedēļas atpakaļ
vecāks
revīzija
b216298647

+ 1 - 0
src/components/czr-ui/CzrButton.vue

@@ -85,6 +85,7 @@ const props = defineProps({
   font-size: 0.88rem;
   color: #606266;
   line-height: 1;
+  word-break: keep-all;
   .svg-icon {
     margin-right: 6px;
   }

+ 2 - 0
src/layout/top-left/head/index.vue

@@ -187,6 +187,7 @@ onMounted(() => {
     color: transparent;
     background-clip: text;
     font-family: Alimama;
+    word-break: keep-all;
   }
   .menus {
     margin-left: 5rem;
@@ -197,6 +198,7 @@ onMounted(() => {
       font-weight: bold;
       font-size: 1.13rem;
       color: #303133;
+      word-break: keep-all;
       &.active {
         color: var(--czr-main-color);
       }

+ 6 - 6
src/layout/top-left/index.vue

@@ -4,12 +4,12 @@
       <HeadCom />
     </div>
     <div class="top-left-layout-center">
-      <div
-        class="top-left-layout-center-sub-menu"
-        v-if="$route.matched.length > 2"
-      >
-        <SubMenuCom />
-      </div>
+      <!--      <div-->
+      <!--        class="top-left-layout-center-sub-menu"-->
+      <!--        v-if="$route.matched.length > 2"-->
+      <!--      >-->
+      <!--        <SubMenuCom />-->
+      <!--      </div>-->
       <div class="top-left-layout-center-content">
         <!--        <BreadcrumbCom v-if="$route.matched.length > 2"/>-->
         <div class="top-left-layout-center-content-views">

+ 51 - 0
src/router/modules/big-model.ts

@@ -128,6 +128,57 @@ const BigModelRouter = [
     meta: {
       title: '管理中心',
     },
+    redirect: '/center/user',
+    children: [
+      {
+        path: 'tenant',
+        name: '7b05e9a1-37cc-4701-b10c-ad1e31121ab5',
+        component: () => import('@/views/manage/center/tenant/index.vue'),
+        meta: {
+          title: '租户管理',
+        },
+      },
+      {
+        path: 'role',
+        name: 'ef9f545d-803e-4fbe-97cf-c89e27bd02ce',
+        component: () => import('@/views/manage/center/role/index.vue'),
+        meta: {
+          title: '角色管理',
+        },
+      },
+      {
+        path: 'user',
+        name: 'd791e13b-9e49-4697-aef1-0bcb3d05aa0c',
+        component: () => import('@/views/manage/center/user/index.vue'),
+        meta: {
+          title: '用户管理',
+        },
+      },
+      {
+        path: 'approve',
+        name: 'c3c3bee8-70ed-43b5-beb4-d0d7541a1e5e',
+        component: () => import('@/views/manage/center/approve/index.vue'),
+        meta: {
+          title: '审批流程配置管理',
+        },
+      },
+      {
+        path: 'safe',
+        name: '9da8b83f-d7f9-4081-b3f3-0d637382349f',
+        component: () => import('@/views/manage/center/safe/index.vue'),
+        meta: {
+          title: '安全管理',
+        },
+      },
+      {
+        path: 'api',
+        name: 'e995a6b2-d230-4b36-a714-d4d01f92ad36',
+        component: () => import('@/views/manage/center/api/index.vue'),
+        meta: {
+          title: 'API服务管控',
+        },
+      },
+    ],
   },
 ]
 

+ 13 - 60
src/views/manage/center/index.vue

@@ -1,32 +1,24 @@
 <template>
   <div class="bm-main-box" style="padding: 0">
     <div class="flex gap-4 px-4 pt-4">
-      <template v-for="item in menus">
+      <template v-for="item in menusCpt">
         <div
           class="__hover flex flex-col items-center"
           :class="
-            state.menu === item.value
+            $route.name === item.name
               ? 'text-base font-bold text-[var(--czr-main-color)]'
               : 'text-sm text-[#576275]'
           "
-          @click="
-            () => {
-              state.menu = item.value
-              $router.replace({
-                name: '3b046708-5a14-450f-9dcd-9d869e336ed7',
-                query: { menu: item.value },
-              })
-            }
-          "
+          @click="$router.push({ name: item.name })"
         >
           <div class="flex h-4 items-center justify-center">
-            {{ item.label }}
+            {{ item.meta?.title }}
           </div>
           <div class="mt-1.75 w-full px-2">
             <div
               class="h-0.5 w-full"
               :class="
-                state.menu === item.value ? 'bg-[var(--czr-main-color)]' : ''
+                $route.name === item.namee ? 'bg-[var(--czr-main-color)]' : ''
               "
             />
           </div>
@@ -34,64 +26,25 @@
       </template>
     </div>
     <div class="flex-1">
-      <component :is="menus.filter((v) => v.value === state.menu)[0]?.com" />
+      <router-view />
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import {
-  defineAsyncComponent,
-  getCurrentInstance,
-  onBeforeMount,
-  reactive,
-  ref,
-} from 'vue'
+import { computed, getCurrentInstance } from 'vue'
 import { useRoute } from 'vue-router'
 
 const route = useRoute()
 const emit = defineEmits([])
 const props = defineProps({})
 const { proxy }: any = getCurrentInstance()
-const menus = [
-  {
-    label: '用户管理',
-    value: 'user',
-    com: defineAsyncComponent(() => import('./user/index.vue')),
-  },
-  {
-    label: '租户管理',
-    value: 'tenant',
-    com: defineAsyncComponent(
-      () => import('@/views/manage/center/tenant/index.vue'),
-    ),
-  },
-  {
-    label: '审批流程配置管理',
-    value: 'approve',
-    com: defineAsyncComponent(() => import('./approve/index.vue')),
-  },
-  {
-    label: '安全管理',
-    value: 'safe',
-    com: defineAsyncComponent(() => import('./safe/index.vue')),
-  },
-  {
-    label: 'API服务管控',
-    value: 'api',
-    com: defineAsyncComponent(() => import('./api/index.vue')),
-  },
-]
-const state: any = reactive({
-  menu: null,
-})
-onBeforeMount(() => {
-  const m = route.query.menu
-  if (m && menus.some((v) => v.value === m)) {
-    state.menu = m
-  } else {
-    state.menu = menus[0].value
-  }
+const menusCpt = computed(() => {
+  return (
+    route.matched.filter(
+      (v) => v.name === '3b046708-5a14-450f-9dcd-9d869e336ed7',
+    )?.[0].children || []
+  )
 })
 </script>
 

+ 75 - 0
src/views/manage/center/role/auth.vue

@@ -0,0 +1,75 @@
+<template>
+  <CzrDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    width="62.5rem"
+    height="auto"
+    max-height="90%"
+    :loading="state.loading"
+    :show-close="false"
+    :show-submit="false"
+  >
+    <div class="bm-form"></div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  computed,
+  getCurrentInstance,
+  nextTick,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { useRouter } from 'vue-router'
+
+const DialogStore = useDialogStore()
+const emit = defineEmits(['update:show', 'refresh'])
+const { proxy } = getCurrentInstance()
+const props = defineProps({
+  show: { default: false },
+  transfer: <any>{},
+})
+const state: any = reactive({
+  loading: false,
+  form: {},
+})
+const ref_form = ref()
+const titleCpt = computed(() => {
+  let t = '授权'
+  return t
+})
+watch(
+  () => props.show,
+  (n) => {
+    if (n) {
+      initDictionary()
+      state.form = {}
+      if (props.transfer.mode !== 'add') {
+        initData()
+      }
+      nextTick(() => {
+        ref_form.value.reset()
+      })
+    }
+  },
+)
+const initDictionary = () => {}
+const initData = () => {
+  // state.loading = true
+  // userDetail(props.transfer.id)
+  //   .then(({ data }: any) => {
+  //     state.form = data
+  //   })
+  //   .catch(() => {})
+  //   .finally(() => {
+  //     state.loading = false
+  //   })
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 137 - 0
src/views/manage/center/role/detail.vue

@@ -0,0 +1,137 @@
+<template>
+  <CzrDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    @onSubmit="onSubmit"
+    width="42.5rem"
+    height="auto"
+    max-height="90%"
+    :loading="state.loading"
+  >
+    <div class="bm-form">
+      <CzrForm ref="ref_form" :form-view="isViewCpt">
+        <CzrFormColumn
+          required
+          :span="24"
+          label="角色名称"
+          v-model:param="state.form.name"
+        />
+      </CzrForm>
+    </div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  computed,
+  getCurrentInstance,
+  nextTick,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { useRouter } from 'vue-router'
+
+const DialogStore = useDialogStore()
+const emit = defineEmits(['update:show', 'refresh'])
+const { proxy } = getCurrentInstance()
+const props = defineProps({
+  show: { default: false },
+  transfer: <any>{},
+})
+const state: any = reactive({
+  loading: false,
+  form: {},
+})
+const ref_form = ref()
+const titleCpt = computed(() => {
+  let t = '角色'
+  switch (props.transfer.mode) {
+    case 'add':
+      t = '新增' + t
+      break
+    case 'edit':
+      t = '编辑' + t
+      break
+    case 'view':
+      t = '查看' + t
+      break
+  }
+  return t
+})
+const isViewCpt = computed(() => props.transfer?.mode === 'view')
+watch(
+  () => props.show,
+  (n) => {
+    if (n) {
+      initDictionary()
+      state.form = {}
+      if (props.transfer.mode !== 'add') {
+        initData()
+      }
+      nextTick(() => {
+        ref_form.value.reset()
+      })
+    }
+  },
+)
+const initDictionary = () => {}
+const initData = () => {
+  // state.loading = true
+  // userDetail(props.transfer.id)
+  //   .then(({ data }: any) => {
+  //     state.form = data
+  //   })
+  //   .catch(() => {})
+  //   .finally(() => {
+  //     state.loading = false
+  //   })
+}
+const onSubmit = () => {
+  ref_form.value
+    .submit()
+    .then(() => {
+      DialogStore.confirm({
+        content: `请确认是否提交?`,
+        onSubmit: () => {
+          state.loading = true
+          if (props.transfer.mode === 'add') {
+            // userAdd(state.form)
+            //   .then(({ data }: any) => {
+            //     ElMessage.success(`${titleCpt.value}成功!`)
+            //     emit('update:show', false)
+            //     emit('refresh')
+            //   })
+            //   .catch(() => {})
+            //   .finally(() => {
+            //     state.loading = false
+            //   })
+          } else {
+            // userEdit(state.form)
+            //   .then(({ data }: any) => {
+            //     ElMessage.success(`${titleCpt.value}成功!`)
+            //     emit('update:show', false)
+            //     emit('refresh')
+            //   })
+            //   .catch(() => {})
+            //   .finally(() => {
+            //     state.loading = false
+            //   })
+          }
+        },
+      })
+    })
+    .catch((e) => {
+      ElMessage({
+        message: e[0].message,
+        grouping: true,
+        type: 'warning',
+      })
+    })
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 272 - 0
src/views/manage/center/role/index.vue

@@ -0,0 +1,272 @@
+<template>
+  <CzrContent
+    v-model:tableHead="state.query.head"
+    @handleReset="onReset"
+    @handleSearch="onSearch"
+  >
+    <template #tableTitle>
+      <div class="flex gap-2.5"></div>
+    </template>
+    <template #buttons>
+      <div class="flex items-center gap-2.5">
+        <CzrForm class="bm-filter" label-width="0px" @handleEnter="onSearch">
+          <CzrFormColumn
+            width="15.63rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.text"
+            placeholder="输入关键词以检索"
+            :prefix-icon="Search"
+          />
+          <CzrButton type="add" @click="onAdd" title="新增角色" />
+        </CzrForm>
+      </div>
+    </template>
+    <template #table>
+      <CzrTable
+        v-loading="state.query.loading"
+        v-model:data="state.query.result.data"
+        :head="state.query.head"
+        :total="state.query.result.total"
+        :page="state.query.page.pageNum"
+        :pageSize="state.query.page.pageSize"
+        @handlePage="onPage"
+        @handleSort="onSort"
+        v-model:selected="state.query.selected"
+      >
+        <template #caozuo-column-value="{ scope }">
+          <div class="__czr-table-operations">
+            <CzrButton type="table" title="编辑" @click="onEdit(scope.row)" />
+            <CzrButton type="table-del" @click="onDel(scope.row)" />
+            <CzrButton
+              type="table"
+              title="关联用户"
+              @click="onRelation(scope.row)"
+            />
+            <CzrButton type="table" title="授权" @click="onAuth(scope.row)" />
+          </div>
+        </template>
+      </CzrTable>
+    </template>
+  </CzrContent>
+  <detailCom
+    v-model:show="state.detail.show"
+    :transfer="state.detail.transfer"
+    @refresh="onSearch"
+  />
+  <relationCom
+    v-model:show="state.relation.show"
+    :transfer="state.relation.transfer"
+    @refresh="onSearch"
+  />
+  <authCom
+    v-model:show="state.auth.show"
+    :transfer="state.auth.transfer"
+    @refresh="onSearch"
+  />
+</template>
+
+<script setup lang="ts">
+import {
+  computed,
+  getCurrentInstance,
+  onMounted,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
+import { CopyDocument, Search } from '@element-plus/icons-vue'
+import { debounce } from 'lodash'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { ElMessage } from 'element-plus'
+import detailCom from './detail.vue'
+import relationCom from './relation.vue'
+import authCom from './auth.vue'
+import { useRouter } from 'vue-router'
+
+const AppStore = useAppStore()
+const DialogStore = useDialogStore()
+const DictionaryStore = useDictionaryStore()
+const router = useRouter()
+const emit = defineEmits([])
+const props = defineProps({})
+const { proxy }: any = getCurrentInstance()
+const state: any = reactive({
+  text: '',
+  query: {
+    init: false,
+    loading: false,
+    head: [
+      { value: 'xxx', label: '角色名称', show: true },
+      {
+        value: 'xxx',
+        label: '关联用户数量',
+        show: true,
+        sort: true,
+      },
+      {
+        value: 'xxx',
+        label: '更新时间',
+        show: true,
+        width: 180,
+        datetime: true,
+        sort: true,
+      },
+      {
+        value: 'caozuo',
+        label: '操作',
+        show: true,
+        width: 300,
+        fixed: 'right',
+        popover: false,
+      },
+    ],
+    page: {
+      pageNum: 1,
+      pageSize: 20,
+    },
+    form: {},
+    formReal: {},
+    sort: {},
+    result: {
+      total: 0,
+      data: [],
+    },
+    selected: [],
+  },
+  detail: {
+    show: false,
+    transfer: {},
+  },
+  relation: {
+    show: false,
+    transfer: {},
+  },
+  auth: {
+    show: false,
+    transfer: {},
+  },
+})
+const setText = debounce((v) => {
+  state.query.form.name = v
+}, 1000)
+watch(
+  () => state.text,
+  (n) => {
+    setText(n)
+  },
+)
+watch(
+  () => state.query.form,
+  (n) => {
+    if (state.query.init) {
+      onSearch()
+    }
+  },
+  { deep: true },
+)
+const onSort = ({ key, value }) => {
+  state.query.sort[key] = value
+  onSearch()
+}
+const onPage = (pageNum, pageSize) => {
+  setTimeout(() => {
+    state.query.init = true
+  }, 100)
+  state.query.page = {
+    pageNum: pageNum,
+    pageSize: pageSize,
+  }
+  const params = {
+    page: state.query.page.pageNum,
+    size: state.query.page.pageSize,
+  }
+  //  添加表单参数
+  for (const [k, v] of Object.entries(state.query.formReal)) {
+    if (proxy.$czrUtil.isValue(v)) {
+      params[k] = v
+    }
+  }
+
+  //  添加排序参数
+  for (const [k, v] of Object.entries(state.query.sort)) {
+  }
+  state.query.result.data = [{}]
+  // state.query.loading = true
+  // userPage(params)
+  //   .then(({ data }: any) => {
+  //     state.query.result.total = data.totalElements
+  //     state.query.result.data = data.content
+  //   })
+  //   .catch(() => {})
+  //   .finally(() => {
+  //     state.query.loading = false
+  //   })
+}
+const onSearch = () => {
+  state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
+  onPage(1, state.query.page.pageSize)
+}
+const onReset = () => {
+  state.query.page = {
+    pageNum: 1,
+    pageSize: 20,
+  }
+  state.query.form = {
+    tenantId: AppStore.tenantInfo.id,
+  }
+  state.query.sort = {}
+  onSearch()
+}
+const onAdd = () => {
+  state.detail.transfer = {
+    mode: 'add',
+  }
+  state.detail.show = true
+}
+const onEdit = (row) => {
+  state.detail.transfer = {
+    mode: 'edit',
+    id: row.id,
+  }
+  state.detail.show = true
+}
+const onDel = (row: any) => {
+  DialogStore.confirm({
+    title: '删除确认',
+    content: `请确认是否删除${row.name}?`,
+    onSubmit: () => {
+      // userDel(row.id)
+      //   .then(() => {
+      //     ElMessage.success('删除成功!')
+      //   })
+      //   .catch(() => {})
+      //   .finally(() => {
+      //     onSearch()
+      //   })
+    },
+  })
+}
+const onRelation = (row) => {
+  state.relation.transfer = {
+    id: row.id,
+  }
+  state.relation.show = true
+}
+const onAuth = (row) => {
+  state.auth.transfer = {
+    id: row.id,
+  }
+  state.auth.show = true
+}
+onMounted(() => {
+  initDictionary()
+  onReset()
+})
+const initDictionary = () => {
+  DictionaryStore.initTenants()
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 75 - 0
src/views/manage/center/role/relation.vue

@@ -0,0 +1,75 @@
+<template>
+  <CzrDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    width="62.5rem"
+    height="auto"
+    max-height="90%"
+    :loading="state.loading"
+    :show-close="false"
+    :show-submit="false"
+  >
+    <div class="bm-form"></div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  computed,
+  getCurrentInstance,
+  nextTick,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { useRouter } from 'vue-router'
+
+const DialogStore = useDialogStore()
+const emit = defineEmits(['update:show', 'refresh'])
+const { proxy } = getCurrentInstance()
+const props = defineProps({
+  show: { default: false },
+  transfer: <any>{},
+})
+const state: any = reactive({
+  loading: false,
+  form: {},
+})
+const ref_form = ref()
+const titleCpt = computed(() => {
+  let t = '关联用户'
+  return t
+})
+watch(
+  () => props.show,
+  (n) => {
+    if (n) {
+      initDictionary()
+      state.form = {}
+      if (props.transfer.mode !== 'add') {
+        initData()
+      }
+      nextTick(() => {
+        ref_form.value.reset()
+      })
+    }
+  },
+)
+const initDictionary = () => {}
+const initData = () => {
+  // state.loading = true
+  // userDetail(props.transfer.id)
+  //   .then(({ data }: any) => {
+  //     state.form = data
+  //   })
+  //   .catch(() => {})
+  //   .finally(() => {
+  //     state.loading = false
+  //   })
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 1 - 14
src/views/manage/center/tenant/index.vue

@@ -270,17 +270,4 @@ onMounted(() => {
 const initDictionary = () => {}
 </script>
 
-<style lang="scss" scoped>
-.model {
-  width: 100%;
-  background-image: url('@/assets/images/model/model-icon-7.png');
-  background-repeat: no-repeat;
-  background-size: 100% 100%;
-  padding: 1rem;
-  border-radius: 10px;
-  box-shadow: 0rem 0.25rem 0.63rem 0rem rgba(40, 83, 247, 0.05);
-  border: var(--czr-border);
-  display: flex;
-  flex-direction: column;
-}
-</style>
+<style lang="scss" scoped></style>

+ 1 - 14
src/views/manage/center/user/index.vue

@@ -377,17 +377,4 @@ const initDictionary = () => {
 }
 </script>
 
-<style lang="scss" scoped>
-.model {
-  width: 100%;
-  background-image: url('@/assets/images/model/model-icon-7.png');
-  background-repeat: no-repeat;
-  background-size: 100% 100%;
-  padding: 1rem;
-  border-radius: 10px;
-  box-shadow: 0rem 0.25rem 0.63rem 0rem rgba(40, 83, 247, 0.05);
-  border: var(--czr-border);
-  display: flex;
-  flex-direction: column;
-}
-</style>
+<style lang="scss" scoped></style>