清理全局角色残留并修复项目权限判断

This commit is contained in:
Cheng Zhou
2026-05-29 10:20:42 +08:00
parent 63457aab11
commit 44d69c2d7b
63 changed files with 739 additions and 443 deletions
+34 -30
View File
@@ -56,10 +56,10 @@
</div>
<div class="setup-toolbar-actions">
<el-button v-if="canManageSetup" type="success" plain :loading="primarySaveLoading" :disabled="isPublishedView" @click="handlePrimarySaveConfig">保存配置</el-button>
<el-button v-if="canManageSetup" type="info" plain :disabled="isPublishedView || !publishedSetupDraft" @click="handleRefillDraft">一键回填</el-button>
<el-button v-if="canManageSetup" type="danger" plain :disabled="isPublishedView" @click="handleClearDraft">清空草稿</el-button>
<el-button v-if="canManageSetup" type="warning" plain :loading="publishConfirmLoading" @click="publishConfigNow">发布版本</el-button>
<el-button v-if="canUpdateSetupConfig" type="success" plain :loading="primarySaveLoading" :disabled="isPublishedView" @click="handlePrimarySaveConfig">保存配置</el-button>
<el-button v-if="canUpdateSetupConfig" type="info" plain :disabled="isPublishedView || !publishedSetupDraft" @click="handleRefillDraft">一键回填</el-button>
<el-button v-if="canUpdateSetupConfig" type="danger" plain :disabled="isPublishedView" @click="handleClearDraft">清空草稿</el-button>
<el-button v-if="canPublishSetupConfig" type="warning" plain :loading="publishConfirmLoading" @click="publishConfigNow">发布版本</el-button>
<el-button
type="info"
plain
@@ -1498,18 +1498,18 @@
</div>
<div class="rollback-axis-actions">
<el-tooltip content="回滚到此版本" placement="top" :show-after="300">
<el-button class="vm-action-btn vm-action-danger" size="small" @click="selectRollbackVersion(row.version)">
<el-button v-if="canRollbackSetupConfig" class="vm-action-btn vm-action-danger" size="small" @click="selectRollbackVersion(row.version)">
<el-icon :size="13"><RefreshLeft /></el-icon>
回滚
</el-button>
</el-tooltip>
<el-tooltip v-if="(row.branch_name || 'main') === 'main'" content="基于此版本新建分支草稿" placement="top" :show-after="300">
<el-tooltip v-if="canUpdateSetupConfig && (row.branch_name || 'main') === 'main'" content="基于此版本新建分支草稿" placement="top" :show-after="300">
<el-button class="vm-action-btn vm-action-primary" size="small" @click="checkoutBranchDraftFromVersion(row.version)">
<el-icon :size="13"><DocumentCopy /></el-icon>
新建分支草稿
</el-button>
</el-tooltip>
<el-tooltip v-if="(row.branch_name || 'main') !== 'main'" content="合并至主线创建新版本" placement="top" :show-after="300">
<el-tooltip v-if="canPublishSetupConfig && (row.branch_name || 'main') !== 'main'" content="合并至主线创建新版本" placement="top" :show-after="300">
<el-button class="vm-action-btn vm-action-primary" size="small" @click="mergeVersionToMain(row.version)">
<el-icon :size="13"><Connection /></el-icon>
合并主线新版本
@@ -1521,7 +1521,7 @@
下载
</el-button>
</el-tooltip>
<el-tooltip content="删除此版本" placement="top" :show-after="300">
<el-tooltip v-if="canDeleteSetupVersion" content="删除此版本" placement="top" :show-after="300">
<el-button
class="vm-action-btn vm-action-danger"
size="small"
@@ -2405,20 +2405,18 @@ const setupDraft = reactive<SetupConfigDraft>({
const storageKey = computed(() => `ctms_setup_config_draft_${String(route.params.projectId || "")}`);
const projectDraftStorageKey = computed(() => `ctms_setup_project_draft_${String(route.params.projectId || "")}`);
const projectPermissions = ref<Record<string, Record<string, any>> | null>(null);
const hasSetupReadPermission = computed(() => {
const selectedProjectPermissionAllowed = (operationKey: string) => {
if (isSystemAdmin(authStore.user)) return true;
if (!projectPermissions.value) return false;
const rolePerms = Object.values(projectPermissions.value)[0];
if (!rolePerms) return false;
return isApiPermissionAllowed(rolePerms["setup_config:update"]);
});
const canManageSetup = computed(() => {
if (isSystemAdmin(authStore.user)) return true;
if (!projectPermissions.value) return false;
const rolePerms = Object.values(projectPermissions.value)[0];
if (!rolePerms) return false;
return isApiPermissionAllowed(rolePerms["setup_config:update"]);
});
return isApiPermissionAllowed(rolePerms[operationKey]);
};
const canReadSetupConfig = computed(() => selectedProjectPermissionAllowed("setup_config:read"));
const canUpdateSetupConfig = computed(() => selectedProjectPermissionAllowed("setup_config:update"));
const canPublishSetupConfig = computed(() => selectedProjectPermissionAllowed("setup_config:publish"));
const canRollbackSetupConfig = computed(() => selectedProjectPermissionAllowed("setup_config:rollback"));
const canDeleteSetupVersion = computed(() => selectedProjectPermissionAllowed("setup_config:delete_version"));
const isPreviewView = computed(() => setupViewMode.value === "preview");
const isPublishedVersionView = computed(() => setupViewMode.value === "published");
const isPublishedView = computed(() => isPreviewView.value || isPublishedVersionView.value);
@@ -2429,7 +2427,7 @@ const currentSetupDraft = computed<SetupConfigDraft>(() => {
return setupDraft;
});
const canEditSetup = computed(
() => Boolean(project.value && !project.value?.is_locked && canManageSetup.value && !isPublishedView.value)
() => Boolean(project.value && !project.value?.is_locked && canUpdateSetupConfig.value && !isPublishedView.value)
);
const canMutateDraft = () => canEditSetup.value && !isPublishedView.value;
const canEditStep1BasicGroup = (group: Exclude<Step1EditSection, "all" | "summary">) =>
@@ -2482,8 +2480,8 @@ const closeIndexedEditor = (controller: IndexedEditorController, successMessage:
controller.index.value = -1;
ElMessage.success(successMessage);
};
const canSaveDraftAction = computed(() => Boolean(project.value && canManageSetup.value && !project.value?.is_locked && !isPublishedView.value));
const canPublishAction = computed(() => Boolean(project.value && canManageSetup.value && !project.value?.is_locked));
const canSaveDraftAction = computed(() => Boolean(project.value && canUpdateSetupConfig.value && !project.value?.is_locked && !isPublishedView.value));
const canPublishAction = computed(() => Boolean(project.value && canPublishSetupConfig.value && !project.value?.is_locked));
const currentStepTitle = computed(() => `${activeStep.value + 1}步:${steps[activeStep.value]?.label || ""}`);
const setupPublishedVersionText = computed(() => {
return setupPublishedVersion.value || "v0";
@@ -4397,7 +4395,7 @@ const loadProject = async () => {
project.value = data as Study;
projectPermissions.value = permRes.data as any;
if (!hasSetupReadPermission.value) {
if (!canReadSetupConfig.value) {
ElMessage.warning("当前角色无权访问立项配置");
router.replace("/admin/projects");
return;
@@ -4450,7 +4448,7 @@ const startEdit = () => {
ElMessage.info("当前为只读视图,请先切换到草稿后再编辑");
return;
}
if (!canManageSetup.value) {
if (!canUpdateSetupConfig.value) {
ElMessage.warning("当前角色无权编辑立项配置");
return;
}
@@ -4634,7 +4632,8 @@ const saveConfigNow = async (): Promise<boolean> => {
};
const doPublishConfigNow = async (): Promise<boolean> => {
if (!project.value || !canPublishAction.value) return false;
if (!project.value) return false;
if (!canPublishAction.value) return false;
try {
if (hasFormUnsavedChanges.value) {
syncProjectInfoIntoSetupDraft();
@@ -4695,7 +4694,8 @@ const doPublishConfigNow = async (): Promise<boolean> => {
};
const publishConfigNow = async () => {
if (!project.value || !canManageSetup.value) return;
if (!project.value) return;
if (!canPublishAction.value) return;
reconcileDraftSyncStateBeforePublish();
if (hasSetupDraftUnsavedChanges.value) {
ElMessage.warning("当前存在未上传的本地草稿,请先点击“保存配置”");
@@ -4960,13 +4960,14 @@ const isLatestPublishedVersion = (rawVersion: number): boolean => {
};
const openRollbackDialog = async () => {
if (!project.value || !canManageSetup.value) return;
if (!project.value || !canReadSetupConfig.value) return;
await loadSetupVersionHistory();
rollbackDialogVisible.value = true;
};
const selectRollbackVersion = async (targetVersion: number) => {
if (!project.value) return;
if (!canRollbackSetupConfig.value) return;
const targetDisplayVersion = getDisplayVersionLabel(targetVersion);
try {
await ElMessageBox.confirm(
@@ -5018,6 +5019,7 @@ const selectRollbackVersion = async (targetVersion: number) => {
const checkoutBranchDraftFromVersion = async (targetVersion: number) => {
if (!project.value) return;
if (!canUpdateSetupConfig.value) return;
const targetDisplayVersion = getDisplayVersionLabel(targetVersion);
try {
await ElMessageBox.confirm(
@@ -5344,6 +5346,7 @@ ${buildExcelWorksheetXml("第6步-中心确认", metaRows, step6Headers, step6Ro
const removeVersion = async (targetVersion: number) => {
if (!project.value) return;
if (!canDeleteSetupVersion.value) return;
if (isLatestPublishedVersion(targetVersion)) {
ElMessage.warning("当前发布版本不能删除");
return;
@@ -5372,6 +5375,7 @@ const removeVersion = async (targetVersion: number) => {
const mergeVersionToMain = async (sourceVersion: number) => {
if (!project.value) return;
if (!canPublishSetupConfig.value) return;
const sourceVersionLabel = getDisplayVersionLabel(sourceVersion);
try {
await ElMessageBox.confirm(
@@ -5420,7 +5424,7 @@ const mergeVersionToMain = async (sourceVersion: number) => {
};
const handleRefillDraft = async () => {
if (!project.value || !canManageSetup.value) return;
if (!project.value || !canUpdateSetupConfig.value) return;
try {
await ElMessageBox.confirm(
`确认将草稿一键回填为当前发布版本 ${setupPublishedVersionText.value} 的内容?`,
@@ -5468,7 +5472,7 @@ const handleRefillDraft = async () => {
};
const handleClearDraft = async () => {
if (!project.value || !canManageSetup.value) return;
if (!project.value || !canUpdateSetupConfig.value) return;
try {
await ElMessageBox.confirm(
"确认清空当前立项配置草稿的所有数据?该操作不会影响已发布版本。",
@@ -5521,7 +5525,7 @@ const ensureCanSaveDraftAction = (): boolean => {
ElMessage.warning("项目信息尚未加载完成,请稍后重试");
return false;
}
if (!canManageSetup.value) {
if (!canUpdateSetupConfig.value) {
ElMessage.warning("当前角色无权保存立项配置");
return false;
}
@@ -5641,7 +5645,7 @@ const ensureStep2Editable = (): boolean => {
ElMessage.info("当前为只读视图,请先切换到草稿后再操作");
return false;
}
if (!canManageSetup.value) {
if (!canUpdateSetupConfig.value) {
ElMessage.warning("当前角色无权编辑立项配置");
return false;
}