diff --git a/backend/app/uploads/study_fe3b62bf-48a7-43c3-b767-7f9f279cca32/project_fe3b62bf-48a7-43c3-b767-7f9f279cca32/06386bc5-61d0-467d-af5c-61fb0893c389.xlsx b/backend/app/uploads/study_fe3b62bf-48a7-43c3-b767-7f9f279cca32/project_fe3b62bf-48a7-43c3-b767-7f9f279cca32/06386bc5-61d0-467d-af5c-61fb0893c389.xlsx
new file mode 100644
index 00000000..56114440
Binary files /dev/null and b/backend/app/uploads/study_fe3b62bf-48a7-43c3-b767-7f9f279cca32/project_fe3b62bf-48a7-43c3-b767-7f9f279cca32/06386bc5-61d0-467d-af5c-61fb0893c389.xlsx differ
diff --git a/frontend/src/components/attachments/AttachmentList.vue b/frontend/src/components/attachments/AttachmentList.vue
index 0c52a4a9..2d39a519 100644
--- a/frontend/src/components/attachments/AttachmentList.vue
+++ b/frontend/src/components/attachments/AttachmentList.vue
@@ -14,7 +14,11 @@
{{ formatFileSize(scope.row.file_size) }}
-
+
+
+ {{ uploaderLabel(scope.row) }}
+
+
@@ -42,6 +46,8 @@ import AttachmentUploader from "./AttachmentUploader.vue";
import { formatFileSize } from "./attachmentUtils";
import { useAuthStore } from "../../store/auth";
import { useStudyStore } from "../../store/study";
+import { fetchUsers } from "../../api/users";
+import { listMembers } from "../../api/members";
const props = defineProps<{
studyId: string;
@@ -53,6 +59,8 @@ const attachments = ref([]);
const loading = ref(false);
const auth = useAuthStore();
const study = useStudyStore();
+const users = ref([]);
+const members = ref([]);
const load = async () => {
if (!props.studyId || !props.entityId) return;
@@ -67,6 +75,37 @@ const load = async () => {
}
};
+const loadUsers = async () => {
+ try {
+ const { data } = await fetchUsers({ limit: 500 });
+ users.value = (data as any).items || data || [];
+ } catch {
+ users.value = [];
+ }
+};
+
+const loadMembers = async () => {
+ if (!props.studyId) return;
+ try {
+ const { data } = await listMembers(props.studyId, { limit: 500 });
+ members.value = Array.isArray(data) ? data : data.items || [];
+ } catch {
+ members.value = [];
+ }
+};
+
+const uploaderLabel = (row: any) => {
+ const userMap = users.value.reduce>((acc, cur) => {
+ if (cur?.id) acc[cur.id] = cur.username || cur.id;
+ return acc;
+ }, {});
+ const memberMap = members.value.reduce>((acc, cur) => {
+ if (cur?.user_id) acc[cur.user_id] = cur.username || cur.user_id;
+ return acc;
+ }, {});
+ return userMap[row.uploaded_by] || memberMap[row.uploaded_by] || row.uploaded_by || "-";
+};
+
const download = (row: any) => {
const token = localStorage.getItem("ctms_token");
const url = token ? `/api/v1/attachments/${row.id}/download?token=${token}` : `/api/v1/attachments/${row.id}/download`;
@@ -92,7 +131,10 @@ const remove = async (row: any) => {
}
};
-onMounted(load);
+onMounted(async () => {
+ await Promise.all([loadUsers(), loadMembers()]);
+ load();
+});
diff --git a/frontend/src/views/admin/ProjectMembers.vue b/frontend/src/views/admin/ProjectMembers.vue
index 4c2f2dd1..a6c46e8f 100644
--- a/frontend/src/views/admin/ProjectMembers.vue
+++ b/frontend/src/views/admin/ProjectMembers.vue
@@ -16,21 +16,29 @@
{{ scope.row.role_in_study }}
-
+
- 启用
- 已禁用
+
+ 全局已禁用
+
+
+ {{ scope.row.is_active ? "启用" : "已禁用" }}
+
-
+
updateRole(scope.row.id, val)"
- :disabled="!scope.row.is_active"
+ :disabled="!scope.row.is_active || scope.row.effectiveStatus === 'DISABLED_GLOBAL'"
>
@@ -38,11 +46,13 @@
+ 该账号已在系统级被禁用,无法在任何项目中使用
删除
{{ scope.row.is_active ? "停用" : "启用" }}
@@ -151,9 +161,11 @@ const loadUsers = async () => {
const memberRows = computed(() =>
members.value.map((m) => {
const user = users.value.find((u) => u.id === m.user_id);
+ const effectiveStatus = user && user.is_active === false ? "DISABLED_GLOBAL" : m.is_active ? "ACTIVE" : "DISABLED";
return {
...m,
username: user?.username || m.user_id,
+ effectiveStatus,
};
})
);
@@ -388,4 +400,9 @@ onMounted(async () => {
color: #666;
margin-top: 4px;
}
+.hint {
+ color: #999;
+ margin: 0 8px;
+ font-size: 12px;
+}
diff --git a/frontend/src/views/admin/Projects.vue b/frontend/src/views/admin/Projects.vue
index 88d1a48c..39846d14 100644
--- a/frontend/src/views/admin/Projects.vue
+++ b/frontend/src/views/admin/Projects.vue
@@ -9,8 +9,16 @@
新建项目
-
-
+
+
+ {{ scope.row.code }}
+
+
+
+
+ {{ scope.row.name }}
+
+
@@ -84,6 +92,10 @@ const enterStudy = (row: Study) => {
router.push("/study/home");
};
+const goDetail = (row: Study) => {
+ router.push(`/projects/${row.id}`);
+};
+
const statusLabel = (status: string) =>
({
DRAFT: "草稿",
diff --git a/pg_data/base/16384/16392 b/pg_data/base/16384/16392
index 8f527b75..5161116d 100644
Binary files a/pg_data/base/16384/16392 and b/pg_data/base/16384/16392 differ
diff --git a/pg_data/base/16384/16399 b/pg_data/base/16384/16399
index 817d0f33..c1322570 100644
Binary files a/pg_data/base/16384/16399 and b/pg_data/base/16384/16399 differ
diff --git a/pg_data/base/16384/16476 b/pg_data/base/16384/16476
index 7dbe28d2..1479d99d 100644
Binary files a/pg_data/base/16384/16476 and b/pg_data/base/16384/16476 differ
diff --git a/pg_data/base/16384/16483 b/pg_data/base/16384/16483
index 19272f51..b62837ca 100644
Binary files a/pg_data/base/16384/16483 and b/pg_data/base/16384/16483 differ
diff --git a/pg_data/base/16384/16489 b/pg_data/base/16384/16489
index 4fb94b20..53f2ac37 100644
Binary files a/pg_data/base/16384/16489 and b/pg_data/base/16384/16489 differ
diff --git a/pg_data/base/16384/16508 b/pg_data/base/16384/16508
index 4fadbd34..421f1733 100644
Binary files a/pg_data/base/16384/16508 and b/pg_data/base/16384/16508 differ
diff --git a/pg_data/base/16384/16529 b/pg_data/base/16384/16529
index d8d188f6..fdfb23cc 100644
Binary files a/pg_data/base/16384/16529 and b/pg_data/base/16384/16529 differ
diff --git a/pg_data/base/16384/16531 b/pg_data/base/16384/16531
index 78d19ec9..34e927d0 100644
Binary files a/pg_data/base/16384/16531 and b/pg_data/base/16384/16531 differ
diff --git a/pg_data/global/pg_control b/pg_data/global/pg_control
index 7ae78d24..c6079c60 100644
Binary files a/pg_data/global/pg_control and b/pg_data/global/pg_control differ
diff --git a/pg_data/pg_wal/000000010000000000000001 b/pg_data/pg_wal/000000010000000000000001
index dc8b42cd..2be75570 100644
Binary files a/pg_data/pg_wal/000000010000000000000001 and b/pg_data/pg_wal/000000010000000000000001 differ
diff --git a/pg_data/pg_xact/0000 b/pg_data/pg_xact/0000
index f1325b6f..1ff89203 100644
Binary files a/pg_data/pg_xact/0000 and b/pg_data/pg_xact/0000 differ