| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- <template>
- <div>
- <a-divider orientation="left">
- {{ $t('iam.res_policy') }}
- </a-divider>
- <a-tabs v-model="currentPolicyResTab" tab-position="left">
- <a-tab-pane v-for="item of policyResList" :key="item.key" :tab="item.label">
- <h6 class="policy-tab-title">
- {{ item.label }}
- <a-checkbox
- class="ml-4"
- :indeterminate="policyModuleCheckMap[item.key].indeterminate"
- :checked="policyModuleCheckMap[item.key].checkAll"
- @change="e => onCheckAllModuleChange(e, item.key)">
- {{ $t('common.checkAll') }}
- </a-checkbox>
- </h6>
- <div v-for="item2 of item.childrens" :key="item2.key">
- <div class="policy-group-title">{{ item2.label }}</div>
- <div v-for="item3 of item2.childrens" :key="item3.key">
- <div class="policy-menu-title">
- <span class="label">{{ item3.label }}</span>
- <a-checkbox
- class="ml-4"
- :indeterminate="policyResCheckedList[item3.key].indeterminate"
- :checked="policyResCheckedList[item3.key].checkAll"
- @change="e => onCheckAllMenuOptionsChange(e, item3.key)">
- {{ $t('common.checkAll') }}
- </a-checkbox>
- </div>
- <a-checkbox-group v-model="policyResCheckedList[item3.key].options">
- <ul class="policy-opts">
- <li v-for="item4 in item3.options" :key="item4.key">
- <a-checkbox :value="item4.key" @change="e => onCheckMenuOptionChange(e, item3.key)">{{ item4.label }}</a-checkbox>
- </li>
- </ul>
- </a-checkbox-group>
- </div>
- </div>
- </a-tab-pane>
- </a-tabs>
- <a-divider orientation="left">
- {{ $t('iam.other_policy') }}
- </a-divider>
- <div class="d-flex align-items-center">
- <a-checkbox
- :checked="checkAll"
- @change="handleCheckAllChange"
- :indeterminate="isIndeterminate"
- :disabled="checkAllDisabled">{{$t('system.text_321', [$t('dictionary.policy')])}}</a-checkbox>
- <a-input class="ml-2" v-model="searchString" :placeholder="$t('iam.policy_search_placeholder')" style="max-width:200px" allow-clear />
- </div>
- <div class="mt-1">
- <template v-for="(item, idx) of options">
- <group
- v-if="showGroup(item)"
- v-show="hasSearchString(item)"
- :key="idx"
- :group="item"
- @groupCheckChange="groupCheckChange"
- :permissions="permissions"
- :scope="scope"
- :policy="policy"
- :searchString="searchString" />
- </template>
- </div>
- </div>
- </template>
- <script>
- import * as R from 'ramda'
- import { SCOPES_MAP } from '@/constants'
- import { getPolicyResList, getPolicyResCheckedList } from '@/utils/policy/policy-res-list'
- import { POLICY_WHITE_LIST } from '@/constants/policy'
- import Group from './Group'
- export default {
- name: 'PolicyRuleCheckbox',
- components: {
- Group,
- },
- props: {
- data: {
- type: Array,
- required: true,
- },
- permissions: Object,
- scope: String,
- checkAllDisabled: Boolean,
- policy: Object,
- },
- data () {
- return {
- checkAll: false,
- isIndeterminate: false,
- options: this.data,
- searchString: '',
- currentPolicyResTab: '',
- policyResList: [],
- policyResCheckedList: getPolicyResCheckedList(this.policy),
- }
- },
- computed: {
- policyOptionsMap () {
- const plainOptionsMap = {}
- this.policyResList.forEach(item => {
- item.childrens.forEach(item => {
- item.childrens.forEach(item => {
- plainOptionsMap[item.key] = item.options
- })
- })
- })
- return plainOptionsMap
- },
- policyModuleCheckMap () {
- const policyModuleCheckMap = {}
- this.policyResList.forEach(item => {
- const menus = []
- item.childrens.forEach(item2 => {
- menus.push(...item2.childrens)
- })
- policyModuleCheckMap[item.key] = {}
- const noCheckData = menus.every(obj => {
- const exist = POLICY_WHITE_LIST.some(item => this.policyResCheckedList[obj.key].options.includes(item))
- return this.policyResCheckedList[obj.key].options.length === (exist ? POLICY_WHITE_LIST.length : 0)
- })
- policyModuleCheckMap[item.key].checkAll = !noCheckData && menus.every(obj => {
- return this.policyResCheckedList[obj.key].checkAll
- })
- policyModuleCheckMap[item.key].indeterminate = !noCheckData && menus.some(obj => {
- return !this.policyResCheckedList[obj.key].checkAll
- })
- })
- return policyModuleCheckMap
- },
- policyModuleResMap () {
- const policyModuleResMap = {}
- this.policyResList.forEach(item => {
- const policyResList = []
- item.childrens.forEach(item2 => {
- item2.childrens.forEach(item3 => {
- policyResList.push(item3.key)
- })
- })
- policyModuleResMap[item.key] = policyResList
- })
- return policyModuleResMap
- },
- },
- watch: {
- data: {
- handler (val) {
- this.options = val
- },
- immediate: true,
- },
- },
- created () {
- this.policyResList = getPolicyResList()
- this.currentPolicyResTab = this.policyResList[0].key
- },
- methods: {
- handleCheckAllChange (e) {
- const val = e.target.checked
- let totalCheckAll = true
- let totalIndeterminate = false
- R.forEach(opt => {
- let optCheckAll = true
- let optIndeterminate = false
- R.forEach(res => {
- const unDisabledActions = res.actions.filter(item => !item.disabled)
- const checked = val ? unDisabledActions.map(action => action.action) : []
- // let checked = []
- // if (val) {
- // if (res.isIndeterminate) {
- // checked = []
- // } else {
- // checked = unDisabledActions.map(action => action.action)
- // }
- // } else {
- // if (!res.isIndeterminate) {
- // checked = []
- // } else {
- // checked = unDisabledActions.map(action => action.action)
- // }
- // }
- const isIndeterminate = checked.length > 0 && checked.length < res.actions.length
- const checkAll = checked.length === res.actions.length
- let show = true
- if (this.scope === SCOPES_MAP.project.key) {
- if (res.isDomainRes || res.isSystemRes) show = false
- } else if (this.scope === SCOPES_MAP.domain.key) {
- if (res.isSystemRes) show = false
- }
- if (show) {
- if (isIndeterminate) {
- optIndeterminate = true
- }
- if (!checkAll) {
- optCheckAll = false
- }
- }
- this.$set(res, 'checkAll', checkAll)
- this.$set(res, 'isIndeterminate', isIndeterminate)
- this.$set(res, 'checked', checked)
- }, opt.resources)
- if (optIndeterminate) {
- totalIndeterminate = true
- }
- if (!optCheckAll) {
- totalCheckAll = false
- }
- this.$set(opt, 'checkAll', optCheckAll)
- this.$set(opt, 'isIndeterminate', optIndeterminate)
- }, this.options)
- this.checkAll = totalCheckAll
- this.isIndeterminate = totalIndeterminate
- },
- groupCheckChange () {
- let checkAll = true
- let allGroupTotal = 0
- let indeterminateGroupTotal = 0
- let checkAllGroupTotal = 0
- for (let i = 0, len = this.options.length; i < len; i++) {
- const group = this.options[i]
- if (this.showGroup(group)) {
- allGroupTotal++
- if (!group.checkAll) {
- checkAll = false
- } else {
- checkAllGroupTotal++
- }
- if (group.isIndeterminate) {
- indeterminateGroupTotal++
- }
- }
- }
- this.isIndeterminate = (indeterminateGroupTotal > 0 && indeterminateGroupTotal < allGroupTotal) || (checkAllGroupTotal > 0 && checkAllGroupTotal < allGroupTotal)
- this.checkAll = checkAll
- },
- showGroup (group) {
- const isShow = group.resources.some(resource => {
- // let flag = false
- // if (this.scope !== SCOPES_MAP.system.key && resource.isSystemRes) {
- // flag = true
- // }
- // if (this.scope !== SCOPES_MAP.domain.key && resource.isDomainRes) {
- // flag = true
- // }
- // if (flag) return false
- // return true
- let show = true
- if (this.scope === SCOPES_MAP.project.key) {
- if (resource.isDomainRes || resource.isSystemRes) show = false
- } else if (this.scope === SCOPES_MAP.domain.key) {
- if (resource.isSystemRes) show = false
- }
- return show
- })
- return isShow
- },
- hasSearchString (group) {
- if (!this.searchString) {
- return true
- }
- if (group.label && group.label.includes(this.searchString)) {
- return true
- }
- if (group.resources && group.resources.filter(item => {
- let show = true
- if (!item.label.includes(this.searchString)) {
- show = false
- } else {
- if (this.scope === SCOPES_MAP.project.key) {
- if (item.isDomainRes || item.isSystemRes) show = false
- } else if (this.scope === SCOPES_MAP.domain.key) {
- if (item.isSystemRes) show = false
- }
- }
- return show
- }).length
- ) {
- return true
- }
- return false
- },
- onCheckAllMenuOptionsChange (e, menuKey) {
- // 查找当前菜单选项的操作集合
- const plainOptions = this.policyOptionsMap[menuKey].map(item => item.key)
- Object.assign(this.policyResCheckedList[menuKey], {
- options: e.target.checked ? Array.from(new Set(plainOptions)) : [],
- indeterminate: false,
- checkAll: e.target.checked,
- })
- this.$nextTick(() => {
- this.$emit('checkMenuOptionsChange', this.policyResCheckedList)
- })
- },
- onCheckMenuOptionChange (e, menuKey) {
- // 查找当前菜单选项的操作集合
- let plainOptions = this.policyOptionsMap[menuKey].map(item => item.key)
- plainOptions = Array.from(new Set(plainOptions))
- this.$nextTick(() => {
- const len = this.policyResCheckedList[menuKey].options.length
- this.policyResCheckedList[menuKey].indeterminate = !!len && this.policyResCheckedList[menuKey].options.length < plainOptions.length
- this.policyResCheckedList[menuKey].checkAll = this.policyResCheckedList[menuKey].options.length === plainOptions.length
- this.$emit('checkMenuOptionsChange', this.policyResCheckedList)
- })
- },
- onCheckAllModuleChange (e, moduleKey) {
- const menuKeys = this.policyModuleResMap[moduleKey]
- menuKeys.forEach(menuKey => {
- this.onCheckAllMenuOptionsChange(e, menuKey)
- })
- },
- },
- }
- </script>
- <style lang="scss" scoped>
- .policy-tab-title {
- height: 40px;
- line-height: 40px;
- border: 1px solid #eee;
- padding-left: 14px;
- }
- .policy-group-title {
- font-size: 14px;
- font-weight: bold;
- padding: 10px 0 10px 0;
- border-bottom: 1px solid #eee;
- }
- .policy-menu-title {
- padding: 10px 0 10px 0;
- .label {
- border-left: 3px solid #999;
- padding-left: 6px;
- }
- }
- .policy-opts {
- padding: 0;
- margin: 0;
- list-style: none;
- display: flex;
- flex-wrap: wrap;
- li {
- width: 220px;
- padding: 10px 20px;
- }
- }
- </style>
|