新增权限点增加
parent
8a7ee5f066
commit
c6b695169e
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.unis.crm.service.impl;
|
||||
|
||||
import com.unis.crm.common.BusinessException;
|
||||
import com.unis.crm.common.UnauthorizedException;
|
||||
import com.unis.crm.dto.expansion.ChannelExpansionItemDTO;
|
||||
import com.unis.crm.dto.expansion.ChannelExpansionContactRequest;
|
||||
import com.unis.crm.dto.expansion.ChannelRelatedProjectSummaryDTO;
|
||||
|
|
@ -18,6 +19,7 @@ import com.unis.crm.dto.expansion.UpdateChannelExpansionRequest;
|
|||
import com.unis.crm.dto.expansion.UpdateSalesExpansionRequest;
|
||||
import com.unis.crm.mapper.ExpansionMapper;
|
||||
import com.unis.crm.service.ExpansionService;
|
||||
import com.unisbase.security.PermissionService;
|
||||
import com.unisbase.security.SpringSecurityTenantProvider;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLDecoder;
|
||||
|
|
@ -47,16 +49,22 @@ public class ExpansionServiceImpl implements ExpansionService {
|
|||
private static final String CERTIFICATION_LEVEL_TYPE_CODE = "tz_rzjb";
|
||||
private static final String CHANNEL_ATTRIBUTE_TYPE_CODE = "tz_qdsx";
|
||||
private static final String INTERNAL_ATTRIBUTE_TYPE_CODE = "tz_xhsnbsx";
|
||||
private static final String CREATE_PERMISSION = "expansion:create";
|
||||
private static final String MULTI_VALUE_CUSTOM_PREFIX = "__custom__:";
|
||||
private static final DateTimeFormatter FOLLOW_UP_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||
private static final Logger log = LoggerFactory.getLogger(ExpansionServiceImpl.class);
|
||||
|
||||
private final ExpansionMapper expansionMapper;
|
||||
private final SpringSecurityTenantProvider tenantProvider;
|
||||
private final PermissionService permissionService;
|
||||
|
||||
public ExpansionServiceImpl(ExpansionMapper expansionMapper, SpringSecurityTenantProvider tenantProvider) {
|
||||
public ExpansionServiceImpl(
|
||||
ExpansionMapper expansionMapper,
|
||||
SpringSecurityTenantProvider tenantProvider,
|
||||
PermissionService permissionService) {
|
||||
this.expansionMapper = expansionMapper;
|
||||
this.tenantProvider = tenantProvider;
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -148,6 +156,7 @@ public class ExpansionServiceImpl implements ExpansionService {
|
|||
|
||||
@Override
|
||||
public Long createSalesExpansion(Long userId, CreateSalesExpansionRequest request) {
|
||||
requirePermission(CREATE_PERMISSION, "无权新增拓展");
|
||||
fillSalesDefaults(request);
|
||||
ensureUniqueEmployeeNo(userId, request.getEmployeeNo(), null);
|
||||
expansionMapper.insertSalesExpansion(userId, request);
|
||||
|
|
@ -160,6 +169,7 @@ public class ExpansionServiceImpl implements ExpansionService {
|
|||
@Override
|
||||
@Transactional
|
||||
public Long createChannelExpansion(Long userId, CreateChannelExpansionRequest request) {
|
||||
requirePermission(CREATE_PERMISSION, "无权新增拓展");
|
||||
fillChannelDefaults(request);
|
||||
ensureUniqueChannelName(userId, request.getChannelName(), null);
|
||||
expansionMapper.insertChannelExpansion(userId, request);
|
||||
|
|
@ -675,4 +685,10 @@ public class ExpansionServiceImpl implements ExpansionService {
|
|||
throw new BusinessException("无权操作该拓展记录");
|
||||
}
|
||||
}
|
||||
|
||||
private void requirePermission(String perm, String message) {
|
||||
if (!permissionService.hasPermi(perm)) {
|
||||
throw new UnauthorizedException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unis.crm.common.BusinessException;
|
||||
import com.unis.crm.common.UnauthorizedException;
|
||||
import com.unis.crm.dto.opportunity.CurrentUserAccountDTO;
|
||||
import com.unis.crm.dto.opportunity.CreateOpportunityFollowUpRequest;
|
||||
import com.unis.crm.dto.opportunity.CreateOpportunityRequest;
|
||||
|
|
@ -23,6 +24,7 @@ import com.unis.crm.mapper.OpportunityMapper;
|
|||
import com.unis.crm.service.OmsClient;
|
||||
import com.unis.crm.service.OpportunityService;
|
||||
import com.unisbase.dto.DataScopeRuleDTO;
|
||||
import com.unisbase.security.PermissionService;
|
||||
import com.unisbase.service.DataScopeService;
|
||||
import com.unisbase.spi.UnisBaseTenantProvider;
|
||||
import java.io.IOException;
|
||||
|
|
@ -50,6 +52,7 @@ public class OpportunityServiceImpl implements OpportunityService {
|
|||
private static final String OPPORTUNITY_TYPE_CODE = "sj_jslx";
|
||||
private static final String CONFIDENCE_TYPE_CODE = "sj_xmbwd";
|
||||
private static final String SYS_IS_TYPE_CODE = "sys_is";
|
||||
private static final String CREATE_PERMISSION = "opportunity:create";
|
||||
private static final String ARCHIVED_OPPORTUNITY_EDIT_MESSAGE = "已签单商机不允许编辑";
|
||||
private static final String ARCHIVED_OPPORTUNITY_PUSH_MESSAGE = "已签单商机不允许推送";
|
||||
private static final String REPORT_ATTACHMENT_METADATA_PREFIX = "[[WORK_REPORT_ATTACHMENTS]]";
|
||||
|
|
@ -62,18 +65,21 @@ public class OpportunityServiceImpl implements OpportunityService {
|
|||
private final ObjectMapper objectMapper;
|
||||
private final DataScopeService dataScopeService;
|
||||
private final UnisBaseTenantProvider tenantProvider;
|
||||
private final PermissionService permissionService;
|
||||
|
||||
public OpportunityServiceImpl(
|
||||
OpportunityMapper opportunityMapper,
|
||||
OmsClient omsClient,
|
||||
ObjectMapper objectMapper,
|
||||
DataScopeService dataScopeService,
|
||||
UnisBaseTenantProvider tenantProvider) {
|
||||
UnisBaseTenantProvider tenantProvider,
|
||||
PermissionService permissionService) {
|
||||
this.opportunityMapper = opportunityMapper;
|
||||
this.omsClient = omsClient;
|
||||
this.objectMapper = objectMapper;
|
||||
this.dataScopeService = dataScopeService;
|
||||
this.tenantProvider = tenantProvider;
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -169,6 +175,7 @@ public class OpportunityServiceImpl implements OpportunityService {
|
|||
@Override
|
||||
@Transactional
|
||||
public Long createOpportunity(Long userId, CreateOpportunityRequest request) {
|
||||
requirePermission(CREATE_PERMISSION, "无权新增商机");
|
||||
fillDefaults(request);
|
||||
Long customerId = resolveOrCreateOwnedCustomerId(userId, request.getCustomerName().trim(), request.getSource());
|
||||
|
||||
|
|
@ -997,6 +1004,12 @@ public class OpportunityServiceImpl implements OpportunityService {
|
|||
|| normalizedOperator.contains("dls");
|
||||
}
|
||||
|
||||
private void requirePermission(String perm, String message) {
|
||||
if (!permissionService.hasPermi(perm)) {
|
||||
throw new UnauthorizedException(message);
|
||||
}
|
||||
}
|
||||
|
||||
private OmsPreSalesOptionDTO resolveSelectedPreSales(
|
||||
OpportunityOmsPushDataDTO pushData,
|
||||
PushOpportunityToOmsRequest request,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import static org.mockito.Mockito.verify;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.unis.crm.common.BusinessException;
|
||||
import com.unis.crm.common.UnauthorizedException;
|
||||
import com.unis.crm.dto.expansion.ChannelExpansionContactRequest;
|
||||
import com.unis.crm.dto.expansion.CreateChannelExpansionRequest;
|
||||
import com.unis.crm.dto.expansion.CreateSalesExpansionRequest;
|
||||
|
|
@ -17,6 +18,7 @@ import com.unis.crm.dto.expansion.SalesExpansionItemDTO;
|
|||
import com.unis.crm.dto.expansion.UpdateChannelExpansionRequest;
|
||||
import com.unis.crm.dto.expansion.UpdateSalesExpansionRequest;
|
||||
import com.unis.crm.mapper.ExpansionMapper;
|
||||
import com.unisbase.security.PermissionService;
|
||||
import com.unisbase.security.SpringSecurityTenantProvider;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
|
@ -36,12 +38,16 @@ class ExpansionServiceImplTest {
|
|||
@Mock
|
||||
private SpringSecurityTenantProvider tenantProvider;
|
||||
|
||||
@Mock
|
||||
private PermissionService permissionService;
|
||||
|
||||
@InjectMocks
|
||||
private ExpansionServiceImpl expansionService;
|
||||
|
||||
@Test
|
||||
void createSalesExpansion_shouldRejectDuplicateEmployeeNo() {
|
||||
CreateSalesExpansionRequest request = buildCreateSalesRequest();
|
||||
when(permissionService.hasPermi("expansion:create")).thenReturn(true);
|
||||
when(expansionMapper.countSalesExpansionByEmployeeNo("EMP001")).thenReturn(1);
|
||||
|
||||
BusinessException exception = assertThrows(
|
||||
|
|
@ -52,6 +58,19 @@ class ExpansionServiceImplTest {
|
|||
verify(expansionMapper, never()).insertSalesExpansion(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createSalesExpansion_shouldRejectWhenPermissionMissing() {
|
||||
CreateSalesExpansionRequest request = buildCreateSalesRequest();
|
||||
when(permissionService.hasPermi("expansion:create")).thenReturn(false);
|
||||
|
||||
UnauthorizedException exception = assertThrows(
|
||||
UnauthorizedException.class,
|
||||
() -> expansionService.createSalesExpansion(1L, request));
|
||||
|
||||
assertEquals("无权新增拓展", exception.getMessage());
|
||||
verify(expansionMapper, never()).insertSalesExpansion(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateSalesExpansion_shouldSkipDuplicateEmployeeNoCheck() {
|
||||
UpdateSalesExpansionRequest request = buildUpdateSalesRequest();
|
||||
|
|
@ -67,6 +86,7 @@ class ExpansionServiceImplTest {
|
|||
@Test
|
||||
void createChannelExpansion_shouldRejectDuplicateChannelName() {
|
||||
CreateChannelExpansionRequest request = buildCreateChannelRequest();
|
||||
when(permissionService.hasPermi("expansion:create")).thenReturn(true);
|
||||
when(expansionMapper.countChannelExpansionByChannelName("渠道A")).thenReturn(1);
|
||||
|
||||
BusinessException exception = assertThrows(
|
||||
|
|
@ -77,6 +97,19 @@ class ExpansionServiceImplTest {
|
|||
verify(expansionMapper, never()).insertChannelExpansion(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createChannelExpansion_shouldRejectWhenPermissionMissing() {
|
||||
CreateChannelExpansionRequest request = buildCreateChannelRequest();
|
||||
when(permissionService.hasPermi("expansion:create")).thenReturn(false);
|
||||
|
||||
UnauthorizedException exception = assertThrows(
|
||||
UnauthorizedException.class,
|
||||
() -> expansionService.createChannelExpansion(1L, request));
|
||||
|
||||
assertEquals("无权新增拓展", exception.getMessage());
|
||||
verify(expansionMapper, never()).insertChannelExpansion(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateChannelExpansion_shouldSkipDuplicateChannelNameCheck() {
|
||||
UpdateChannelExpansionRequest request = buildUpdateChannelRequest();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unis.crm.common.BusinessException;
|
||||
import com.unis.crm.common.UnauthorizedException;
|
||||
import com.unis.crm.dto.opportunity.CurrentUserAccountDTO;
|
||||
import com.unis.crm.dto.opportunity.CreateOpportunityRequest;
|
||||
import com.unis.crm.dto.opportunity.OmsPreSalesOptionDTO;
|
||||
|
|
@ -24,6 +25,7 @@ import com.unis.crm.dto.opportunity.UpdateOpportunityIntegrationRequest;
|
|||
import com.unis.crm.mapper.OpportunityMapper;
|
||||
import com.unis.crm.service.OmsClient;
|
||||
import com.unisbase.dto.DataScopeRuleDTO;
|
||||
import com.unisbase.security.PermissionService;
|
||||
import com.unisbase.service.DataScopeService;
|
||||
import com.unisbase.spi.UnisBaseTenantProvider;
|
||||
import java.math.BigDecimal;
|
||||
|
|
@ -53,6 +55,9 @@ class OpportunityServiceImplTest {
|
|||
@Mock
|
||||
private UnisBaseTenantProvider tenantProvider;
|
||||
|
||||
@Mock
|
||||
private PermissionService permissionService;
|
||||
|
||||
@InjectMocks
|
||||
private OpportunityServiceImpl opportunityService;
|
||||
|
||||
|
|
@ -84,6 +89,7 @@ class OpportunityServiceImplTest {
|
|||
|
||||
@Test
|
||||
void createOpportunity_shouldRejectWhenCustomerDoesNotExist() {
|
||||
when(permissionService.hasPermi("opportunity:create")).thenReturn(true);
|
||||
when(opportunityMapper.selectOwnedCustomerIdByName(1L, "客户A")).thenReturn(null);
|
||||
when(opportunityMapper.insertOpportunity(eq(1L), any(), any(CreateOpportunityRequest.class))).thenAnswer(invocation -> {
|
||||
CreateOpportunityRequest request = invocation.getArgument(2);
|
||||
|
|
@ -102,6 +108,18 @@ class OpportunityServiceImplTest {
|
|||
verify(opportunityMapper).insertCustomer(any(), eq(1L), eq("客户A"), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createOpportunity_shouldRejectWhenPermissionMissing() {
|
||||
when(permissionService.hasPermi("opportunity:create")).thenReturn(false);
|
||||
|
||||
UnauthorizedException exception = assertThrows(
|
||||
UnauthorizedException.class,
|
||||
() -> opportunityService.createOpportunity(1L, updateRequest("客户A")));
|
||||
|
||||
assertEquals("无权新增商机", exception.getMessage());
|
||||
verify(opportunityMapper, never()).insertOpportunity(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateOpportunity_shouldKeepCurrentCustomerWhenCustomerNameUnchanged() {
|
||||
when(opportunityMapper.countOwnedOpportunity(1L, 10L)).thenReturn(1);
|
||||
|
|
@ -172,6 +190,7 @@ class OpportunityServiceImplTest {
|
|||
|
||||
@Test
|
||||
void createOpportunity_shouldPersistEditableSnapshotFields() {
|
||||
when(permissionService.hasPermi("opportunity:create")).thenReturn(true);
|
||||
when(opportunityMapper.selectOwnedCustomerIdByName(1L, "客户A")).thenReturn(200L);
|
||||
when(opportunityMapper.insertOpportunity(eq(1L), eq(200L), any(CreateOpportunityRequest.class))).thenAnswer(invocation -> {
|
||||
CreateOpportunityRequest request = invocation.getArgument(2);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,16 @@ export interface UserRole {
|
|||
roleName?: string;
|
||||
}
|
||||
|
||||
export interface UserPermission {
|
||||
permId?: number;
|
||||
parentId?: number;
|
||||
name?: string;
|
||||
code: string;
|
||||
permType?: string;
|
||||
status?: number;
|
||||
isVisible?: number;
|
||||
}
|
||||
|
||||
export interface AdminUserSummary {
|
||||
userId: number;
|
||||
username: string;
|
||||
|
|
@ -808,6 +818,7 @@ const LOGIN_PATH = "/login";
|
|||
const USER_CONTEXT_CACHE_TTL_MS = 2 * 60 * 1000;
|
||||
const CURRENT_USER_CACHE_KEY = "auth-cache:current-user";
|
||||
const PROFILE_OVERVIEW_CACHE_KEY = "auth-cache:profile-overview";
|
||||
const MY_PERMISSIONS_CACHE_KEY = "auth-cache:my-permissions";
|
||||
const memoryRequestCache = new Map<string, { expiresAt: number; value: unknown }>();
|
||||
const inFlightRequestCache = new Map<string, Promise<unknown>>();
|
||||
let authExpiryTimer: number | null = null;
|
||||
|
|
@ -1235,6 +1246,29 @@ export async function refreshCurrentUser() {
|
|||
return profile;
|
||||
}
|
||||
|
||||
export async function listMyPermissions() {
|
||||
return getCachedAuthedRequest<UserPermission[]>(
|
||||
MY_PERMISSIONS_CACHE_KEY,
|
||||
() => request<UserPermission[]>("/api/sys/api/permissions/me", undefined, true),
|
||||
);
|
||||
}
|
||||
|
||||
export function canUsePermission(perm: string, codes: string[]) {
|
||||
if (!perm) {
|
||||
return true;
|
||||
}
|
||||
if (!codes.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hasMenuCodes = codes.some((code) => code.startsWith("menu:"));
|
||||
const hasButtonCodes = codes.some((code) => !code.startsWith("menu:") && code.includes(":"));
|
||||
if (perm.startsWith("menu:")) {
|
||||
return !hasMenuCodes || codes.includes(perm);
|
||||
}
|
||||
return !hasButtonCodes || codes.includes(perm);
|
||||
}
|
||||
|
||||
export async function getDashboardHome() {
|
||||
return request<DashboardHome>("/api/dashboard/home", undefined, true);
|
||||
}
|
||||
|
|
@ -1650,7 +1684,7 @@ function writeCachedValue<T>(cacheKey: string, value: T, ttlMs = USER_CONTEXT_CA
|
|||
}
|
||||
|
||||
function clearCachedAuthContext() {
|
||||
[CURRENT_USER_CACHE_KEY, PROFILE_OVERVIEW_CACHE_KEY].forEach((cacheKey) => {
|
||||
[CURRENT_USER_CACHE_KEY, PROFILE_OVERVIEW_CACHE_KEY, MY_PERMISSIONS_CACHE_KEY].forEach((cacheKey) => {
|
||||
memoryRequestCache.delete(cacheKey);
|
||||
inFlightRequestCache.delete(cacheKey);
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Search, Plus, Download, MapPin, Building2, User, Phone, X, Clock, FileT
|
|||
import { motion, AnimatePresence } from "motion/react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import {
|
||||
canUsePermission,
|
||||
checkChannelExpansionDuplicate,
|
||||
checkSalesExpansionDuplicate,
|
||||
createChannelExpansion,
|
||||
|
|
@ -13,6 +14,7 @@ import {
|
|||
getExpansionOverview,
|
||||
getOpportunityMeta,
|
||||
getStoredCurrentUserId,
|
||||
listMyPermissions,
|
||||
updateChannelExpansion,
|
||||
updateSalesExpansion,
|
||||
type ChannelExpansionContact,
|
||||
|
|
@ -138,6 +140,7 @@ function createEmptyChannelContact(): ChannelExpansionContact {
|
|||
}
|
||||
|
||||
const CHANNEL_REVENUE_LABEL = "年度营业额(万元)";
|
||||
const EXPANSION_CREATE_PERMISSION = "expansion:create";
|
||||
const EXPANSION_EXPORT_PREFERENCES_STORAGE_KEY = "crm:expansion-export-preferences";
|
||||
|
||||
const defaultSalesForm: CreateSalesExpansionPayload = {
|
||||
|
|
@ -1353,6 +1356,7 @@ export default function Expansion() {
|
|||
const [exporting, setExporting] = useState(false);
|
||||
const [exportFilterOpen, setExportFilterOpen] = useState(false);
|
||||
const [exportFilters, setExportFilters] = useState<ExpansionExportFilters>(() => loadExpansionExportPreferences());
|
||||
const [permissionCodes, setPermissionCodes] = useState<string[] | null>(null);
|
||||
const [salesDuplicateChecking, setSalesDuplicateChecking] = useState(false);
|
||||
const [channelDuplicateChecking, setChannelDuplicateChecking] = useState(false);
|
||||
const [createError, setCreateError] = useState("");
|
||||
|
|
@ -1375,6 +1379,7 @@ export default function Expansion() {
|
|||
const [editSalesForm, setEditSalesForm] = useState<CreateSalesExpansionPayload>(defaultSalesForm);
|
||||
const [editChannelForm, setEditChannelForm] = useState<CreateChannelExpansionPayload>(defaultChannelForm);
|
||||
const hasForegroundModal = createOpen || editOpen || exportFilterOpen;
|
||||
const canCreateExpansion = permissionCodes !== null && canUsePermission(EXPANSION_CREATE_PERMISSION, permissionCodes);
|
||||
|
||||
const loadMeta = useCallback(async () => {
|
||||
const data = await getExpansionMeta();
|
||||
|
|
@ -1388,6 +1393,33 @@ export default function Expansion() {
|
|||
return data;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
async function loadPermissions() {
|
||||
try {
|
||||
const permissions = await listMyPermissions();
|
||||
if (!cancelled) {
|
||||
setPermissionCodes(
|
||||
permissions
|
||||
.filter((permission) => permission.status !== 0)
|
||||
.map((permission) => permission.code)
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setPermissionCodes(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadPermissions();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
|
|
@ -2516,13 +2548,15 @@ export default function Expansion() {
|
|||
<Download className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">{exporting ? "导出中..." : "导出"}</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleOpenCreate}
|
||||
className={cn("crm-btn-sm crm-btn-primary flex items-center gap-2", disableMobileMotion ? "active:scale-100" : "active:scale-95")}
|
||||
>
|
||||
<Plus className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">新增</span>
|
||||
</button>
|
||||
{canCreateExpansion ? (
|
||||
<button
|
||||
onClick={handleOpenCreate}
|
||||
className={cn("crm-btn-sm crm-btn-primary flex items-center gap-2", disableMobileMotion ? "active:scale-100" : "active:scale-95")}
|
||||
>
|
||||
<Plus className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">新增</span>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useLocation } from "react-router-dom";
|
|||
import {
|
||||
checkChannelExpansionDuplicate,
|
||||
checkSalesExpansionDuplicate,
|
||||
canUsePermission,
|
||||
createChannelExpansion,
|
||||
createOpportunity,
|
||||
createSalesExpansion,
|
||||
|
|
@ -17,6 +18,7 @@ import {
|
|||
getOpportunityOmsPreSalesOptions,
|
||||
getOpportunityOverview,
|
||||
getStoredCurrentUserId,
|
||||
listMyPermissions,
|
||||
pushOpportunityToOms,
|
||||
updateOpportunity,
|
||||
type ChannelExpansionContact,
|
||||
|
|
@ -68,6 +70,7 @@ const OPPORTUNITY_EXPANSION_OPTION_LIMIT = 20;
|
|||
const OPPORTUNITY_EXPANSION_SEARCH_DEBOUNCE_MS = 300;
|
||||
const OPPORTUNITY_NEXT_PLAN_LABEL = "下一步销售计划";
|
||||
const LEGACY_OPPORTUNITY_NEXT_PLAN_LABEL = "后续规划";
|
||||
const OPPORTUNITY_CREATE_PERMISSION = "opportunity:create";
|
||||
const OPPORTUNITY_EXPORT_PREFERENCES_STORAGE_KEY = "crm:opportunity-export-preferences";
|
||||
|
||||
const COMPETITOR_OPTIONS = [
|
||||
|
|
@ -1854,6 +1857,7 @@ export default function Opportunities() {
|
|||
const [exporting, setExporting] = useState(false);
|
||||
const [exportFilterOpen, setExportFilterOpen] = useState(false);
|
||||
const [exportFilters, setExportFilters] = useState<OpportunityExportFilters>(() => loadOpportunityExportPreferences());
|
||||
const [permissionCodes, setPermissionCodes] = useState<string[] | null>(null);
|
||||
const [error, setError] = useState("");
|
||||
const [exportError, setExportError] = useState("");
|
||||
const [items, setItems] = useState<OpportunityItem[]>([]);
|
||||
|
|
@ -1898,12 +1902,40 @@ export default function Opportunities() {
|
|||
const [loadingChannelExpansionOptions, setLoadingChannelExpansionOptions] = useState(false);
|
||||
const hasLoadedOpportunityExpansionOptionsRef = useRef(false);
|
||||
const hasForegroundModal = createOpen || editOpen || pushConfirmOpen || exportFilterOpen || quickCreateOpen;
|
||||
const canCreateOpportunity = permissionCodes !== null && canUsePermission(OPPORTUNITY_CREATE_PERMISSION, permissionCodes);
|
||||
|
||||
const fetchOpportunityExpansionOptions = async (query?: string) => getOpportunityExpansionOptions({
|
||||
keyword: query,
|
||||
limit: OPPORTUNITY_EXPANSION_OPTION_LIMIT,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
async function loadPermissions() {
|
||||
try {
|
||||
const permissions = await listMyPermissions();
|
||||
if (!cancelled) {
|
||||
setPermissionCodes(
|
||||
permissions
|
||||
.filter((permission) => permission.status !== 0)
|
||||
.map((permission) => permission.code)
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setPermissionCodes(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadPermissions();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
|
|
@ -2867,13 +2899,15 @@ export default function Opportunities() {
|
|||
<Download className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">{exporting ? "导出中..." : "导出"}</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={handleOpenCreate}
|
||||
className={cn("crm-btn-sm crm-btn-primary flex items-center gap-2", disableMobileMotion ? "active:scale-100" : "active:scale-95")}
|
||||
>
|
||||
<Plus className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">新增商机</span>
|
||||
</button>
|
||||
{canCreateOpportunity ? (
|
||||
<button
|
||||
onClick={handleOpenCreate}
|
||||
className={cn("crm-btn-sm crm-btn-primary flex items-center gap-2", disableMobileMotion ? "active:scale-100" : "active:scale-95")}
|
||||
>
|
||||
<Plus className="crm-icon-md" />
|
||||
<span className="hidden sm:inline">新增商机</span>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UnisBase - 智能会议系统</title>
|
||||
<script type="module" crossorigin src="/assets/index-CibjLtv7.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-DNoKV8lp.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CaWPk49l.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ function isPlatformOnlyMenu(item: SysPermission) {
|
|||
|| item.path === "/platform-settings";
|
||||
}
|
||||
|
||||
function isPermissionOnlyMenu(item: SysPermission) {
|
||||
return item.code === "crm"
|
||||
|| item.code === "menu:expansion"
|
||||
|| item.code === "menu:opportunities";
|
||||
}
|
||||
|
||||
function resolveSelectedMenuPath(pathname: string): string {
|
||||
if (pathname.startsWith("/dashboard-analytics-settings/cards/")) {
|
||||
return "/dashboard-analytics-settings";
|
||||
|
|
@ -143,6 +149,7 @@ export default function AppLayout() {
|
|||
|
||||
const filtered = data
|
||||
.filter((item) => isPlatformMode || !isPlatformOnlyMenu(item))
|
||||
.filter((item) => !isPermissionOnlyMenu(item))
|
||||
.filter((item) => (item.permType === "menu" || item.permType === "directory") && item.isVisible === 1 && item.status === 1)
|
||||
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
|
||||
setMenus(filtered);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
-- 20260630
|
||||
-- 修复/补齐前台拓展管理“新增”按钮权限点:expansion:create
|
||||
-- 执行后可在 frontend1 角色管理的功能权限树中看到:CRM业务 / 拓展 / 新增拓展。
|
||||
-- 可重复执行;CRM业务与拓展节点仅用于权限管理,不在后台侧边栏显示。
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to public;
|
||||
|
||||
do $$
|
||||
declare
|
||||
v_business_parent_id bigint;
|
||||
v_expansion_menu_perm_id bigint;
|
||||
v_expansion_create_perm_id bigint;
|
||||
v_has_role_permission_tenant boolean;
|
||||
begin
|
||||
perform setval('sys_permission_perm_id_seq', coalesce((select max(perm_id) from sys_permission), 0) + 1, false);
|
||||
perform setval('sys_role_permission_id_seq', coalesce((select max(id) from sys_role_permission), 0) + 1, false);
|
||||
|
||||
select exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = current_schema()
|
||||
and table_name = 'sys_role_permission'
|
||||
and column_name = 'tenant_id'
|
||||
) into v_has_role_permission_tenant;
|
||||
|
||||
select perm_id
|
||||
into v_business_parent_id
|
||||
from sys_permission
|
||||
where code = 'crm'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_business_parent_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
null, 'CRM业务', 'crm', 'directory', 1, null, null, 'AppstoreOutlined',
|
||||
10, 0, 1, 'CRM前台业务权限分组,仅用于权限管理,不在后台侧边栏显示', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_business_parent_id;
|
||||
else
|
||||
update sys_permission
|
||||
set name = 'CRM业务',
|
||||
perm_type = 'directory',
|
||||
level = 1,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = coalesce(nullif(icon, ''), 'AppstoreOutlined'),
|
||||
sort_order = coalesce(sort_order, 10),
|
||||
is_visible = 0,
|
||||
status = 1,
|
||||
description = 'CRM前台业务权限分组,仅用于权限管理,不在后台侧边栏显示',
|
||||
meta = coalesce(meta, '{}'::jsonb),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_business_parent_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_expansion_menu_perm_id
|
||||
from sys_permission
|
||||
where code = 'menu:expansion'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_expansion_menu_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_business_parent_id, '拓展', 'menu:expansion', 'menu', 2,
|
||||
null, null, 'TeamOutlined', 20, 0, 1,
|
||||
'CRM前台拓展管理页面权限分组,仅用于权限管理,不在后台侧边栏显示', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_expansion_menu_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_business_parent_id,
|
||||
name = '拓展',
|
||||
perm_type = 'menu',
|
||||
level = 2,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = coalesce(nullif(icon, ''), 'TeamOutlined'),
|
||||
sort_order = coalesce(sort_order, 20),
|
||||
is_visible = 0,
|
||||
status = 1,
|
||||
description = 'CRM前台拓展管理页面权限分组,仅用于权限管理,不在后台侧边栏显示',
|
||||
meta = coalesce(meta, '{}'::jsonb),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_expansion_menu_perm_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_expansion_create_perm_id
|
||||
from sys_permission
|
||||
where code = 'expansion:create'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_expansion_create_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_expansion_menu_perm_id, '新增拓展', 'expansion:create', 'button', 3,
|
||||
null, null, null, 1, 1, 1, '控制CRM前台拓展管理页面的新增按钮和销售/渠道拓展创建接口', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_expansion_create_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_expansion_menu_perm_id,
|
||||
name = '新增拓展',
|
||||
perm_type = 'button',
|
||||
level = 3,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = null,
|
||||
sort_order = 1,
|
||||
is_visible = 1,
|
||||
status = 1,
|
||||
description = '控制CRM前台拓展管理页面的新增按钮和销售/渠道拓展创建接口',
|
||||
meta = '{}'::jsonb,
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_expansion_create_perm_id;
|
||||
end if;
|
||||
|
||||
if v_has_role_permission_tenant then
|
||||
insert into sys_role_permission (role_id, perm_id, tenant_id, is_deleted, created_at, updated_at)
|
||||
select distinct r.role_id, permission_source.perm_id, r.tenant_id, 0, now(), now()
|
||||
from sys_role r
|
||||
cross join (
|
||||
select unnest(array[v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id]) as perm_id
|
||||
) permission_source
|
||||
where coalesce(r.is_deleted, 0) = 0
|
||||
and permission_source.perm_id is not null
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
)
|
||||
and not exists (
|
||||
select 1
|
||||
from sys_role_permission rp
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id = permission_source.perm_id
|
||||
);
|
||||
|
||||
update sys_role_permission rp
|
||||
set tenant_id = coalesce(rp.tenant_id, r.tenant_id),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
from sys_role r
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id in (v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id)
|
||||
and coalesce(r.is_deleted, 0) = 0
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
);
|
||||
else
|
||||
insert into sys_role_permission (role_id, perm_id, is_deleted, created_at, updated_at)
|
||||
select distinct r.role_id, permission_source.perm_id, 0, now(), now()
|
||||
from sys_role r
|
||||
cross join (
|
||||
select unnest(array[v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id]) as perm_id
|
||||
) permission_source
|
||||
where coalesce(r.is_deleted, 0) = 0
|
||||
and permission_source.perm_id is not null
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
)
|
||||
and not exists (
|
||||
select 1
|
||||
from sys_role_permission rp
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id = permission_source.perm_id
|
||||
);
|
||||
|
||||
update sys_role_permission rp
|
||||
set is_deleted = 0,
|
||||
updated_at = now()
|
||||
from sys_role r
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id in (v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id)
|
||||
and coalesce(r.is_deleted, 0) = 0
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
);
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
commit;
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
-- 20260630
|
||||
-- 新增前台业务按钮权限点:
|
||||
-- opportunity:create 新增商机
|
||||
-- expansion:create 新增拓展
|
||||
-- 执行后可在 frontend1 权限管理与角色权限绑定中维护这些权限。
|
||||
-- 可重复执行;已执行过旧版本的环境,重新执行本脚本会修复父子关系和管理员授权。
|
||||
|
||||
begin;
|
||||
|
||||
set search_path to public;
|
||||
|
||||
do $$
|
||||
declare
|
||||
v_business_parent_id bigint;
|
||||
v_expansion_menu_perm_id bigint;
|
||||
v_expansion_create_perm_id bigint;
|
||||
v_menu_perm_id bigint;
|
||||
v_create_perm_id bigint;
|
||||
v_has_role_permission_tenant boolean;
|
||||
begin
|
||||
perform setval('sys_permission_perm_id_seq', coalesce((select max(perm_id) from sys_permission), 0) + 1, false);
|
||||
perform setval('sys_role_permission_id_seq', coalesce((select max(id) from sys_role_permission), 0) + 1, false);
|
||||
|
||||
select exists (
|
||||
select 1
|
||||
from information_schema.columns
|
||||
where table_schema = current_schema()
|
||||
and table_name = 'sys_role_permission'
|
||||
and column_name = 'tenant_id'
|
||||
) into v_has_role_permission_tenant;
|
||||
|
||||
select perm_id
|
||||
into v_business_parent_id
|
||||
from sys_permission
|
||||
where code = 'crm'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_business_parent_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
null, 'CRM业务', 'crm', 'directory', 1, null, null, 'AppstoreOutlined',
|
||||
10, 0, 1, 'CRM前台业务权限分组,仅用于权限管理,不在后台侧边栏显示', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_business_parent_id;
|
||||
else
|
||||
update sys_permission
|
||||
set name = 'CRM业务',
|
||||
perm_type = 'directory',
|
||||
level = 1,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = coalesce(nullif(icon, ''), 'AppstoreOutlined'),
|
||||
sort_order = coalesce(sort_order, 10),
|
||||
is_visible = 0,
|
||||
status = 1,
|
||||
description = 'CRM前台业务权限分组,仅用于权限管理,不在后台侧边栏显示',
|
||||
meta = coalesce(meta, '{}'::jsonb),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_business_parent_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_expansion_menu_perm_id
|
||||
from sys_permission
|
||||
where code = 'menu:expansion'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_expansion_menu_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_business_parent_id, '拓展', 'menu:expansion', 'menu', 2,
|
||||
null, null, 'TeamOutlined', 20, 0, 1,
|
||||
'CRM前台拓展管理页面权限分组,仅用于权限管理,不在后台侧边栏显示', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_expansion_menu_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_business_parent_id,
|
||||
name = '拓展',
|
||||
perm_type = 'menu',
|
||||
level = 2,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = coalesce(nullif(icon, ''), 'TeamOutlined'),
|
||||
sort_order = coalesce(sort_order, 20),
|
||||
is_visible = 0,
|
||||
status = 1,
|
||||
description = 'CRM前台拓展管理页面权限分组,仅用于权限管理,不在后台侧边栏显示',
|
||||
meta = coalesce(meta, '{}'::jsonb),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_expansion_menu_perm_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_expansion_create_perm_id
|
||||
from sys_permission
|
||||
where code = 'expansion:create'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_expansion_create_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_expansion_menu_perm_id, '新增拓展', 'expansion:create', 'button', 3,
|
||||
null, null, null, 1, 1, 1, '控制CRM前台拓展管理页面的新增按钮和销售/渠道拓展创建接口', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_expansion_create_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_expansion_menu_perm_id,
|
||||
name = '新增拓展',
|
||||
perm_type = 'button',
|
||||
level = 3,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = null,
|
||||
sort_order = 1,
|
||||
is_visible = 1,
|
||||
status = 1,
|
||||
description = '控制CRM前台拓展管理页面的新增按钮和销售/渠道拓展创建接口',
|
||||
meta = '{}'::jsonb,
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_expansion_create_perm_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_menu_perm_id
|
||||
from sys_permission
|
||||
where code = 'menu:opportunities'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_menu_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_business_parent_id, '商机', 'menu:opportunities', 'menu', 2,
|
||||
null, null, 'BriefcaseOutlined', 30, 0, 1,
|
||||
'CRM前台商机储备页面权限分组,仅用于权限管理,不在后台侧边栏显示', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_menu_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_business_parent_id,
|
||||
name = '商机',
|
||||
perm_type = 'menu',
|
||||
level = 2,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = coalesce(nullif(icon, ''), 'BriefcaseOutlined'),
|
||||
sort_order = coalesce(sort_order, 30),
|
||||
is_visible = 0,
|
||||
status = 1,
|
||||
description = 'CRM前台商机储备页面权限分组,仅用于权限管理,不在后台侧边栏显示',
|
||||
meta = coalesce(meta, '{}'::jsonb),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_menu_perm_id;
|
||||
end if;
|
||||
|
||||
select perm_id
|
||||
into v_create_perm_id
|
||||
from sys_permission
|
||||
where code = 'opportunity:create'
|
||||
order by perm_id
|
||||
limit 1;
|
||||
|
||||
if v_create_perm_id is null then
|
||||
insert into sys_permission (
|
||||
parent_id, name, code, perm_type, level, path, component, icon,
|
||||
sort_order, is_visible, status, description, meta, is_deleted, created_at, updated_at
|
||||
) values (
|
||||
v_menu_perm_id, '新增商机', 'opportunity:create', 'button', 3,
|
||||
null, null, null, 1, 1, 1, '控制CRM前台商机储备页面的新增商机按钮和创建接口', '{}'::jsonb, 0, now(), now()
|
||||
)
|
||||
returning perm_id into v_create_perm_id;
|
||||
else
|
||||
update sys_permission
|
||||
set parent_id = v_menu_perm_id,
|
||||
name = '新增商机',
|
||||
perm_type = 'button',
|
||||
level = 3,
|
||||
path = null,
|
||||
component = null,
|
||||
icon = null,
|
||||
sort_order = 1,
|
||||
is_visible = 1,
|
||||
status = 1,
|
||||
description = '控制CRM前台商机储备页面的新增商机按钮和创建接口',
|
||||
meta = '{}'::jsonb,
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
where perm_id = v_create_perm_id;
|
||||
end if;
|
||||
|
||||
if v_has_role_permission_tenant then
|
||||
insert into sys_role_permission (role_id, perm_id, tenant_id, is_deleted, created_at, updated_at)
|
||||
select distinct r.role_id, permission_source.perm_id, r.tenant_id, 0, now(), now()
|
||||
from sys_role r
|
||||
cross join (
|
||||
select unnest(array[v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id, v_menu_perm_id, v_create_perm_id]) as perm_id
|
||||
) permission_source
|
||||
where coalesce(r.is_deleted, 0) = 0
|
||||
and permission_source.perm_id is not null
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
)
|
||||
and not exists (
|
||||
select 1
|
||||
from sys_role_permission rp
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id = permission_source.perm_id
|
||||
);
|
||||
|
||||
update sys_role_permission rp
|
||||
set tenant_id = coalesce(rp.tenant_id, r.tenant_id),
|
||||
is_deleted = 0,
|
||||
updated_at = now()
|
||||
from sys_role r
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id in (v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id, v_menu_perm_id, v_create_perm_id)
|
||||
and coalesce(r.is_deleted, 0) = 0
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
);
|
||||
else
|
||||
insert into sys_role_permission (role_id, perm_id, is_deleted, created_at, updated_at)
|
||||
select distinct r.role_id, permission_source.perm_id, 0, now(), now()
|
||||
from sys_role r
|
||||
cross join (
|
||||
select unnest(array[v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id, v_menu_perm_id, v_create_perm_id]) as perm_id
|
||||
) permission_source
|
||||
where coalesce(r.is_deleted, 0) = 0
|
||||
and permission_source.perm_id is not null
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
)
|
||||
and not exists (
|
||||
select 1
|
||||
from sys_role_permission rp
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id = permission_source.perm_id
|
||||
);
|
||||
|
||||
update sys_role_permission rp
|
||||
set is_deleted = 0,
|
||||
updated_at = now()
|
||||
from sys_role r
|
||||
where rp.role_id = r.role_id
|
||||
and rp.perm_id in (v_business_parent_id, v_expansion_menu_perm_id, v_expansion_create_perm_id, v_menu_perm_id, v_create_perm_id)
|
||||
and coalesce(r.is_deleted, 0) = 0
|
||||
and (
|
||||
r.role_code in ('TENANT_ADMIN', 'ADMIN', 'SYS_ADMIN', 'PLATFORM_ADMIN', 'SUPER_ADMIN')
|
||||
or r.role_name ilike '%管理员%'
|
||||
or r.role_name ilike '%admin%'
|
||||
);
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
commit;
|
||||
Loading…
Reference in New Issue