完善后台管理与测试支撑

1、为后台用户列表增加关键词和状态筛选,后端同步支持过滤与总数统计。

2、创建用户时要求填写初始密码,并补充前端校验和自动填充隔离。

3、优化项目管理列表角色展示、项目详情抽屉脏数据保护和审计详情抽屉关闭体验。

4、清理旧费用附件关联、统一测试模型注册,并更新迁移端点和注册筛选测试。
This commit is contained in:
Cheng Zhou
2026-06-04 11:12:40 +08:00
parent 90ca061db8
commit 41968384b5
17 changed files with 337 additions and 145 deletions
+19 -6
View File
@@ -1653,7 +1653,8 @@
v-model="projectMilestoneEditorVisible"
direction="rtl"
size="480px"
:close-on-click-modal="false"
:close-on-click-modal="true"
:before-close="projectMilestoneEditorDirtyGuard.beforeClose"
:show-close="false"
class="setup-milestone-editor-drawer"
>
@@ -1756,7 +1757,8 @@
v-model="siteMilestoneEditorVisible"
direction="rtl"
size="480px"
:close-on-click-modal="false"
:close-on-click-modal="true"
:before-close="siteMilestoneEditorDirtyGuard.beforeClose"
:show-close="false"
class="setup-milestone-editor-drawer"
>
@@ -1836,7 +1838,8 @@
v-model="siteEnrollmentEditorVisible"
direction="rtl"
size="480px"
:close-on-click-modal="false"
:close-on-click-modal="true"
:before-close="siteEnrollmentEditorDirtyGuard.beforeClose"
:show-close="false"
class="setup-milestone-editor-drawer"
>
@@ -1936,6 +1939,7 @@ import { isSystemAdmin } from "../../utils/roles";
import { isApiPermissionAllowed } from "../../utils/apiPermissionValue";
import { groupErrorsBySection, parseFieldPath, type SetupValidationError } from "../../utils/setupFieldLocator";
import { buildSetupReadableDiffRows, serializeDiffValue, type SetupDiffRow } from "../../utils/setupDiffRows";
import { useDrawerDirtyGuard } from "../../utils/drawerDirtyGuard";
import {
SETUP_WORKFLOW_TAG_META,
buildProjectDiffRows,
@@ -2161,6 +2165,9 @@ const siteEnrollmentEditorForm = reactive<SiteEnrollmentPlanDraft>({
note: "",
stageBreakdown: "",
});
const projectMilestoneEditorDirtyGuard = useDrawerDirtyGuard(() => projectMilestoneEditorForm);
const siteMilestoneEditorDirtyGuard = useDrawerDirtyGuard(() => siteMilestoneEditorForm);
const siteEnrollmentEditorDirtyGuard = useDrawerDirtyGuard(() => siteEnrollmentEditorForm);
type EnrollmentCycle = "month" | "quarter";
@@ -4394,6 +4401,9 @@ const loadProject = async () => {
const { data } = studyRes;
project.value = data as Study;
projectPermissions.value = permRes.data as any;
studyStore.setViewContext({
pageTitle: project.value.name || TEXT.modules.adminProjects.detailTitle,
});
if (!canReadSetupConfig.value) {
ElMessage.warning("当前角色无权访问立项配置");
@@ -5694,7 +5704,7 @@ const removeProjectMilestone = (index: number) => {
setupDraft.projectMilestones.splice(index, 1);
};
const openProjectMilestoneEditor = (index: number) => {
openIndexedEditor(setupDraft.projectMilestones, index, projectMilestoneEditor, (row) => {
const opened = openIndexedEditor(setupDraft.projectMilestones, index, projectMilestoneEditor, (row) => {
projectMilestoneEditorForm.id = row.id || "";
projectMilestoneEditorForm.name = row.name || "";
projectMilestoneEditorForm.startDate = resolveProjectMilestoneStart(row);
@@ -5705,6 +5715,7 @@ const openProjectMilestoneEditor = (index: number) => {
projectMilestoneEditorForm.remark = row.remark || "";
projectMilestoneEditorForm.status = row.status || "未开始";
});
if (opened) projectMilestoneEditorDirtyGuard.syncBaseline();
};
const saveProjectMilestoneEditor = () => {
if (!canMutateDraft()) return;
@@ -5784,7 +5795,7 @@ const removeSiteMilestone = (index: number) => {
setupDraft.siteMilestones.splice(index, 1);
};
const openSiteMilestoneEditor = (index: number) => {
openIndexedEditor(setupDraft.siteMilestones, index, siteMilestoneEditor, (row) => {
const opened = openIndexedEditor(setupDraft.siteMilestones, index, siteMilestoneEditor, (row) => {
siteMilestoneEditorForm.id = row.id || "";
siteMilestoneEditorForm.milestone = row.milestone || "";
siteMilestoneEditorForm.planDate = row.planDate || "";
@@ -5792,6 +5803,7 @@ const openSiteMilestoneEditor = (index: number) => {
siteMilestoneEditorForm.remark = row.remark || "";
siteMilestoneEditorForm.status = row.status || "未开始";
});
if (opened) siteMilestoneEditorDirtyGuard.syncBaseline();
};
const saveSiteMilestoneEditor = () => {
if (!canMutateDraft()) return;
@@ -5832,7 +5844,7 @@ const removeSiteEnrollment = (index: number) => {
setupDraft.siteEnrollmentPlans.splice(index, 1);
};
const openSiteEnrollmentEditor = (index: number) => {
openIndexedEditor(setupDraft.siteEnrollmentPlans, index, siteEnrollmentEditor, (row) => {
const opened = openIndexedEditor(setupDraft.siteEnrollmentPlans, index, siteEnrollmentEditor, (row) => {
siteEnrollmentEditorForm.id = row.id || "";
siteEnrollmentEditorForm.siteId = row.siteId || "";
siteEnrollmentEditorForm.siteName = row.siteName || "";
@@ -5842,6 +5854,7 @@ const openSiteEnrollmentEditor = (index: number) => {
siteEnrollmentEditorForm.note = row.note || "";
siteEnrollmentEditorForm.stageBreakdown = row.stageBreakdown || "";
});
if (opened) siteEnrollmentEditorDirtyGuard.syncBaseline();
};
const saveSiteEnrollmentEditor = () => {
if (!canMutateDraft()) return;