diff --git a/frontend1/src/pages/system/user-data-scope/index.less b/frontend1/src/pages/system/user-data-scope/index.less index c46bdc24..41bb8ed4 100644 --- a/frontend1/src/pages/system/user-data-scope/index.less +++ b/frontend1/src/pages/system/user-data-scope/index.less @@ -1,5 +1,6 @@ .user-data-scope-page { min-height: 100%; + overflow: hidden; } .user-data-scope-overview { @@ -38,7 +39,45 @@ } .user-data-scope-table-card { + flex: 1; + min-height: 0; overflow: hidden; + + .ant-card-body { + height: 100%; + display: flex; + flex-direction: column; + overflow: hidden; + } +} + +.user-data-scope-table { + min-height: 0; + display: flex; + flex: 1; + flex-direction: column; + + .ant-spin-nested-loading, + .ant-spin-container { + min-height: 0; + display: flex; + flex: 1; + flex-direction: column; + } + + .ant-table { + min-height: 0; + flex: 1; + } + + .ant-table-container { + min-height: 0; + } + + .ant-table-pagination { + flex-shrink: 0; + margin: 12px 16px !important; + } } @media (max-width: 991px) { diff --git a/frontend1/src/pages/system/user-data-scope/index.tsx b/frontend1/src/pages/system/user-data-scope/index.tsx index bd43dcfa..280addf3 100644 --- a/frontend1/src/pages/system/user-data-scope/index.tsx +++ b/frontend1/src/pages/system/user-data-scope/index.tsx @@ -4,10 +4,10 @@ import dayjs from "dayjs"; import { useCallback, useEffect, useMemo, useState } from "react"; import { DeleteOutlined, EditOutlined, PlusOutlined, SearchOutlined, TeamOutlined } from "@ant-design/icons"; import PageHeader from "@/components/shared/PageHeader"; -import { deleteUserDataScopeGrant, listTenants, listUserDataScopeGrants, listUserDataScopeUsers, saveUserDataScopeAssignment } from "@/api"; +import { deleteUserDataScopeGrant, fetchUsersByRoleId, listRoles, listTenants, listUserDataScopeGrants, listUserDataScopeUsers, saveUserDataScopeAssignment } from "@/api"; import { usePermission } from "@/hooks/usePermission"; import { getStandardPagination } from "@/utils/pagination"; -import type { SysTenant, UserDataScopeGrant, UserDataScopeUser } from "@/types"; +import type { SysRole, SysTenant, UserDataScopeGrant, UserDataScopeUser } from "@/types"; import "./index.less"; const { Text } = Typography; @@ -141,7 +141,9 @@ export default function UserDataScopePage() { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); + const [roleUserLoading, setRoleUserLoading] = useState(false); const [users, setUsers] = useState([]); + const [roles, setRoles] = useState([]); const [grants, setGrants] = useState([]); const [tenants, setTenants] = useState([]); const [drawerOpen, setDrawerOpen] = useState(false); @@ -170,6 +172,15 @@ export default function UserDataScopePage() { setUsers(list || []); }, [selectedTenantId]); + const loadRoles = useCallback(async () => { + if (!selectedTenantId) { + setRoles([]); + return; + } + const list = await listRoles(selectedTenantId); + setRoles(list || []); + }, [selectedTenantId]); + const loadGrants = useCallback(async () => { if (!selectedTenantId) { setGrants([]); @@ -182,11 +193,11 @@ export default function UserDataScopePage() { const loadPageData = useCallback(async () => { setLoading(true); try { - await Promise.all([loadTenants(), loadUsers(), loadGrants()]); + await Promise.all([loadTenants(), loadUsers(), loadRoles(), loadGrants()]); } finally { setLoading(false); } - }, [loadTenants, loadUsers, loadGrants]); + }, [loadTenants, loadUsers, loadRoles, loadGrants]); useEffect(() => { loadPageData(); @@ -244,12 +255,28 @@ export default function UserDataScopePage() { [selectedDrawerViewerId, userOptions] ); + const roleOptions = useMemo(() => roles.map((role) => { + const label = role.roleName || role.roleCode || String(role.roleId); + return { + label: ( + + {label} + {role.roleCode && role.roleCode !== label && {role.roleCode}} + + ), + displayLabel: label, + value: role.roleId, + searchText: `${role.roleName || ""} ${role.roleCode || ""}` + }; + }), [roles]); + const openCreate = () => { setEditingGrantGroup(null); form.resetFields(); form.setFieldsValue({ resourceTypes: ["OPPORTUNITY"], enabled: true, + roleIds: [], ownerUserIds: [] }); setDrawerOpen(true); @@ -261,6 +288,7 @@ export default function UserDataScopePage() { form.setFieldsValue({ viewerUserId: record.viewerUserId, resourceTypes: record.resourceTypes, + roleIds: [], ownerUserIds: record.ownerUsers.map((owner) => owner.userId), enabled: record.enabled, expireAt: record.expireAt ? dayjs(record.expireAt) : undefined, @@ -274,6 +302,27 @@ export default function UserDataScopePage() { setEditingGrantGroup(null); }; + const handleRoleSelectChange = async (roleIds: number[]) => { + form.setFieldValue("roleIds", roleIds); + if (!roleIds.length) { + return; + } + const selectedViewerUserId = form.getFieldValue("viewerUserId"); + const selectedOwnerIds = new Set(form.getFieldValue("ownerUserIds") || []); + setRoleUserLoading(true); + try { + const roleUsers = await Promise.all(roleIds.map((roleId) => fetchUsersByRoleId(roleId))); + roleUsers.flat().forEach((user) => { + if (user?.userId && user.userId !== selectedViewerUserId) { + selectedOwnerIds.add(user.userId); + } + }); + form.setFieldValue("ownerUserIds", Array.from(selectedOwnerIds)); + } finally { + setRoleUserLoading(false); + } + }; + const handleSave = async () => { if (!selectedTenantId) { message.warning("请先选择租户"); @@ -469,12 +518,13 @@ export default function UserDataScopePage() { +