全局中文化
This commit is contained in:
@@ -3,37 +3,37 @@
|
||||
<el-card>
|
||||
<div class="header">
|
||||
<div>
|
||||
<h3>项目成员配置(角色仅在当前项目内生效)</h3>
|
||||
<div class="sub" v-if="project">项目:{{ project.code }} - {{ project.name }}</div>
|
||||
<div class="sub">同一账号在不同项目可拥有不同角色,角色授权仅在本页进行</div>
|
||||
<h3>{{ TEXT.modules.adminProjectMembers.title }}</h3>
|
||||
<div class="sub" v-if="project">{{ TEXT.modules.adminProjectMembers.projectPrefix }}{{ project.code }} - {{ project.name }}</div>
|
||||
<div class="sub">{{ TEXT.modules.adminProjectMembers.subtitle }}</div>
|
||||
</div>
|
||||
<el-button type="primary" @click="openAdd">新增成员</el-button>
|
||||
<el-button type="primary" @click="openAdd">{{ TEXT.common.actions.add }}{{ TEXT.modules.adminProjectMembers.memberLabel }}</el-button>
|
||||
</div>
|
||||
<el-table :data="memberRows" v-loading="loading" stripe>
|
||||
<el-table-column prop="username" label="用户名" min-width="160" />
|
||||
<el-table-column prop="role_in_study" label="项目角色" width="140">
|
||||
<el-table-column prop="username" :label="TEXT.modules.adminProjectMembers.username" min-width="160" />
|
||||
<el-table-column prop="role_in_study" :label="TEXT.modules.adminProjectMembers.projectRole" width="140">
|
||||
<template #default="scope">
|
||||
<el-tag>{{ scope.row.role_in_study }}</el-tag>
|
||||
<el-tag>{{ displayEnum(TEXT.enums.userRole, scope.row.role_in_study) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="160">
|
||||
<el-table-column :label="TEXT.common.fields.status" width="160">
|
||||
<template #default="scope">
|
||||
<el-tooltip
|
||||
v-if="scope.row.effectiveStatus === 'DISABLED_GLOBAL'"
|
||||
content="请前往【账号治理】启用该账号"
|
||||
:content="TEXT.modules.adminProjectMembers.disabledGlobalHint"
|
||||
placement="top"
|
||||
>
|
||||
<el-tag type="danger">全局已禁用</el-tag>
|
||||
<el-tag type="danger">{{ TEXT.modules.adminProjectMembers.disabledGlobal }}</el-tag>
|
||||
</el-tooltip>
|
||||
<el-tag v-else :type="scope.row.is_active ? 'success' : 'danger'">
|
||||
{{ scope.row.is_active ? "启用" : "已禁用" }}
|
||||
{{ scope.row.is_active ? TEXT.common.actions.enable : TEXT.modules.adminProjectMembers.disabled }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="added_at" label="加入时间" width="200">
|
||||
<el-table-column prop="added_at" :label="TEXT.modules.adminProjectMembers.addedAt" width="200">
|
||||
<template #default="scope">{{ displayDateTime(scope.row.added_at) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="360" fixed="right">
|
||||
<el-table-column :label="TEXT.common.labels.actions" width="360" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.role_in_study"
|
||||
@@ -42,14 +42,14 @@
|
||||
@change="(val) => updateRole(scope.row.id, val)"
|
||||
:disabled="!scope.row.is_active || scope.row.effectiveStatus === 'DISABLED_GLOBAL'"
|
||||
>
|
||||
<el-option label="PM" value="PM" />
|
||||
<el-option label="CRA" value="CRA" />
|
||||
<el-option label="PV" value="PV" />
|
||||
<el-option label="IMP" value="IMP" />
|
||||
<el-option label="ADMIN" value="ADMIN" />
|
||||
<el-option :label="TEXT.enums.userRole.PM" value="PM" />
|
||||
<el-option :label="TEXT.enums.userRole.CRA" value="CRA" />
|
||||
<el-option :label="TEXT.enums.userRole.PV" value="PV" />
|
||||
<el-option :label="TEXT.enums.userRole.IMP" value="IMP" />
|
||||
<el-option :label="TEXT.enums.userRole.ADMIN" value="ADMIN" />
|
||||
</el-select>
|
||||
<span v-if="scope.row.effectiveStatus === 'DISABLED_GLOBAL'" class="hint">该账号已在系统级被禁用,无法在任何项目中使用</span>
|
||||
<el-button link type="danger" size="small" @click="onDelete(scope.row)">删除</el-button>
|
||||
<span v-if="scope.row.effectiveStatus === 'DISABLED_GLOBAL'" class="hint">{{ TEXT.modules.adminProjectMembers.disabledGlobalDesc }}</span>
|
||||
<el-button link type="danger" size="small" @click="onDelete(scope.row)">{{ TEXT.common.actions.delete }}</el-button>
|
||||
<el-button
|
||||
link
|
||||
:type="scope.row.is_active ? 'danger' : 'primary'"
|
||||
@@ -57,17 +57,17 @@
|
||||
:disabled="scope.row.effectiveStatus === 'DISABLED_GLOBAL'"
|
||||
@click="toggleActive(scope.row)"
|
||||
>
|
||||
{{ scope.row.is_active ? "停用" : "启用" }}
|
||||
{{ scope.row.is_active ? TEXT.common.actions.disable : TEXT.common.actions.enable }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog title="新增成员" width="520px" v-model="addVisible" :close-on-click-modal="false">
|
||||
<el-dialog :title="TEXT.modules.adminProjectMembers.newTitle" width="520px" v-model="addVisible" :close-on-click-modal="false">
|
||||
<el-form :model="newMember" label-width="120px" ref="addFormRef" :rules="addRules">
|
||||
<el-form-item label="用户" prop="user_id">
|
||||
<el-select v-model="newMember.user_id" filterable placeholder="请选择用户">
|
||||
<el-form-item :label="TEXT.modules.adminProjectMembers.user" prop="user_id">
|
||||
<el-select v-model="newMember.user_id" filterable :placeholder="TEXT.modules.adminProjectMembers.userPlaceholder">
|
||||
<el-option
|
||||
v-for="user in availableUsers"
|
||||
:key="user.id"
|
||||
@@ -77,19 +77,19 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色" prop="role_in_study">
|
||||
<el-select v-model="newMember.role_in_study" placeholder="请选择角色">
|
||||
<el-option label="PM" value="PM" />
|
||||
<el-option label="CRA" value="CRA" />
|
||||
<el-option label="PV" value="PV" />
|
||||
<el-option label="IMP" value="IMP" />
|
||||
<el-option label="ADMIN" value="ADMIN" />
|
||||
<el-form-item :label="TEXT.modules.adminProjectMembers.projectRole" prop="role_in_study">
|
||||
<el-select v-model="newMember.role_in_study" :placeholder="TEXT.modules.adminProjectMembers.rolePlaceholder">
|
||||
<el-option :label="TEXT.enums.userRole.PM" value="PM" />
|
||||
<el-option :label="TEXT.enums.userRole.CRA" value="CRA" />
|
||||
<el-option :label="TEXT.enums.userRole.PV" value="PV" />
|
||||
<el-option :label="TEXT.enums.userRole.IMP" value="IMP" />
|
||||
<el-option :label="TEXT.enums.userRole.ADMIN" value="ADMIN" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="addVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="adding" @click="submitAdd">保存</el-button>
|
||||
<el-button @click="addVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
|
||||
<el-button type="primary" :loading="adding" @click="submitAdd">{{ TEXT.common.actions.save }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -106,7 +106,8 @@ import type { Study, StudyMember, UserInfo } from "../../types/api";
|
||||
import { useAuthStore } from "../../store/auth";
|
||||
import { evaluateAction } from "../../guards/actionGuard";
|
||||
import { logAudit } from "../../audit";
|
||||
import { displayDateTime } from "../../utils/display";
|
||||
import { displayDateTime, displayEnum } from "../../utils/display";
|
||||
import { TEXT, requiredMessage } from "../../locales";
|
||||
|
||||
const route = useRoute();
|
||||
const projectId = computed(() => route.params.projectId as string);
|
||||
@@ -125,8 +126,8 @@ const newMember = reactive({
|
||||
});
|
||||
|
||||
const addRules = reactive<FormRules>({
|
||||
user_id: [{ required: true, message: "请选择用户", trigger: "change" }],
|
||||
role_in_study: [{ required: true, message: "请选择角色", trigger: "change" }],
|
||||
user_id: [{ required: true, message: requiredMessage(TEXT.modules.adminProjectMembers.user), trigger: "change" }],
|
||||
role_in_study: [{ required: true, message: requiredMessage(TEXT.modules.adminProjectMembers.projectRole), trigger: "change" }],
|
||||
});
|
||||
|
||||
const loadProject = async () => {
|
||||
@@ -146,7 +147,7 @@ const loadMembers = async () => {
|
||||
const { data } = await listMembers(projectId.value, { limit: 500 });
|
||||
members.value = Array.isArray(data) ? data : data.items || [];
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "成员列表加载失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.modules.adminProjectMembers.loadFailed);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
@@ -187,7 +188,7 @@ const submitAdd = async () => {
|
||||
target: { projectId: projectId.value },
|
||||
});
|
||||
if (!decision.allowed) {
|
||||
ElMessage.warning(decision.reason || "无权限执行该操作");
|
||||
ElMessage.warning(decision.reason || TEXT.common.messages.noPermission);
|
||||
logAudit(decision.auditType, {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -200,7 +201,7 @@ const submitAdd = async () => {
|
||||
adding.value = true;
|
||||
try {
|
||||
await addMember(projectId.value, newMember);
|
||||
ElMessage.success("成员已添加");
|
||||
ElMessage.success(TEXT.modules.adminProjectMembers.addSuccess);
|
||||
addVisible.value = false;
|
||||
loadMembers();
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
@@ -210,7 +211,7 @@ const submitAdd = async () => {
|
||||
severity: "normal",
|
||||
});
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "添加失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.modules.adminProjectMembers.addFailed);
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -231,7 +232,7 @@ const updateRole = async (memberId: string, role: string) => {
|
||||
target: { projectId: projectId.value, memberId },
|
||||
});
|
||||
if (!decision.allowed) {
|
||||
ElMessage.warning(decision.reason || "无权限执行该操作");
|
||||
ElMessage.warning(decision.reason || TEXT.common.messages.noPermission);
|
||||
logAudit(decision.auditType, {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -242,7 +243,7 @@ const updateRole = async (memberId: string, role: string) => {
|
||||
}
|
||||
try {
|
||||
await updateMember(projectId.value, memberId, { role_in_study: role });
|
||||
ElMessage.success("角色已更新");
|
||||
ElMessage.success(TEXT.modules.adminProjectMembers.roleUpdated);
|
||||
loadMembers();
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
@@ -251,7 +252,7 @@ const updateRole = async (memberId: string, role: string) => {
|
||||
severity: "normal",
|
||||
});
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "更新失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.common.messages.updateFailed);
|
||||
loadMembers();
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
@@ -271,7 +272,7 @@ const toggleActive = async (row: StudyMember) => {
|
||||
target: { projectId: projectId.value, memberId: row.id },
|
||||
});
|
||||
if (!decision.allowed) {
|
||||
ElMessage.warning(decision.reason || "无权限执行该操作");
|
||||
ElMessage.warning(decision.reason || TEXT.common.messages.noPermission);
|
||||
logAudit(decision.auditType, {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -281,14 +282,14 @@ const toggleActive = async (row: StudyMember) => {
|
||||
return;
|
||||
}
|
||||
if (row.is_active) {
|
||||
const ok = await ElMessageBox.confirm("该操作将影响项目成员,请确认是否继续", "停用成员", {
|
||||
const ok = await ElMessageBox.confirm(TEXT.modules.adminProjectMembers.disableConfirm, TEXT.modules.adminProjectMembers.disableTitle, {
|
||||
type: "warning",
|
||||
confirmButtonText: "确认",
|
||||
confirmButtonText: TEXT.common.actions.confirm,
|
||||
}).catch(() => null);
|
||||
if (!ok) return;
|
||||
try {
|
||||
await updateMember(projectId.value, row.id, { is_active: false });
|
||||
ElMessage.success("成员已停用");
|
||||
ElMessage.success(TEXT.modules.adminProjectMembers.disableSuccess);
|
||||
loadMembers();
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
@@ -298,7 +299,7 @@ const toggleActive = async (row: StudyMember) => {
|
||||
severity: "normal",
|
||||
});
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "操作失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.common.messages.actionFailed);
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -311,7 +312,7 @@ const toggleActive = async (row: StudyMember) => {
|
||||
} else {
|
||||
try {
|
||||
await updateMember(projectId.value, row.id, { is_active: true });
|
||||
ElMessage.success("成员已启用");
|
||||
ElMessage.success(TEXT.modules.adminProjectMembers.enableSuccess);
|
||||
loadMembers();
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
@@ -321,7 +322,7 @@ const toggleActive = async (row: StudyMember) => {
|
||||
severity: "normal",
|
||||
});
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "操作失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.common.messages.actionFailed);
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -342,7 +343,7 @@ const onDelete = async (row: StudyMember) => {
|
||||
target: { projectId: projectId.value, memberId: row.id },
|
||||
});
|
||||
if (!decision.allowed) {
|
||||
ElMessage.warning(decision.reason || "无权限执行该操作");
|
||||
ElMessage.warning(decision.reason || TEXT.common.messages.noPermission);
|
||||
logAudit(decision.auditType, {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -351,16 +352,16 @@ const onDelete = async (row: StudyMember) => {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const ok = await ElMessageBox.confirm("确认将该账号从本项目移除?账号本身不会被删除。", "删除成员", {
|
||||
const ok = await ElMessageBox.confirm(TEXT.modules.adminProjectMembers.removeConfirm, TEXT.modules.adminProjectMembers.removeTitle, {
|
||||
type: "warning",
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "取消",
|
||||
confirmButtonText: TEXT.common.actions.confirm,
|
||||
cancelButtonText: TEXT.common.actions.cancel,
|
||||
}).catch(() => null);
|
||||
if (!ok) return;
|
||||
try {
|
||||
await removeMember(projectId.value, row.id);
|
||||
members.value = members.value.filter((m) => m.id !== row.id);
|
||||
ElMessage.success("已从项目移除");
|
||||
ElMessage.success(TEXT.modules.adminProjectMembers.removeSuccess);
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
@@ -369,7 +370,7 @@ const onDelete = async (row: StudyMember) => {
|
||||
severity: "normal",
|
||||
});
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e?.response?.data?.message || "删除失败");
|
||||
ElMessage.error(e?.response?.data?.message || TEXT.common.messages.deleteFailed);
|
||||
logAudit("PROJECT_MEMBER_UPDATED", {
|
||||
targetId: projectId.value,
|
||||
targetName: project.value?.name,
|
||||
|
||||
Reference in New Issue
Block a user