OAPERM1 收紧启用前权限冻结
这个提交包含在:
@@ -28,12 +28,6 @@ const PROCUREMENT_SELF_SERVICE_PERMISSIONS = [
|
||||
"procurement.submit",
|
||||
] as const;
|
||||
|
||||
const TRAVEL_SELF_SERVICE_PERMISSIONS = [
|
||||
"travel.create",
|
||||
"travel.view_own",
|
||||
"travel.submit",
|
||||
] as const;
|
||||
|
||||
const ASSET_SELF_SERVICE_PERMISSIONS = ["asset.view_own"] as const;
|
||||
const PROJECT_SELF_SERVICE_PERMISSIONS = ["project.view_own"] as const;
|
||||
|
||||
@@ -44,7 +38,6 @@ const EMPLOYEE_BASE_PERMISSIONS = [
|
||||
...EXPENSE_SELF_SERVICE_PERMISSIONS,
|
||||
...LEAVE_SELF_SERVICE_PERMISSIONS,
|
||||
...ATTENDANCE_SELF_SERVICE_PERMISSIONS,
|
||||
...TRAVEL_SELF_SERVICE_PERMISSIONS,
|
||||
...PROJECT_SELF_SERVICE_PERMISSIONS,
|
||||
] as const;
|
||||
|
||||
@@ -66,8 +59,6 @@ const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
||||
"attendance.view_all",
|
||||
"procurement.approve",
|
||||
"procurement.view_all",
|
||||
"travel.approve",
|
||||
"travel.view_all",
|
||||
"asset.view_all",
|
||||
"report.dashboard.view",
|
||||
"project.view_all",
|
||||
@@ -88,8 +79,6 @@ const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
||||
"attendance.view_all",
|
||||
"procurement.approve",
|
||||
"procurement.view_all",
|
||||
"travel.approve",
|
||||
"travel.view_all",
|
||||
"asset.view_all",
|
||||
"report.dashboard.view",
|
||||
"budget.view",
|
||||
@@ -106,8 +95,6 @@ const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
||||
"payment.batch.manage",
|
||||
"expense.view_all",
|
||||
"procurement.view_all",
|
||||
"travel.view_all",
|
||||
"travel.payment.manage",
|
||||
"asset.view_all",
|
||||
"attendance.view_all",
|
||||
],
|
||||
@@ -129,9 +116,6 @@ const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
||||
"expense.finance.override_duplicate",
|
||||
"procurement.view_all",
|
||||
"procurement.manage",
|
||||
"travel.view_all",
|
||||
"travel.manage",
|
||||
"travel.payment.manage",
|
||||
"asset.view_all",
|
||||
"asset.manage",
|
||||
"asset.inventory",
|
||||
@@ -149,9 +133,6 @@ const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
||||
...EMPLOYEE_BASE_PERMISSIONS,
|
||||
"procurement.view_all",
|
||||
"procurement.manage",
|
||||
"travel.view_all",
|
||||
"travel.manage",
|
||||
"travel.payment.manage",
|
||||
"asset.view_all",
|
||||
"asset.manage",
|
||||
"asset.transfer",
|
||||
|
||||
@@ -38,7 +38,7 @@ export const NAV_ITEMS: NavItem[] = [
|
||||
{ to: "/workflow/tasks", label: "审批待办", icon: "fact_check", anyOf: ["expense.approve", "leave.approve", "attendance.approve", "procurement.approve", "travel.approve"] },
|
||||
{ to: "/contracts-registry", label: "合同台账", icon: "description", anyOf: ["project.view_all", "project.manage", "system.settings"] },
|
||||
{ to: "/purchase-requests", label: "采购申请", icon: "shopping_cart", anyOf: ["procurement.create", "procurement.view_own", "procurement.view_all", "procurement.manage"] },
|
||||
{ to: "/travel-requests", label: "差旅申请", icon: "flight", anyOf: ["travel.view_all", "travel.manage", "travel.payment.manage", "integration.manage"] },
|
||||
{ to: "/travel-requests", label: "差旅申请", icon: "flight", anyOf: ["travel.view_all", "travel.manage", "travel.payment.manage"] },
|
||||
{ to: "/budgets", label: "预算管理", icon: "account_balance", anyOf: ["budget.view", "budget.manage"] },
|
||||
{ to: "/payment-batches", label: "支付批次", icon: "payments", anyOf: ["payment.batch.manage", "risk.review.manage"] },
|
||||
{ to: "/ap-operations", label: "AP 运营", icon: "account_balance_wallet", anyOf: ["payment.batch.manage", "risk.review.manage"] },
|
||||
|
||||
@@ -183,6 +183,7 @@ export function EmployeeProfilePage() {
|
||||
queryFn: () => fetchEmployeeProfile(employeeId),
|
||||
});
|
||||
const canManageEmployeeProfile = hasPermission(permissions, "system.users");
|
||||
const canManageSensitiveHr = hasPermission(permissions, "system.settings");
|
||||
const canEditSelfProfile = me?.id === employeeId;
|
||||
const canEditBaseFields = canManageEmployeeProfile || canEditSelfProfile;
|
||||
const canEditExtendedFields = canManageEmployeeProfile;
|
||||
@@ -266,11 +267,19 @@ export function EmployeeProfilePage() {
|
||||
}, [employeeId, requestedTab]);
|
||||
|
||||
useEffect(() => {
|
||||
if (canManageEmployeeProfile || canEditSelfProfile || activeTab === "profile" || activeTab === "performance") {
|
||||
if (activeTab === "salary" && !canManageSensitiveHr && !canEditSelfProfile) {
|
||||
updateActiveTab("profile");
|
||||
return;
|
||||
}
|
||||
if (activeTab === "performance" && !canManageSensitiveHr && !canEditSelfProfile) {
|
||||
updateActiveTab("profile");
|
||||
return;
|
||||
}
|
||||
if (canManageEmployeeProfile || canEditSelfProfile || activeTab === "profile") {
|
||||
return;
|
||||
}
|
||||
updateActiveTab("profile");
|
||||
}, [activeTab, canEditSelfProfile, canManageEmployeeProfile]);
|
||||
}, [activeTab, canEditSelfProfile, canManageEmployeeProfile, canManageSensitiveHr]);
|
||||
|
||||
useEffect(() => {
|
||||
setAvatarFile(null);
|
||||
@@ -528,8 +537,8 @@ export function EmployeeProfilePage() {
|
||||
profileQuery.isError && isApiError(profileQuery.error) && profileQuery.error.status === 403;
|
||||
const performanceOnlyMode = activeTab === "performance" && profilePermissionDenied && Boolean(performanceQuery.data);
|
||||
const showPerformanceTab =
|
||||
canManageEmployeeProfile || canEditSelfProfile || performanceOnlyMode || performanceQuery.data?.viewerRole === "manager";
|
||||
const showSalaryTab = canManageEmployeeProfile || canEditSelfProfile;
|
||||
canManageSensitiveHr || canEditSelfProfile || performanceOnlyMode || performanceQuery.data?.viewerRole === "manager";
|
||||
const showSalaryTab = canManageSensitiveHr || canEditSelfProfile;
|
||||
|
||||
const performanceContent =
|
||||
performanceQuery.isLoading ? (
|
||||
@@ -546,7 +555,7 @@ export function EmployeeProfilePage() {
|
||||
]}
|
||||
/>
|
||||
);
|
||||
const salaryContent = <EmployeeSalaryPanel employeeId={employeeId} canManage={canManageEmployeeProfile} isSelf={canEditSelfProfile} />;
|
||||
const salaryContent = <EmployeeSalaryPanel employeeId={employeeId} canManage={canManageSensitiveHr} isSelf={canEditSelfProfile} />;
|
||||
|
||||
if (profileQuery.isLoading || (activeTab === "performance" && profilePermissionDenied && performanceQuery.isLoading)) {
|
||||
return <div className="card-std p-6 text-sm text-zinc-500">加载员工档案中...</div>;
|
||||
|
||||
@@ -117,7 +117,7 @@ export function PeopleStatsPage() {
|
||||
<section className="card-std p-5">
|
||||
<div className="text-sm text-zinc-500">上月人均薪资</div>
|
||||
<div className="mt-2 text-3xl font-semibold text-zinc-900">{moneyText(salarySummary.previousMonth?.averageNetAmount)}</div>
|
||||
<div className="mt-2 text-xs text-zinc-500">非 system.users 不展示任何薪资汇总</div>
|
||||
<div className="mt-2 text-xs text-zinc-500">非 system.settings 不展示任何薪资汇总</div>
|
||||
</section>
|
||||
) : null}
|
||||
<section className="card-std p-5">
|
||||
|
||||
@@ -471,7 +471,7 @@ export function AppRouter() {
|
||||
<Route
|
||||
path="payroll"
|
||||
element={
|
||||
<RequirePermission anyOf={["system.users"]}>
|
||||
<RequirePermission anyOf={["system.settings"]}>
|
||||
{withRouteFallback(<PayrollPage />)}
|
||||
</RequirePermission>
|
||||
}
|
||||
@@ -480,7 +480,7 @@ export function AppRouter() {
|
||||
<Route
|
||||
path="performance"
|
||||
element={
|
||||
<RequirePermission anyOf={["system.users"]}>
|
||||
<RequirePermission anyOf={["system.settings"]}>
|
||||
{withRouteFallback(<PerformancePage />)}
|
||||
</RequirePermission>
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户