Bladeren bron

fix: 修改匹配机制

bill 2 jaren geleden
bovenliggende
commit
e7142b56a5
9 gewijzigde bestanden met toevoegingen van 115 en 53 verwijderingen
  1. 3 1
      src/api/constant.ts
  2. 5 1
      src/api/role.ts
  3. 4 2
      src/main.ts
  4. 15 2
      src/store/project.ts
  5. 48 13
      src/store/roles.ts
  6. 3 14
      src/store/user.ts
  7. 6 13
      src/views/project/columns.ts
  8. 12 1
      src/views/project/detailed.vue
  9. 19 6
      src/views/role/edit.vue

+ 3 - 1
src/api/constant.ts

@@ -59,5 +59,7 @@ export const ADD_ROLE = '/smart-site/role/addOrUpdate'
 export const DEL_ROLE = '/smart-site/projectRole/deleteUser'
 export const UPDATE_ROLE = '/smart-site/role/addOrUpdate'
 export const ROLE_OPTIONS = '/smart-site/menu/treeselect/all'
-export const USER_ROLE_OPTIONS = '/smart-site/menu/treeselect'
+// export const USER_ROLE_OPTIONS = '/smart-site/menu/treeselect'
+export const USER_ROLE_OPTIONS = '/smart-site/menu/menuselect'
+export const PROJECT_ROLE_OPTIONS = '/smart-site/menu/treeselect'
 export const SELECT_OPTIONS = '/smart-site/role/select'

+ 5 - 1
src/api/role.ts

@@ -6,7 +6,8 @@ import {
   UPDATE_ROLE,
   ROLE_OPTIONS,
   USER_ROLE_OPTIONS,
-  SELECT_OPTIONS
+  SELECT_OPTIONS,
+  PROJECT_ROLE_OPTIONS
 } from './constant'
 import type { PageResult, PageRequest, Project } from './'
 import { RoutesName } from '@/router'
@@ -51,5 +52,8 @@ export const fetchRoleOptions = () => axios.post<RoleOptions>(ROLE_OPTIONS, {})
 export const fetchUserRoleOptions = () =>
   axios.post<RoleOptions>(USER_ROLE_OPTIONS, {})
 
+export const fetchProjectRoleOptions = (projectId: Project['projectId']) =>
+  axios.post<RoleOptions>(PROJECT_ROLE_OPTIONS, { projectId })
+
 export const fetchRoleSelects = (projectId: Project['projectId']) =>
   axios.post<Roles>(SELECT_OPTIONS, { projectId })

+ 4 - 2
src/main.ts

@@ -4,7 +4,7 @@ import 'ant-design-vue/lib/message/style/index.less'
 import './style.scss'
 import App from './App.vue'
 import { router, enableRouteNames } from './router'
-import { pinia, useUserStore } from './store'
+import { pinia, useProject, useUserStore } from './store'
 
 export const app = createApp(App)
 app.use(router)
@@ -12,9 +12,11 @@ app.use(pinia)
 app.mount('#app')
 
 const userStore = useUserStore(pinia)
