feat(subject): 参与者状态依赖筛选日期并支持后续编辑
- 未填写筛选日期的参与者不再默认进入 SCREENING,状态显示为占位符。 - SubjectUpdate 不再开放 status 入参,改由后端依据日期推导,并新增 screening_date 字段允许 PM/CRA 后续补录筛选日期。 - 参与者管理页与详情页同步:详情页支持编辑筛选日期,列表页与详情页 在没有筛选日期时显示占位符而非旧 enum 值。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -85,7 +85,7 @@
|
||||
<template #default="scope">{{ displayDate(scope.row.consent_date) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" :label="TEXT.common.fields.status">
|
||||
<template #default="scope">{{ displayEnum(TEXT.enums.subjectStatus, scope.row.status) }}</template>
|
||||
<template #default="scope">{{ displaySubjectStatus(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="enrollment_date" :label="TEXT.common.fields.enrollmentDate">
|
||||
<template #default="scope">{{ displayDate(scope.row.enrollment_date) }}</template>
|
||||
@@ -227,6 +227,10 @@ const getAeBadges = (row: any) => {
|
||||
}
|
||||
return badges;
|
||||
};
|
||||
const displaySubjectStatus = (subject: any) => {
|
||||
if (!subject?.screening_date) return TEXT.common.fallback;
|
||||
return displayEnum(TEXT.enums.subjectStatus, subject.status);
|
||||
};
|
||||
const filteredItems = computed(() => {
|
||||
const keyword = filters.value.keyword.trim().toLowerCase();
|
||||
return items.value.filter((item) => {
|
||||
|
||||
@@ -30,9 +30,18 @@
|
||||
<el-descriptions-item :label="TEXT.modules.subjectManagement.screeningNo">{{ detail.subject_no || TEXT.common.fallback }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="TEXT.common.fields.site">{{ siteMap[detail.site_id] || TEXT.common.fallback }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="TEXT.common.fields.status">
|
||||
<span>{{ displayEnum(TEXT.enums.subjectStatus, detail.status) }}</span>
|
||||
<span>{{ displaySubjectStatus(detail) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="TEXT.common.fields.screeningDate">
|
||||
<el-date-picker
|
||||
v-if="subjectEditing"
|
||||
v-model="subjectForm.screening_date"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
size="small"
|
||||
/>
|
||||
<span v-else>{{ displayDate(detail.screening_date) }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :label="TEXT.common.fields.screeningDate">{{ displayDate(detail.screening_date) }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="TEXT.common.fields.consentDate">
|
||||
<el-date-picker
|
||||
v-if="subjectEditing"
|
||||
@@ -532,6 +541,7 @@ const detail = reactive<any>({
|
||||
const subjectEditing = ref(false);
|
||||
const subjectSaving = ref(false);
|
||||
const subjectForm = reactive({
|
||||
screening_date: "",
|
||||
enrollment_date: "",
|
||||
baseline_date: "",
|
||||
consent_date: "",
|
||||
@@ -665,6 +675,11 @@ const getErrorMessage = (error: any, fallback: string) => {
|
||||
return fallback;
|
||||
};
|
||||
|
||||
const displaySubjectStatus = (subject: any) => {
|
||||
if (!subject?.screening_date) return TEXT.common.fallback;
|
||||
return displayEnum(TEXT.enums.subjectStatus, subject.status);
|
||||
};
|
||||
|
||||
const loadSites = async () => {
|
||||
if (!studyId) return;
|
||||
try {
|
||||
@@ -702,6 +717,7 @@ const startSubjectEdit = () => {
|
||||
ElMessage.warning("中心已停用");
|
||||
return;
|
||||
}
|
||||
subjectForm.screening_date = detail.screening_date || "";
|
||||
subjectForm.consent_date = detail.consent_date || "";
|
||||
subjectForm.enrollment_date = detail.enrollment_date || "";
|
||||
subjectForm.baseline_date = detail.baseline_date || "";
|
||||
@@ -723,6 +739,7 @@ const saveSubjectEdit = async () => {
|
||||
subjectSaving.value = true;
|
||||
try {
|
||||
const payload = {
|
||||
screening_date: subjectForm.screening_date || null,
|
||||
consent_date: subjectForm.consent_date || null,
|
||||
enrollment_date: subjectForm.enrollment_date || null,
|
||||
baseline_date: subjectForm.baseline_date || null,
|
||||
|
||||
Reference in New Issue
Block a user