feat: 设置模块角色权限中数据权限70%

This commit is contained in:
Zzz1zz 2025-07-15 00:54:36 +08:00
parent c5588374ba
commit 73a0d92fe7
5 changed files with 195 additions and 50 deletions

View file

@ -69,5 +69,6 @@ module.exports = {
'import/no-extraneous-dependencies': 0,
// 禁用 prefer-destructuring 规则,因为它对对象解构和数组解构都产生错误警告
'prefer-destructuring': 0,
'no-return-assign': ['error', 'except-parens'],
},
};

View file

@ -0,0 +1,95 @@
<template>
<a-tree
:data="data"
:expanded-keys="expandedKeys"
:selected-keys="selectedKeys"
:field-names="fieldNames"
:checkable="checkable"
:checked-keys="checkable ? checkedKeys : undefined"
v-bind="$attrs"
@update:expanded-keys="(val) => updateExpandedKeys(val)"
@update:selected-keys="(val) => updateSelectedKeys(val)"
@update:checked-keys="(val) => updateCheckedKeys(val)"
>
<template #icon>
<IconStar v-if="!checkable" />
</template>
<slot />
</a-tree>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
const props = defineProps({
data: {
type: Array as () => unknown[],
required: true,
},
expandedKeys: {
type: Array as () => (string | number)[],
default: () => [],
},
selectedKeys: {
type: Array as () => (string | number)[],
default: () => [],
},
checkedKeys: {
type: Array as () => (string | number)[],
default: () => [],
},
checkable: {
type: Boolean,
default: false,
},
fieldNames: {
type: Object as () => { key: string; title: string; children?: string },
default: () => ({ key: 'id', title: 'name', children: 'children' }),
},
});
const emits = defineEmits([
'update:expandedKeys',
'update:selectedKeys',
'update:checkedKeys',
]);
const expandedKeys = ref<(string | number)[]>(props.expandedKeys ?? []);
const selectedKeys = ref<(string | number)[]>(props.selectedKeys ?? []);
const checkedKeys = ref<(string | number)[]>(props.checkedKeys ?? []);
watch(
() => props.expandedKeys,
(val) => (expandedKeys.value = val ?? [])
);
watch(
() => props.selectedKeys,
(val) => (selectedKeys.value = val ?? [])
);
watch(
() => props.checkedKeys,
(val) => (checkedKeys.value = val ?? [])
);
watch(expandedKeys, (val) => emits('update:expandedKeys', val));
watch(selectedKeys, (val) => emits('update:selectedKeys', val));
watch(checkedKeys, (val) => emits('update:checkedKeys', val));
function updateExpandedKeys(val: (string | number)[] | undefined): void {
const newVal = val ?? [];
expandedKeys.value = newVal;
emits('update:expandedKeys', newVal);
}
function updateSelectedKeys(val: (string | number)[] | undefined): void {
const newVal = val ?? [];
selectedKeys.value = newVal;
emits('update:selectedKeys', newVal);
}
function updateCheckedKeys(val: (string | number)[] | undefined): void {
const newVal = val ?? [];
checkedKeys.value = newVal;
emits('update:checkedKeys', newVal);
}
</script>

View file

