统一状态流转为前端状态机
This commit is contained in:
@@ -6,18 +6,28 @@
|
||||
<h3>AE(不良事件)</h3>
|
||||
<p>{{ ae.term }}</p>
|
||||
</div>
|
||||
<PermissionAction action="ae.close">
|
||||
<el-button :type="ae.status === 'CLOSED' ? 'primary' : 'danger'" size="small" @click="toggleClose">
|
||||
{{ ae.status === "CLOSED" ? "重新打开" : "关闭" }}
|
||||
</el-button>
|
||||
</PermissionAction>
|
||||
<div class="action-buttons">
|
||||
<template v-for="action in availableActions" :key="action.key">
|
||||
<PermissionAction action="ae.close">
|
||||
<el-button
|
||||
size="small"
|
||||
:type="action.danger ? 'danger' : 'primary'"
|
||||
@click="onAction(action)"
|
||||
>
|
||||
{{ action.label }}
|
||||
</el-button>
|
||||
</PermissionAction>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="受试者ID">{{ ae.subject_id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="严重性">{{ ae.seriousness }}</el-descriptions-item>
|
||||
<el-descriptions-item label="严重程度">{{ ae.severity }}</el-descriptions-item>
|
||||
<el-descriptions-item label="发生日期">{{ ae.onset_date }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ statusLabel(ae.status) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="stateColor(aeState)">{{ stateLabel(aeState) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="描述">{{ ae.description }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
@@ -52,6 +62,8 @@ import CommentList from "../components/CommentList.vue";
|
||||
import AttachmentList from "../components/attachments/AttachmentList.vue";
|
||||
import PermissionAction from "../components/PermissionAction.vue";
|
||||
import { usePermission } from "../utils/permission";
|
||||
import { aeMachine, getAvailableActions, getStateColor, getStateLabel } from "../state-machine";
|
||||
import type { ActionConfig } from "../state-machine";
|
||||
|
||||
const route = useRoute();
|
||||
const study = useStudyStore();
|
||||
@@ -61,7 +73,10 @@ const ae = ref<any | null>(null);
|
||||
const studyId = computed(() => study.currentStudy?.id || "");
|
||||
|
||||
const { can } = usePermission();
|
||||
const canClose = computed(() => can("ae.close"));
|
||||
const aeState = computed(() => (ae.value?.status as string) || "NEW");
|
||||
const availableActions = computed(() => getAvailableActions(aeMachine, aeState.value));
|
||||
const stateLabel = (v?: string | null) => getStateLabel(aeMachine, v);
|
||||
const stateColor = (v?: string | null) => getStateColor(aeMachine, v) || "info";
|
||||
|
||||
const enrichOverdue = (item: any) => {
|
||||
if (!item) return item;
|
||||
@@ -84,15 +99,14 @@ const load = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleClose = async () => {
|
||||
const onAction = async (action: ActionConfig) => {
|
||||
if (!study.currentStudy || !ae.value) return;
|
||||
const targetStatus = ae.value.status === "CLOSED" ? "FOLLOW_UP" : "CLOSED";
|
||||
await ElMessageBox.confirm(
|
||||
`确定将该 AE 状态设置为 ${targetStatus === "CLOSED" ? "已关闭" : "随访中"}?该操作不可撤销,请谨慎确认。`,
|
||||
"提示"
|
||||
);
|
||||
if (action.confirm) {
|
||||
const ok = await ElMessageBox.confirm(action.confirmText || "确认执行该操作?", "提示").catch(() => null);
|
||||
if (!ok) return;
|
||||
}
|
||||
try {
|
||||
const resp = await updateAe(study.currentStudy.id, ae.value.id, { status: targetStatus });
|
||||
const resp = await updateAe(study.currentStudy.id, ae.value.id, { status: action.to });
|
||||
ElMessage.success("状态已更新");
|
||||
ae.value = enrichOverdue(resp.data);
|
||||
await load();
|
||||
@@ -101,13 +115,6 @@ const toggleClose = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const statusLabel = (v: string) =>
|
||||
({
|
||||
NEW: "新增",
|
||||
FOLLOW_UP: "随访中",
|
||||
CLOSED: "已关闭",
|
||||
}[v] || v);
|
||||
|
||||
onMounted(async () => {
|
||||
if (!auth.user && auth.token) {
|
||||
await auth.fetchMe().catch(() => {});
|
||||
|
||||
Reference in New Issue
Block a user