审计日志并入系统管理、规范项目成员获取逻辑

This commit is contained in:
Cheng Zhou
2025-12-26 14:57:57 +08:00
parent 7c9befc3c9
commit 71db309e12
17 changed files with 94 additions and 116 deletions
+18 -6
View File
@@ -117,7 +117,7 @@ import {
setFaqStatus,
} from "../api/faqs";
import { listMembers } from "../api/members";
import { displayDateTime, displayUser } from "../utils/display";
import { displayDateTime, displayUser, getMemberDisplayName, getUserDisplayName } from "../utils/display";
import { useAuthStore } from "../store/auth";
import { usePermission } from "../utils/permission";
import FaqItemForm from "../components/FaqItemForm.vue";
@@ -185,16 +185,28 @@ const bestReply = computed(() => {
const memberMap = computed(() =>
members.value.reduce<Record<string, string>>((acc, cur) => {
const username = cur?.user?.display_name || cur?.user?.username || cur?.username;
if (cur?.user_id) acc[cur.user_id] = username || cur.user_id;
const username = getMemberDisplayName(cur);
if (cur?.user_id && username) acc[cur.user_id] = username;
return acc;
}, {})
);
const userMap = computed(() => {
if (!auth.user?.id) return {};
const name = auth.user.display_name || auth.user.username || auth.user.id;
return { [auth.user.id]: name };
const map: Record<string, string> = {};
if (auth.user?.id) {
const name = getUserDisplayName(auth.user) || auth.user.id;
map[auth.user.id] = name;
}
const push = (id?: string | null, name?: string | null) => {
if (!id || !name) return;
map[id] = name;
};
push(item.value?.created_by, item.value?.created_by_name || item.value?.created_by_display_name || item.value?.created_by_email);
replies.value.forEach((r) => {
push(r?.created_by, r?.created_by_name || r?.created_by_display_name || r?.created_by_email);
push(r?.quote?.created_by, r?.quote?.created_by_name || r?.quote?.created_by_display_name || r?.quote?.created_by_email);
});
return map;
});
const categoryName = computed(() => {
+6 -6
View File
@@ -79,7 +79,7 @@ import {
getMilestoneStatusLabel,
getMilestoneTypeLabel,
} from "../dictionaries/milestone.dict";
import { displayDate, displayUser } from "../utils/display";
import { displayDate, displayUser, getMemberDisplayName, getUserDisplayName } from "../utils/display";
const route = useRoute();
const study = useStudyStore();
@@ -134,17 +134,17 @@ const siteName = (row: any) => {
const ownerName = (ownerId: string) => {
const memberMap = members.value.reduce<Record<string, string>>((acc, cur) => {
const username = cur?.user?.display_name || cur?.user?.full_name || cur?.user?.username || cur?.username;
if (cur?.user_id) acc[cur.user_id] = username || cur.user_id;
if (cur?.id) acc[cur.id] = username || cur.id;
const username = getMemberDisplayName(cur);
if (cur?.user_id && username) acc[cur.user_id] = username;
if (cur?.id && username) acc[cur.id] = username;
return acc;
}, {});
const owner = milestone.value?.owner;
const nameFromObject = owner?.display_name || owner?.full_name || owner?.username;
const nameFromObject = getUserDisplayName(owner);
if (nameFromObject) return nameFromObject;
return memberMap[ownerId] || ownerId || "—";
return memberMap[ownerId] || "—";
};
onMounted(async () => {
+3 -9
View File
@@ -83,7 +83,7 @@ import {
getMilestoneStatusLabel,
getMilestoneTypeLabel,
} from "../dictionaries/milestone.dict";
import { displayDate, displayUser } from "../utils/display";
import { displayDate, displayUser, getMemberDisplayName } from "../utils/display";
const study = useStudyStore();
const router = useRouter();
@@ -150,14 +150,8 @@ const statusColor = (v: string) => getMilestoneStatusColor(v);
const memberMap = computed(() =>
members.value.reduce<Record<string, string>>((acc, cur) => {
const username =
cur?.user?.full_name ||
cur?.user?.display_name ||
cur?.user?.username ||
cur?.user?.email ||
cur?.username ||
cur?.email;
if (cur?.user_id) acc[cur.user_id] = username || cur.user_id;
const username = getMemberDisplayName(cur);
if (cur?.user_id && username) acc[cur.user_id] = username;
return acc;
}, {})
);
+4 -4
View File
@@ -77,7 +77,7 @@ import { useAuthStore } from "../store/auth";
import VerificationTable from "../components/VerificationTable.vue";
import SiteSelect from "../components/selectors/SiteSelect.vue";
import SubjectSelect from "../components/selectors/SubjectSelect.vue";
import { displayDate } from "../utils/display";
import { displayDate, getMemberDisplayName } from "../utils/display";
const study = useStudyStore();
const auth = useAuthStore();
@@ -188,9 +188,9 @@ const subjectMap = computed(() =>
const verifierMap = computed(() =>
members.value.reduce<Record<string, string>>((acc, cur) => {
const username = cur?.user?.display_name || cur?.user?.full_name || cur?.user?.username || cur?.username;
if (cur?.user_id) acc[cur.user_id] = username || cur.user_id;
if (cur?.id) acc[cur.id] = username || cur.id;
const username = getMemberDisplayName(cur);
if (cur?.user_id && username) acc[cur.user_id] = username;
if (cur?.id && username) acc[cur.id] = username;
return acc;
}, {})
);
+3 -4
View File
@@ -151,13 +151,12 @@ const eventTypeOptions = Object.entries(auditDict).map(([value, cfg]) => ({
}));
const userOptions = computed(() => users.value.map((u: any) => ({ label: u.username, value: u.id })));
const isAdmin = computed(() => auth.user?.role === "ADMIN");
const canProjectExport = computed(() => !!study.currentStudy && (auth.user?.role === "ADMIN" || auth.user?.role === "PM" || study.currentStudyRole === "PM"));
const canProjectExport = computed(() => !!study.currentStudy && auth.user?.role === "ADMIN");
const ensureAccess = () => {
const role = auth.user?.role;
const studyRole = study.currentStudyRole;
if (!(role === "ADMIN" || role === "PM" || studyRole === "PM")) {
router.replace("/study/home");
if (role !== "ADMIN") {
router.replace("/admin/users");
}
};