+const projectStore = useProject(pinia)
 
 watch(
-  () => userStore.roleMenus,
+  () =>
+    Array.from(new Set([...userStore.roleMenus, ...projectStore.roleMenus])),
   nMenus => {
     enableRouteNames([...nMenus])
   },

+ 15 - 2
src/store/project.ts

@@ -1,5 +1,6 @@
 import { defineStore } from 'pinia'
 import { useUserStore } from './user'
+import { transformNames } from './roles'
 import {
   fetchProject,
   uploadProjectBimScene,
@@ -11,7 +12,8 @@ import {
   deleteProjectBimScene,
   BimStatus,
   deleteProjectScene,
-  updateProjectBimSceneName
+  updateProjectBimSceneName,
+  fetchProjectRoleOptions
 } from '@/api'
 
 import type {
@@ -21,10 +23,17 @@ import type {
   UpdateProjectData,
   Bim
 } from '@/api'
+import { RoutesName } from '@/router/constant'
 
 export const BinType = Symbol('bin')
 export const binTypeDesc = 'BIM'
 export type { Project, BimUploadData, Bim }
+export const DefaultMenus = [
+  RoutesName.projectScenes,
+  RoutesName.projectTaggings,
+  RoutesName.projectMembers,
+  RoutesName.projectRoles
+]
 
 export type ProjectScene = Omit<Scene, 'type' | 'num' | 'status'> &
   (
@@ -48,7 +57,8 @@ type CurrentState = null | Project
 
 export const useProject = defineStore('project', {
   state: () => ({
-    current: null as CurrentState
+    current: null as CurrentState,
+    roleMenus: DefaultMenus
   }),
   getters: {
     scenes: state => {
@@ -77,6 +87,9 @@ export const useProject = defineStore('project', {
       state.current?.projectId === id
   },
   actions: {
+    async setRoles(id: Project['projectId']) {
+      this.roleMenus = transformNames(await fetchProjectRoleOptions(id))
+    },
     async setCurrent(id: Project['projectId']) {
       this.current = await fetchProject(id)
     },

+ 48 - 13
src/store/roles.ts

@@ -6,42 +6,77 @@ import type { RoleOptions } from '@/api'
 export type { RoleOptions, RoleOption } from '@/api'
 export { fetchRoleOptions } from '@/api'
 
-type MenuTree = { key: RoleOption['id']; title: string; children: MenuTree[] }
-const transformMenuTree = (roleOptions: RoleOptions): MenuTree[] => {
+export type MenuTree = {
+  key: RoleOption['id']
+  title: string
+  children: MenuTree[]
+}
+const transformMenuTree = (
+  roleOptions: RoleOptions,
+  disabledIds: RoleOption['id'][] = []
+): MenuTree[] => {
   return roleOptions.map(role => ({
     title: routesMetas[role.path].title,
     key: role.id,
-    children: role.children ? transformMenuTree(role.children) : []
+    children: role.children
+      ? transformMenuTree(role.children, disabledIds)
+      : [],
+    disabled: disabledIds.includes(role.id)
   }))
 }
 
+export const transformNames = (options: RoleOptions) => {
+  const names: RoutesName[] = []
+  for (const option of options) {
+    names.push(option.path)
+    if (option.children) {
+      names.push(...transformNames(option.children))
+    }
+  }
+  return names
+}
+
+const findRole = (
+  list: RoleOptions,
+  predicate: (option: RoleOption) => boolean
+): RoleOption | void => {
+  for (const option of list) {
+    if (predicate(option)) {
+      return option
+    } else if (option.children?.length) {
+      const selected = findRole(option.children, predicate)
+      if (selected) {
+        return selected
+      }
+    }
+  }
+}
+
 export const useRoleStore = defineStore('role', {
   state: () => ({
     list: [] as RoleOptions
   }),
   getters: {
     getRole: state => (name: RoutesName) =>
-      state.list.find(role => role.path === name)!,
+      findRole(state.list, role => role.path === name)!,
+    getName: state => (id: RoleOption['id']) =>
+      findRole(state.list, role => role.id === id)!.path,
     getRoles() {
       return (names: RoutesName[]) => names.map(name => this.getRole(name))
     },
-    getRoleId() {
+    getRoleId(state) {
       return (name: RoutesName) => this.getRole(name).id
     },
     getRoleIds() {
       return (names: RoutesName[]) => names.map(name => this.getRoleId(name))
     },
-    getName: state => (id: RoleOption['id']) =>
-      state.list.find(role => role.id === id)!.path,
     getNames() {
       return (ids: RoleOption['id'][]) => ids.map(this.getName)
     },
-    menuTree: state => {
-      console.log(state.list)
-      const tree = transformMenuTree(state.list)
-      console.log(tree)
-      return tree
-    }
+    getMenuTree:
+      state =>
+      (disabledIds: RoleOption['id'][] = []) =>
+        transformMenuTree(state.list, disabledIds)
   },
   actions: {
     async fetch() {

+ 3 - 14
src/store/user.ts

@@ -5,9 +5,9 @@ import {
   postLogout,
   setToken,
   delToken,
-  fetchUserRoleOptions,
-  RoleOptions
+  fetchUserRoleOptions
 } from '@/api'
+import { transformNames } from './roles'
 import { defineStore } from 'pinia'
 
 import type { User, UserMeta, LoginState } from '@/api'
@@ -38,24 +38,13 @@ if (userRolesStorage) {
   } catch {}
 }
 
-const transformRoleOptions = (options: RoleOptions) => {
-  const names: RoutesName[] = []
-  for (const option of options) {
-    names.push(option.path)
-    if (option.children) {
-      names.push(...transformRoleOptions(option.children))
-    }
-  }
-  return names
-}
-
 export const useUserStore = defineStore('user', {
   state: () => defState,
   actions: {
     async fetchRoles() {
       const options = await fetchUserRoleOptions()
       this.roleMenus = Array.from(
-        new Set([...LeastMenus, ...transformRoleOptions(options)])
+        new Set([...LeastMenus, ...transformNames(options)])
       )
       localStorage.setItem('user-roles', JSON.stringify(this.roleMenus))
     },

+ 6 - 13
src/views/project/columns.ts

@@ -1,13 +1,13 @@
 import { h } from 'vue'
 import { ProjectStatusDesc, ProjectStatus } from '@/api'
 import { router, RoutesName } from '@/router'
-import { useUserStore, pinia } from '@/store'
+import { useUserStore, pinia, useProject } from '@/store'
 import unProjectPic from '@/assets/images/un-project-pic.png'
 
 import type { SimpleProject } from '@/api'
 import type { ColumnsType } from 'ant-design-vue/es/table'
 
-const userStore = useUserStore(pinia)
+const projectStore = useProject(pinia)
 
 export const ProjectStatusComp = (props: SimpleProject) => {
   const desc = ProjectStatusDesc[props.projectStatus]
@@ -68,17 +68,10 @@ export const projectColumns: ColumnsType<SimpleProject> = [
     dataIndex: 'projectId',
     key: 'projectId',
     customRender({ record }) {
-      const allMenus = [
-        RoutesName.projectScenes,
-        RoutesName.projectTaggings,
-        RoutesName.projectMembers,
-        RoutesName.projectRoles
-      ]
-      const roleMenus = userStore.roleMenus
-      const targetMenu = allMenus.find(menu => roleMenus.includes(menu))
-      const onManage = () => {
+      const onManage = async () => {
+        await projectStore.setRoles(record.projectId)
         router.push({
-          name: targetMenu,
+          name: RoutesName.projectScenes,
           params: { id: record.projectId }
         })
       }
@@ -90,7 +83,7 @@ export const projectColumns: ColumnsType<SimpleProject> = [
         {
           class: 'table-actions'
         },
-        targetMenu ? [renderManage] : []
+        [renderManage]
       )
     }
   }

+ 12 - 1
src/views/project/detailed.vue

@@ -77,7 +77,7 @@ const allOptions = [
 const tabOptions = ref(allOptions)
 
 watch(
-  () => useUserStore().roleMenus,
+  () => useProject().roleMenus,
   enables => {
     tabOptions.value = allOptions.filter(option => enables.includes(option.key))
   },
@@ -104,6 +104,17 @@ useRealtime(() => {
   return projectStore.setCurrent(id).catch(back)
 })
 
+watch(
+  () => router.currentRoute.value.params,
+  params => {
+    console.log(params)
+    if (params.id) {
+      projectStore.setRoles(Number(params.id))
+    }
+  },
+  { immediate: true }
+)
+
 let interval: number
 onActivated(() => {
   interval = setInterval(() => {

+ 19 - 6
src/views/role/edit.vue

@@ -52,11 +52,15 @@
       <a-form-item name="roleMenus" label="菜单分配">
         <div class="menu-layer ant-input">
           <a-tree
-            v-if="roleStore.menuTree.length"
-            v-model:checkedKeys="editRole.menuIds"
+            v-if="menuTree.length"
+            :disable-checkbox="defaultRoles"
+            :checked-keys="
+              Array.from(new Set([...editRole.menuIds, ...defaultRoles]))
+            "
             default-expand-all
             checkable
-            :tree-data="roleStore.menuTree"
+            :tree-data="menuTree"
+            @update:checked-keys="ids => (editRole.menuIds = ids as any)"
           />
         </div>
       </a-form-item>
@@ -67,7 +71,7 @@
 <script lang="ts" setup>
 import { ref, defineProps, toRaw, onMounted } from 'vue'
 import { RoutesName } from '@/router'
-import { useRoleStore, useProject } from '@/store'
+import { useRoleStore, useProject, MenuTree } from '@/store'
 
 import { Role } from '@/api'
 import type { FormInstance } from 'ant-design-vue'
@@ -83,6 +87,8 @@ const props = defineProps<{
 }>()
 const roleStore = useRoleStore()
 const projectStore = useProject()
+const defaultRoles = ref<Role['roleId'][]>([])
+const menuTree = ref<MenuTree[]>([])
 
 const editRole = ref<EditRole>(
   props.role
@@ -102,13 +108,20 @@ const saveHandler = async () => {
   await props.onSave({
     ...toRaw(editRole.value),
     remark: editRole.value.remark || '',
-    menuIds: editRole.value.menuIds || []
+    menuIds: Array.from(
+      new Set([...editRole.value.menuIds, ...defaultRoles.value])
+    )
   })
   visible.value = false
 }
 
 onMounted(async () => {
-  roleStore.fetch()
+  await roleStore.fetch()
+  defaultRoles.value = roleStore.getRoleIds([
+    RoutesName.projectScenes,
+    RoutesName.personal
+  ])
+  menuTree.value = roleStore.getMenuTree(defaultRoles.value)
 })
 </script>