@ -112,7 +112,11 @@ export default {
'all.clear': '全部清空',
'function.permission.setting': '功能权限设置',
'user.assignment.setting': '用户分配设置',
'data.permission.setting': '数据权限设置',
'change.role': '变更角色',
'all.data.permission': '全部数据权限',
'customize.data.permission': '自定义数据权限',
'self.data.permission': '仅本人数据',
...localeSettings,
...localeMessageBox,

View file

@ -14,16 +14,11 @@
</a-button>
</div>
</template>
<a-tree
<DepartmentTree
v-model:expanded-keys="expandedKeys"
v-model:selected-keys="selectedKeys"
:field-names="{ key: 'id', title: 'name' }"
:data="departmentListData"
>
<template #icon>
<IconStar />
</template>
</a-tree>
/>
</a-card>
</a-col>
<a-col flex="auto">
@ -82,9 +77,9 @@
<template #operate="{ record }">
<a-space>
<!-- <a-button>查看</a-button> -->
<a-button type="primary" @click="handleEditUser(record.id)">{{
$t('edit')
}}</a-button>
<a-button type="primary" @click="handleEditUser(record.id)">
{{ $t('edit') }}</a-button
>
<a-popover trigger="click" position="bottom">
<a-button>{{ $t('more') }}</a-button>
<template #content>
@ -138,6 +133,7 @@
import useDepartmentList from '@/composables/useDepartmentList';
import useDataTable from '@/composables/useDataTable';
import { Message } from '@arco-design/web-vue';
import DepartmentTree from '@/components/common/DepartmentTree.vue';
import userFormDrawer from './components/user-form-drawer.vue';
const { t } = useI18n();

View file

@ -63,15 +63,19 @@
</a-card>
</a-col>
<a-col flex="auto" class="full_height">
<a-tabs class="tabs_card" @change="handleTabChange">
<a-tabs v-model:active-key="currentTabsKey" class="tabs_card">
<template #extra>
<p style="margin-right: 10px">
<span>{{ $t('last.updated') }}</span>
<span>{{ roleItemInfo ? roleItemInfo.updatedAt : '' }}</span>
</p>
<a-button type="primary" @click="handleSubmit">{{
$t('submit')
}}</a-button>
<a-button
v-if="currentTabsKey !== '3'"
type="primary"
@click="handleSubmit"
>
{{ $t('submit') }}</a-button
>
</template>
<a-tab-pane key="1" :title="$t('function.permission')">
<permissionCollapse
@ -81,10 +85,43 @@
/>
</a-tab-pane>
<a-tab-pane key="2" :title="$t('data.permission')">
Content of Tab Panel 2
<h4>{{ $t('data.permission.setting') }}</h4>
<div style="padding: 20px 0">
<a-radio-group v-model="dataType">
<a-radio :value="1">{{ $t('all.data.permission') }}</a-radio>
<a-radio :value="2">{{
$t('customize.data.permission')
}}</a-radio>
<a-radio :value="3">{{ $t('self.data.permission') }}</a-radio>
</a-radio-group>
<a-row
v-if="dataType === 2"
:gutter="12"
style="margin-top: 20px"
>
<a-col :span="12">
<a-card>
<h4 style="margin-bottom: 10px">选择组织架构</h4>
<DepartmentTree
v-model:expanded-keys="expandedKeys"
v-model:selected-keys="selectedKeys"
:data="departmentListData"
checkable
/>
</a-card>
</a-col>
<a-col :span="12">
<a-card>
<h4 style="margin-bottom: 10px">选择项目</h4>
<div style="margin-top: 20px"> TODO 后面再对接 </div>
</a-card>
</a-col>
</a-row>
</div>
</a-tab-pane>
<a-tab-pane key="3" :title="$t('user.assignment')">
<h4>{{ $t('user.assignment.setting') }}</h4>
<div style="padding-bottom: 20px">
<DataTable
style="margin-top: 20px"
:data="renderData"
@ -103,7 +140,9 @@
</template>
<template #status="{ record }">
<a-tag :color="record.status == 1 ? 'green' : 'red'">
{{ record.status == 1 ? $t('enable') : $t('disable') }}</a-tag
{{
record.status == 1 ? $t('enable') : $t('disable')
}}</a-tag
>
</template>
<template #operate="{ record }">
@ -112,6 +151,7 @@
}}</a-button>
</template>
</DataTable>
</div>
<changeRoleDrawer
v-model:visible="changeRoleDrawerVisible"
:role-id="currentRoleActiveId"
@ -127,7 +167,7 @@
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { ref, onMounted, watch } from 'vue';
import {
getRoleList,
RoleItem,
@ -142,10 +182,14 @@
import useDataTable from '@/composables/useDataTable';
import type { TableColumnData } from '@arco-design/web-vue';
import { useI18n } from 'vue-i18n';
import DepartmentTree from '@/components/common/DepartmentTree.vue';
import useDepartmentList from '@/composables/useDepartmentList';
import permissionCollapse from './components/permission-collapse.vue';
import roleFormDrawer from './components/role-form-drawer.vue';
import changeRoleDrawer from './components/change-role-drawer.vue';
const { departmentListData, allDepartmentKeys } = useDepartmentList();
const { loading, setLoading } = useLoading(true);
const { t } = useI18n();
const roleList = ref<RoleItem[]>([]);
@ -157,6 +201,10 @@
const permissionList = ref<any[]>([]);
const changeRoleDrawerVisible = ref<boolean>(false);
const selectedUserId = ref<number | null>(null);
const currentTabsKey = ref<string>('1');
const dataType = ref<number>(1);
const expandedKeys = ref<(string | number)[]>([]);
const selectedKeys = ref<(string | number)[]>([]);
// 使用 DataTable composable
const {
data: renderData,
@ -213,6 +261,7 @@
title: t('lastLogin'),
dataIndex: 'lastLoginTime',
key: 'lastLoginTime',
align: 'center',
render: ({ record }) => record.lastLoginTime || '-',
},
{
@ -325,7 +374,13 @@
const onRoleSubmit = () => {
getRoleListData(false);
};
watch(
allDepartmentKeys,
(val) => {
expandedKeys.value = val;
},
{ immediate: true }
);
function handleSubmit() {
if (!currentRoleActiveId.value) {
Message.warning('请先选择一个角色');
@ -365,12 +420,6 @@
console.error('保存角色权限失败:', error);
});
}
const handleTabChange = (key) => {
if (key === '3') {
// 占位注释,避免空代码块
}
};
// 分页事件处理
const onPageChange = (page: number) => {
setCurrent(page);