123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- <template>
- <CzrDialog
- :show="show"
- :title="titleCpt"
- @onClose="$emit('update:show', false)"
- @onSubmit="onSubmit"
- width="42.5rem"
- height="80%"
- :loading="state.loading"
- >
- <div class="bm-form flex size-full gap-4">
- <div class="flex flex-1 flex-col gap-4">
- <div>
- <CzrFormColumn
- class="__czr-table-form-column"
- :span="24"
- label-width="0px"
- v-model:param="state.text"
- placeholder="输入关键词以检索"
- :prefix-icon="Search"
- />
- </div>
- <div class="flex-1 overflow-y-auto">
- <el-tree
- ref="ref_tree"
- class="tree"
- :data="treeDataCpt"
- default-expand-all
- :filter-node-method="filterNode"
- show-checkbox
- node-key="value"
- :check-on-click-leaf="false"
- :expand-on-click-node="false"
- :check-strictly="true"
- @node-click="onNodeClick"
- >
- <template #default="{ node, data }">
- <div>
- {{ data.label }}
- <template v-if="data.auths?.length > 0">
- <span
- :class="
- data.auths.filter((v) =>
- state.activeAuths.includes(v.value),
- ).length === data.auths.length
- ? 'text-[var(--czr-success-color)]'
- : 'text-[var(--czr-error-color)]'
- "
- >
- ({{
- data.auths.filter((v) =>
- state.activeAuths.includes(v.value),
- ).length
- }}/{{ data.auths.length }})
- </span>
- </template>
- </div>
- </template>
- </el-tree>
- </div>
- </div>
- <div class="flex-1" v-if="state.currentMenu.title">
- <el-card
- class="size-full"
- :body-style="{ height: '100%', width: '100%' }"
- >
- <div class="flex size-full flex-col gap-4">
- <div class="font-bold">{{ state.currentMenu.title }}</div>
- <div class="flex flex-1 flex-col gap-2 overflow-auto">
- <template v-if="state.currentMenu.auths?.length > 0">
- <el-button-group size="small">
- <el-button type="primary" @click="onCheckAll(true)"
- >全选</el-button
- >
- <el-button type="info" @click="onCheckAll(false)"
- >取消全选</el-button
- >
- </el-button-group>
- <el-checkbox-group v-model="state.activeAuths">
- <template v-for="item in state.currentMenu.auths">
- <el-checkbox :value="item.value">
- {{ item.label }}
- </el-checkbox>
- </template>
- </el-checkbox-group>
- </template>
- <template v-else> 该菜单暂无可配置权限 </template>
- </div>
- </div>
- </el-card>
- </div>
- </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'
- import { Search } from '@element-plus/icons-vue'
- import CzrDialog from '@/components/czr-ui/CzrDialog.vue'
- import { rolesAuths, rolesAuthsAdd } from '@/api/modules/center/role'
- import bigModelRouter from '@/router/modules/big-model'
- const DialogStore = useDialogStore()
- const AppStore = useAppStore()
- const router = useRouter()
- const emit = defineEmits(['update:show', 'refresh'])
- const { proxy } = getCurrentInstance()
- const props = defineProps({
- show: { default: false },
- transfer: <any>{},
- })
- const state: any = reactive({
- loading: false,
- text: '',
- authsOptions: [],
- activeAuths: [],
- currentMenu: {
- title: '',
- auths: [],
- },
- })
- const ref_tree = ref()
- const titleCpt = computed(() => {
- let t = '授权'
- return t
- })
- watch(
- () => props.show,
- (n) => {
- if (n) {
- initDictionary()
- initData()
- }
- },
- )
- const initDictionary = () => {}
- const initData = () => {
- state.loading = true
- state.activeAuths = []
- ref_tree.value?.setCheckedKeys([], false)
- rolesAuths(props.transfer.roleId)
- .then(({ data }: any) => {
- const authArr: any = []
- const menuArr: any = []
- data.forEach((v) => {
- if (v.auth.includes(AppStore.permission.splitAuth)) {
- authArr.push(v.auth)
- } else {
- menuArr.push(v.auth)
- }
- })
- state.activeAuths = authArr
- ref_tree.value?.setCheckedKeys(menuArr, true)
- })
- .catch(() => {})
- .finally(() => {
- state.loading = false
- })
- }
- watch(
- () => state.text,
- (val) => {
- ref_tree.value!.filter(val)
- },
- )
- const filterNode = (value, data) => {
- if (!value) return true
- return data.label.includes(value)
- }
- const treeDataCpt = computed(() => {
- const subsMap = new Map()
- const menus: any = []
- const formatRou = (rou) => {
- const obj = {
- label: rou.meta?.title || rou.name,
- value: rou.name,
- children: [],
- auths:
- rou.meta?.auths?.map((v) => ({
- label: v.label,
- value: `${rou.name}${AppStore.permission.splitAuth}${v.value}`,
- })) || [],
- active: [],
- }
- if (rou.children?.length > 0) {
- obj.children = rou.children.map((v) => formatRou(v))
- }
- return obj
- }
- const deep = (arr) => {
- return arr.filter((v) => {
- if (v.children?.length > 0) {
- v.children = deep(v.children)
- }
- if (!v.meta.noAuth) {
- return true
- }
- })
- }
- deep(bigModelRouter()).forEach((r) => {
- if (r.meta?.root) {
- if (subsMap.has(r.meta.root)) {
- subsMap.set(r.meta.root, [...subsMap.get(r.meta.root), formatRou(r)])
- } else {
- subsMap.set(r.meta.root, [formatRou(r)])
- }
- } else {
- menus.push(formatRou(r))
- }
- })
- menus.forEach((v) => {
- if (subsMap.has(v.value)) {
- v.children.push(...subsMap.get(v.value))
- }
- })
- return menus
- })
- const onNodeClick = (data, node) => {
- const getTitle = (n, title = '') => {
- if (n.label) {
- if (title) {
- title = n.label + ' > ' + title
- } else {
- title = n.label
- }
- }
- if (n.parent) {
- return getTitle(n.parent, title)
- }
- return title
- }
- state.currentMenu.title = getTitle(node)
- state.currentMenu.auths = data.auths
- }
- const onCheckAll = (flag) => {
- if (flag) {
- state.currentMenu.auths.forEach((v) => {
- if (!state.activeAuths.includes(v.value)) {
- state.activeAuths.push(v.value)
- }
- })
- } else {
- state.activeAuths = state.activeAuths.filter(
- (v) => !state.currentMenu.auths.some((a) => a.value === v),
- )
- }
- }
- const onSubmit = () => {
- const arr = [...ref_tree.value.getCheckedKeys(), ...state.activeAuths]
- state.loading = true
- rolesAuthsAdd(props.transfer.roleId, arr)
- .then(({ data }: any) => {
- ElMessage.success('授权成功!')
- })
- .finally(() => {
- state.loading = false
- initData()
- })
- }
- </script>
- <style lang="scss" scoped>
- :deep(.tree) {
- background-color: transparent;
- }
- </style>
|