项目详情页--初步更新

This commit is contained in:
Cheng Zhou
2025-12-18 19:36:47 +08:00
parent eed83cec5a
commit fb4950f8f7
17 changed files with 205 additions and 9 deletions
+118
View File
@@ -0,0 +1,118 @@
<template>
<div class="page">
<el-card class="mb-12">
<div class="header">
<div>
<h3>项目详情</h3>
<p class="sub" v-if="project">项目{{ project.code }} - {{ project.name }}</p>
</div>
<div class="actions">
<el-button type="primary" @click="enterProject" :disabled="!project">进入项目</el-button>
<el-button @click="goMembers" :disabled="!project">项目成员配置</el-button>
<el-button @click="goSites" :disabled="!project">中心管理</el-button>
</div>
</div>
</el-card>
<el-card class="mb-12">
<h4 class="section-title">项目基本信息</h4>
<el-descriptions v-if="project" :column="2" border>
<el-descriptions-item label="项目编号">{{ project.code }}</el-descriptions-item>
<el-descriptions-item label="项目名称">{{ project.name }}</el-descriptions-item>
<el-descriptions-item label="申办方">{{ project.sponsor || "—" }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ statusLabel(project.status) }}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ project.created_at || "—" }}</el-descriptions-item>
</el-descriptions>
<el-skeleton v-else :rows="4" animated />
</el-card>
<el-card>
<h4 class="section-title">项目通用文件</h4>
<AttachmentList
v-if="project"
:study-id="project.id"
entity-type="project"
:entity-id="project.id"
:show-uploader="true"
/>
<el-skeleton v-else :rows="3" animated />
</el-card>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { fetchStudyDetail } from "../../api/studies";
import type { Study } from "../../types/api";
import AttachmentList from "../../components/attachments/AttachmentList.vue";
import { useStudyStore } from "../../store/study";
const route = useRoute();
const router = useRouter();
const studyStore = useStudyStore();
const project = ref<Study | null>(null);
const loadProject = async () => {
try {
const { data } = await fetchStudyDetail(route.params.projectId as string);
project.value = data as Study;
} catch (e: any) {
ElMessage.error(e?.response?.data?.message || "项目加载失败");
}
};
const statusLabel = (status: string) =>
({
DRAFT: "草稿",
ACTIVE: "进行中",
CLOSED: "已关闭",
}[status] || status);
const enterProject = () => {
if (!project.value) return;
studyStore.setCurrentStudy({ ...project.value, role_in_study: project.value.role_in_study || "PM" } as Study);
router.push("/study/home");
};
const goMembers = () => {
if (!project.value) return;
router.push(`/admin/projects/${project.value.id}/members`);
};
const goSites = () => {
if (!project.value) return;
router.push(`/admin/projects/${project.value.id}/sites`);
};
onMounted(() => {
loadProject();
});
</script>
<style scoped>
.page {
padding: 16px;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
}
.actions {
display: flex;
gap: 8px;
}
.sub {
color: #666;
margin-top: 4px;
}
.section-title {
margin-bottom: 12px;
}
.mb-12 {
margin-bottom: 12px;
}
</style>