123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- <template>
- <div class="permission-container">
- <el-form :model="configMsgForm" :rules="permissionRules" ref="configMsgFormRef" label-width="200px" class="demo-ruleForm">
- <el-form-item label="消息配置" prop="permission">
- <!-- <el-checkbox :indeterminate="allIndeterminate" v-model="allCheck" @change="handleCheckAll">全部选择</el-checkbox> -->
- <div v-for="item in permissions" :key="item.identifier" class="level_1">
- <el-row :gutter="20">
- <el-col :span="4">
- <el-checkbox
- v-model="item.has_select"
- :label="item.name"
- :indeterminate="checkIndeterminate(item.children)"
- @change="handleCheckboxChanged(item)"
- ></el-checkbox>
- </el-col>
- <el-col :span="20">
- <div v-for="_item in item.child" :key="_item.identifier" class="checkbox-dropdown">
- <el-popover placement="bottom" trigger="hover" :open-delay="300" :disabled="!hasChildren(_item)" :append-to-body="false">
- <template #reference>
- <el-checkbox
- v-model="_item.has_select"
- :indeterminate="checkIndeterminate(_item.child)"
- @click.stop
- @change="handleCheckboxChanged(_item, item)"
- >
- {{ _item.name }}
- <template v-if="hasChildren(_item)">
- <i class="el-icon-arrow-down"></i>
- </template>
- </el-checkbox>
- </template>
- <div class="role-dropdown__list" v-if="hasChildren(_item)">
- <div class="role-dropdown" v-for="__item in _item.child" :key="__item.identifier">
- <el-popover placement="right" trigger="hover" :open-delay="200" :disabled="!hasChildren(__item)" :append-to-body="false">
- <template #reference>
- <div class="role-dropdown__label">
- <el-checkbox
- v-model="__item.has_select"
- :indeterminate="checkIndeterminate(__item.child)"
- @click.stop
- @change="handleCheckboxChanged(__item, _item)"
- >
- {{ __item.name }}
- <template v-if="hasChildren(__item)">
- <i class="el-icon-arrow-right"></i>
- </template>
- </el-checkbox>
- </div>
- </template>
- <div class="role-dropdown__list" v-if="hasChildren(__item)">
- <div class="role-dropdown" v-for="___item in __item.child" :key="___item.identifier">
- <el-popover placement="right" trigger="hover" :open-delay="200" :disabled="!hasChildren(___item)" :append-to-body="false">
- <template #reference>
- <div class="role-dropdown__label">
- <el-checkbox
- v-model="___item.has_select"
- :indeterminate="checkIndeterminate(___item.child)"
- @click.stop
- @change="handleCheckboxChanged(___item, __item)"
- >{{ ___item.name }}</el-checkbox
- >
- </div>
- </template>
- </el-popover>
- </div>
- </div>
- </el-popover>
- </div>
- </div>
- </el-popover>
- </div>
- </el-col>
- </el-row>
- </div>
- </el-form-item>
- <el-form-item label="">
- <el-button type="primary" size="small" style="margin-top: 15px" @click="saveRolePermission">保存设置</el-button>
- </el-form-item>
- </el-form>
- </div>
- </template>
-
- <script lang="ts" setup>
- import { ref, reactive, onMounted, watch, nextTick } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import { ElMessage } from 'element-plus';
- import * as API_Auth from '@/api/auth';
- import * as API_Menus from '@/api/menus';
- import * as API_Setting from '@/api/setting';
- import * as API_Company from '@/api/company';
- import { useStore } from 'vuex';
- const store = useStore();
- /* import { Foundation } from '../../composables/ui-utils'; */
- const route = useRoute();
- const router = useRouter();
- const props = {
- label: 'name',
- value: 'id',
- emitPath: false,
- multiple: true,
- checkStrictly: true,
- };
- const checked = ref(true);
- const deptList = ref<any>([]);
- const oneDimensionalList = ref<any>([]); // 源数据平铺成一级节点
- /** 权限 表单 */
- const configMsgForm = reactive({
- data_scope: 'ALL',
- role_name: '',
- role_describe: '',
- });
- /** 权限 表单规则 */
- const permissionRules = reactive({
- role_name: [
- { required: true, message: '请输入角色名称!', trigger: 'blur' },
- { min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur' },
- ],
- });
- const permissions = ref<any>([]);
- const allCheck = ref(false);
- const allIndeterminate = ref(false);
- const isAllSelected = ref(false);
- const role_id = ref<any>(route.query.id);
- const searchSelectAllNodeIndex = () => {
- let selectAllOptionIndex = -1;
- configMsgForm.dept_ids.forEach((res, index) => {
- if (res.length === 1) {
- selectAllOptionIndex = index;
- }
- });
- return selectAllOptionIndex;
- };
- const visibleChange = (visible) => {
- if (visible) {
- deptList.value.unshift({
- id: '全选',
- name: '全选',
- value: '全选',
- });
- } else {
- deptList.value.shift();
- }
- };
- // 选择级联选择器
- const selectHandle = async (e = []) => {
- const selectLength = e.filter((v) => v !== '全选').length;
- const has_all_option = e.some((v) => v === '全选');
- let dept_ids = [...configMsgForm.dept_ids];
- if (has_all_option && isAllSelected.value) {
- // 移除了选项中除全部外的某个节点
- dept_ids = dept_ids.filter((v) => v !== '全选');
- dept_ids.splice(searchSelectAllNodeIndex(), 1);
- configMsgForm.dept_ids = dept_ids;
- isAllSelected.value = false;
- } else if (has_all_option && !isAllSelected.value) {
- // 选中全部节点
- isAllSelected.value = true;
- const deptListData = deptList.value;
- const dept_ids = [];
- const loopSelectData = (list) => {
- list.forEach((e) => {
- dept_ids.push(e.id);
- if (e.children && e.children.length > 0) {
- loopSelectData(e.children);
- }
- });
- };
- loopSelectData(deptListData);
- configMsgForm.dept_ids = dept_ids;
- } else if (!has_all_option && isAllSelected.value) {
- // 取消选中全部节点
- isAllSelected.value = false;
- configMsgForm.dept_ids = [];
- } else if (selectLength === oneDimensionalList.value.length) {
- isAllSelected.value = true;
- dept_ids.unshift('全选');
- configMsgForm.dept_ids = dept_ids;
- }
- nextTick(() => {
- // 强制更新
- });
- };
- /* 处理树形数据 */
- let buildTree = function buildTree(list, parent_id) {
- const tree = [];
- for (let i = 0; i < list.length; i++) {
- if (list[i].parent_id === parent_id) {
- const node = {
- id: list[i].id,
- parent_id: list[i].parent_id,
- name: list[i].name,
- create_time: list[i].create_time,
- remark: list[i].remark,
- sn: list[i].sn,
- sort: list[i].sort,
- type: list[i].type,
- region_ids: list[i].region_ids,
- children: buildTree(list, list[i].id),
- };
- tree.push(node);
- }
- }
- return tree;
- };
- /** 获取部门 */
- const GET_DeptList = () => {
- API_Setting.getDeptList().then((response) => {
- deptList.value = buildTree(response, '0');
- const oneDimensionalListData = [];
- const loopData = (list) => {
- list.forEach((e) => {
- oneDimensionalListData.push(e);
- if (e.children && e.children.length > 0) {
- loopData(e.children);
- }
- });
- };
- loopData(response);
- oneDimensionalList.value = oneDimensionalListData;
- if (configMsgForm.dept_ids.length === oneDimensionalListData.length) {
- // 设置数据范围全选
- configMsgForm.dept_ids.push('全选');
- isAllSelected.value = true;
- }
- });
- };
- /** 判断是否还有子集 */
- const hasChildren = (item) => {
- return Array.isArray(item.children) && item.children.length !== 0;
- };
- /** 全选 */
- const handleCheckAll = (checked) => {
- allIndeterminate.value = false;
- permissions.value = setPermissionsCheck(permissions.value, checked);
- };
- /** 选择 */
- const handleCheckboxChanged = (item, parent) => {
- if (item.child && item.child.length) {
- item.child = setPermissionsCheck(item.child, item.checked);
- }
- /* countAllPermissions(permissions.value);
- countParentChecked(permissions.value); */
- };
- /** 设置权限状态 */
- const setPermissionsCheck = (permissions, checked) => {
- const perm = [...permissions];
- perm.map((item) => {
- item.checked = checked;
- if (item.children && item.children.length) {
- item.children = setPermissionsCheck(item.children, checked);
- }
- });
- return perm;
- };
- /** 检测是否有不确定性 */
- const checkIndeterminate = (permissions) => {
- if (!Array.isArray(permissions)) return false;
- const _len = permissions.length;
- const __len = permissions.filter((item) => item.checked).length;
- return __len !== 0 && _len !== __len;
- };
- /** 获取所有权限展开后的长度、被选中的长度 */
- const countAllPermissions = (perms?: any[]) => {
- const currentPermissions = perms || permissions.value;
- if (!Array.isArray(currentPermissions)) {
- console.warn('permissions is not an array:', currentPermissions);
- return [];
- }
- const _list = [];
- currentPermissions.forEach((item) => {
- _list.push(item);
- if (item.children) _list.push(...countAllPermissions(item.children));
- });
- const length = _list.length;
- const length_checked = _list.filter((_item) => _item.checked).length;
- allCheck.value = length === length_checked;
- allIndeterminate.value = length_checked !== 0 && length !== length_checked;
- return _list;
- };
- /** 计算所有父辈的选中状态 */
- const countParentChecked = (perms?: any[]) => {
- const currentPermissions = perms || permissions.value;
- currentPermissions.forEach((item) => {
- if (item.children && item.children.length) {
- countParentChecked(item.children);
- const length = item.children.length;
- const checked_length = item.children.filter((_item) => _item.checked).length;
- item.checked = !!checked_length;
- }
- });
- };
- /** 保存角色权限 */
- const configMsgFormRef = ref();
- const saveRolePermission = () => {
- configMsgFormRef.value.validate((valid) => {
- if (valid) {
- let params = { vos: permissions.value };
- /* if (!params.dept_ids) {
- ElMessage.error('请选择数据范围!');
- return;
- }
- params.dept_ids = params.dept_ids.filter((v) => v !== '全选');
- if (params.dept_ids) {
- if (isAllSelected.value) {
- params.data_scope = 'ALL';
- params.dept_ids = params.dept_ids.join(',');
- } else {
- params.data_scope = 'DEPT_CUSTOM';
- params.dept_ids = params.dept_ids.join(',');
- }
- } */
- API_Company.updateSelectMsg(params).then((res) => {
- ElMessage.success('保存成功!');
- GET_RolePermission();
- });
- /* const saveSuccess = () => {
- ElMessage.success('保存成功!');
- router.push({ name: 'roleManage' });
- };*/
- /* role_id.value === '0' ? API_Auth.addRole(params).then(() => saveSuccess()) : API_Auth.editRole(role_id.value, params).then(() => saveSuccess()); */
- } else {
- ElMessage.error('表单填写有误,请检查!');
- return false;
- }
- });
- };
- /** 获取消息树 */
- const GET_RolePermission = () => {
- API_Company.getSendNumByCompany({company_id: store.state.companId}).then((res) => {
- permissions.value = res;
- });
- /* API_Menus.getMenusChildren().then((res) => {
- if (role_id.value !== '0') {
- API_Auth.getRolePermission(role_id.value).then((response) => {
- const checkedIds = expandRouters(response.menus);
- permissions.value = filterRoleRouter(res, checkedIds);
- if (Array.isArray(permissions.value)) {
- countAllPermissions();
- } else {
- console.warn('Invalid permissions data:', permissions.value);
- }
- GET_DeptList();
- });
- } else {
- permissions.value = res;
- if (Array.isArray(permissions.value)) {
- countAllPermissions();
- } else {
- console.warn('Invalid permissions data:', permissions.value);
- }
- GET_DeptList();
- }
- });*/
- };
- /** 展开路由的identifier */
- const expandRouters = (menus) => {
- const routers = [];
- menus.forEach((item) => {
- item.checked && routers.push(item.identifier);
- if (item.children && item.children.length) {
- routers.push(...expandRouters(item.children));
- }
- });
- return routers;
- };
- /** 递归筛选被选中的路由 */
- const filterRoleRouter = (routers, ids) => {
- const _routers = [];
- routers.forEach((item) => {
- if (ids.includes(item.identifier) || item.hidden) {
- item.checked = true;
- } else {
- item.checked = false;
- }
- if (item.children) {
- item.children = filterRoleRouter(item.children, ids);
- }
- _routers.push(item);
- });
- return _routers;
- };
- onMounted(() => {
- GET_RolePermission();
- });
- /* watch(
- () => route.query.id,
- () => {
- role_id.value = route.query.id;
- GET_RolePermission();
- }
- ); */
- </script>
-
- <style scoped>
- .permission-container {
- padding: 10px;
- background-color: #fff;
- padding-bottom: 150px;
- }
- .level_1 {
- padding: 15px 0;
- border-bottom: 1px dashed #e7e7e7;
- }
- .level_1:last-child {
- border-bottom: none;
- }
- :deep(.el-form-item__label) {
- padding-top: 15px;
- }
- :deep(.el-form-item__content) {
- display: block;
- border-left: 1px solid #e7e7e7;
- padding-left: 20px;
- padding-top: 15px;
- }
- :deep(.el-form-item__content .el-form-item__error) {
- padding-left: 20px;
- }
- :deep(.el-form-item:last-child .el-form-item__content) {
- padding-top: 0;
- }
- :deep(.el-form-item:not(:first-child)) {
- border-top: 1px solid #e7e7e7;
- position: relative;
- }
- :deep(.el-form-item:not(:first-child)::after) {
- content: ' ';
- width: 1px;
- height: 22px;
- background-color: #e7e7e7;
- position: absolute;
- top: -22px;
- left: 200px;
- }
- :deep(.el-button-group) {
- display: inline-block;
- }
- :deep(.el-button-group .el-button) {
- display: inline-block;
- padding: 0;
- border: none;
- }
- :deep(.el-button-group .el-button:focus),
- :deep(.el-button-group .el-button:hover) {
- color: #606266;
- border-color: #fff;
- background-color: #fff;
- }
- .checkbox-dropdown {
- display: inline-block;
- min-width: 130px;
- cursor: pointer;
- }
- .checkbox-dropdown .checked {
- color: #409eff;
- }
- .role-dropdown {
- display: flex;
- align-items: center;
- width: 25%;
- height: 30px;
- margin-bottom: 10px;
- }
- .role-dropdown:last-child {
- margin-bottom: 0;
- }
- .role-dropdown__label {
- display: flex;
- align-items: center;
- width: 100%;
- }
- :deep(.role-dropdown__label .el-checkbox__label) {
- color: inherit;
- }
- .role-dropdown__list {
- max-height: 320px;
- overflow-y: auto;
- }
- </style>
|