统一业务页面权限与抽屉编辑
1、将 FAQ 分类和问题维护改为抽屉交互,并按分类、问题、回复的细粒度权限控制入口。 2、将注意事项、可行性和伦理记录接入详情页抽屉编辑,创建时支持先保存主记录再上传附件。 3、将参与者基础信息编辑改为抽屉,详情页按可读权限显示病史、访视、AE 和 PD 标签页。 4、补充业务页面权限一致性测试,覆盖停用中心、无权限入口和面包屑上下文。
This commit is contained in:
@@ -102,9 +102,9 @@
|
||||
<el-table-column prop="remark" :label="TEXT.modules.projectMilestones.columns.remark" show-overflow-tooltip>
|
||||
<template #default="scope">{{ scope.row.remark || TEXT.common.fallback }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="TEXT.modules.projectMilestones.columns.operations" width="100">
|
||||
<el-table-column v-if="canUpdateMilestones" :label="TEXT.modules.projectMilestones.columns.operations" width="100">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="openEditor(scope.row)">{{ TEXT.common.actions.edit }}</el-button>
|
||||
<el-button v-if="canUpdateMilestones" link type="primary" @click="openEditor(scope.row)">{{ TEXT.common.actions.edit }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty>
|
||||
@@ -120,7 +120,8 @@
|
||||
v-model="editorVisible"
|
||||
direction="rtl"
|
||||
size="460px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-click-modal="true"
|
||||
:before-close="editorDirtyGuard.beforeClose"
|
||||
:show-close="false"
|
||||
class="milestone-editor-drawer"
|
||||
>
|
||||
@@ -185,7 +186,7 @@
|
||||
<template #footer>
|
||||
<div class="time-editor-footer">
|
||||
<el-button @click="editorVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
|
||||
<el-button type="primary" @click="saveEditor">{{ TEXT.common.actions.save }}</el-button>
|
||||
<el-button v-if="canUpdateMilestones" type="primary" @click="saveEditor">{{ TEXT.common.actions.save }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
@@ -200,6 +201,8 @@ import { listProjectMilestones, updateProjectMilestone } from "../../api/project
|
||||
import { TEXT } from "../../locales";
|
||||
import StateEmpty from "../../components/StateEmpty.vue";
|
||||
import { displayDateTime } from "../../utils/display";
|
||||
import { usePermission } from "../../utils/permission";
|
||||
import { useDrawerDirtyGuard } from "../../utils/drawerDirtyGuard";
|
||||
|
||||
interface MilestoneRow {
|
||||
id: string;
|
||||
@@ -231,6 +234,7 @@ type MilestoneLocalEdit = {
|
||||
};
|
||||
|
||||
const study = useStudyStore();
|
||||
const { can } = usePermission();
|
||||
const rows = ref<MilestoneRow[]>([]);
|
||||
const loading = ref(false);
|
||||
const dataSourceLabel = ref<string>(TEXT.modules.projectMilestones.sourcePublished);
|
||||
@@ -244,8 +248,10 @@ const editorForm = reactive<MilestoneLocalEdit>({
|
||||
actualEndDate: "",
|
||||
remark: "",
|
||||
});
|
||||
const editorDirtyGuard = useDrawerDirtyGuard(() => editorForm);
|
||||
|
||||
const doneCount = computed(() => rows.value.filter((item) => getStatusView(item).completed).length);
|
||||
const canUpdateMilestones = computed(() => can("project.milestones.update"));
|
||||
|
||||
const toDateOnly = (value?: string): Date | null => {
|
||||
if (!value) return null;
|
||||
@@ -398,18 +404,27 @@ const validateDateRange = (start?: string, end?: string, label?: string) => {
|
||||
};
|
||||
|
||||
const openEditor = (row: MilestoneRow) => {
|
||||
if (!canUpdateMilestones.value) {
|
||||
ElMessage.warning("权限不足");
|
||||
return;
|
||||
}
|
||||
editingRowId.value = row.id;
|
||||
editorForm.adjustedStartDate = row.adjustedStartDate || "";
|
||||
editorForm.adjustedEndDate = row.adjustedEndDate || "";
|
||||
editorForm.actualStartDate = row.actualStartDate || "";
|
||||
editorForm.actualEndDate = row.actualEndDate || "";
|
||||
editorForm.remark = row.remark || "";
|
||||
editorDirtyGuard.syncBaseline();
|
||||
editorVisible.value = true;
|
||||
};
|
||||
|
||||
const saveEditor = async () => {
|
||||
const studyId = study.currentStudy?.id;
|
||||
if (!studyId || !editingRowId.value) return;
|
||||
if (!canUpdateMilestones.value) {
|
||||
ElMessage.warning("权限不足");
|
||||
return;
|
||||
}
|
||||
if (!validateDateRange(editorForm.adjustedStartDate, editorForm.adjustedEndDate, "调整计划时间")) return;
|
||||
if (!validateDateRange(editorForm.actualStartDate, editorForm.actualEndDate, "实际时间")) return;
|
||||
const patch = {
|
||||
|
||||
Reference in New Issue
Block a user