<!-- 项目 -->
|
|
<template>
|
<div class="project-info" v-if="project">
|
<!-- 项目名称 -->
|
<div class="custom-card custom-input">
|
<span>{{ project?.name || "未知项目" }}</span>
|
<div v-if="showEdit" class="icon" @click="$emit('edit')">
|
<el-icon><Edit /></el-icon>
|
</div>
|
</div>
|
|
<!-- 项目方法信息 -->
|
<div class="custom-card custom-info">
|
<div
|
class="info-circle"
|
:style="{ backgroundColor: currentMethodConfig?.color || '#409EFF' }"
|
>
|
{{ currentMethodConfig?.icon || "📊" }}
|
</div>
|
<div class="info-cont">
|
<div class="title">
|
{{
|
currentMethodConfig?.title ||
|
project?.instance?.title ||
|
"深度学习项目"
|
}}
|
</div>
|
<div class="text">
|
{{
|
currentMethodConfig?.description ||
|
project?.instance?.description ||
|
"暂无描述信息"
|
}}
|
</div>
|
</div>
|
<div v-if="showMore" class="more" @click="$emit('more')">
|
<el-icon><More /></el-icon>
|
</div>
|
</div>
|
|
<!-- 项目详细信息 -->
|
<div v-if="showDetails" class="custom-card project-details">
|
<div class="custom-item">
|
<div class="label">项目文件:</div>
|
<div
|
class="text clickable-path"
|
@click="handleOpenFolder(project?.path)"
|
:title="'点击打开文件夹: ' + project?.path"
|
>
|
{{ project?.path }}
|
</div>
|
</div>
|
<div class="custom-item">
|
<div class="label">标签类别:</div>
|
<!-- 显示统计数据中的类别 -->
|
<div class="text">
|
{{
|
formatCategories(project?.statistics?.categories) || "暂无标签类别"
|
}}
|
</div>
|
</div>
|
<div class="custom-item">
|
<div class="label">标签实例/图像:</div>
|
<div class="text">
|
{{ project?.statistics?.totalAnnotations || 0 }}/{{
|
project?.statistics?.totalImages || 0
|
}}
|
</div>
|
</div>
|
<div class="custom-item">
|
<div class="label">创建时间/修改时间:</div>
|
<div class="text">
|
{{ formatDate(project?.createdAt) }}/{{
|
formatDate(project?.updatedAt)
|
}}
|
</div>
|
</div>
|
<div class="custom-item">
|
<div class="label">程序版本/文件版本:</div>
|
<div class="text">
|
{{ project?.version?.program }}/{{ project?.version?.file }}
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { onMounted } from "vue";
|
import { useMethodConfig } from "../../utils/config/methodConfig";
|
import { formatDate } from "../../utils/system/dateFormatter";
|
|
const props = defineProps({
|
project: {
|
type: Object,
|
default: () => null,
|
},
|
showEdit: {
|
type: Boolean,
|
default: false,
|
},
|
showMore: {
|
type: Boolean,
|
default: false,
|
},
|
showDetails: {
|
type: Boolean,
|
default: false,
|
},
|
});
|
|
const emit = defineEmits(["edit", "more"]);
|
|
// 使用公共方法配置工具
|
const { currentMethodConfig, loadMethods } = useMethodConfig(props.project);
|
|
// 格式化类别显示
|
const formatCategories = (categories) => {
|
if (!categories || !Array.isArray(categories) || categories.length === 0) {
|
return "暂无标签类别";
|
}
|
// 类别名称现在使用了序号格式(如"类别 00001"),已经是唯一的,直接显示即可
|
return categories.join(", ");
|
};
|
|
// 打开文件夹
|
const handleOpenFolder = async (folderPath) => {
|
if (!folderPath) {
|
alert("项目路径不存在");
|
return;
|
}
|
|
try {
|
if (window.electronAPI?.openFolder) {
|
const result = await window.electronAPI.openFolder(folderPath);
|
if (!result.success) {
|
alert("打开文件夹失败: " + result.error);
|
}
|
} else {
|
alert("系统API不可用");
|
}
|
} catch (error) {
|
console.error("打开文件夹失败:", error);
|
alert("打开文件夹失败: " + error.message);
|
}
|
};
|
|
// 初始化时加载方法配置
|
onMounted(() => {
|
loadMethods();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.project-info {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
|
.custom-card {
|
background: linear-gradient(
|
180deg,
|
rgba(255, 255, 255, 0.6) 0%,
|
rgba(255, 255, 255, 0.4) 100%
|
);
|
border-radius: 6px;
|
border: 2px solid #ffffff;
|
padding: 0;
|
}
|
|
.custom-input {
|
height: 50px;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 15px;
|
gap: 10px;
|
|
span {
|
font-size: 14px;
|
min-height: 20px;
|
color: #222;
|
font-weight: 600;
|
flex: 1;
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
|
.icon {
|
cursor: pointer;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
padding: 4px;
|
border-radius: 4px;
|
transition: background-color 0.2s;
|
|
&:hover {
|
background-color: rgba(0, 0, 0, 0.1);
|
}
|
}
|
}
|
|
.custom-info {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
height: 80px;
|
padding: 0 15px;
|
position: relative;
|
|
.info-circle {
|
width: 35px;
|
height: 35px;
|
border-radius: 50%;
|
background: #409eff;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 18px;
|
color: white;
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
flex-shrink: 0;
|
}
|
|
.info-cont {
|
flex: 1;
|
|
.title {
|
font-size: 14px;
|
color: #333;
|
margin-bottom: 4px;
|
font-weight: 500;
|
}
|
|
.text {
|
font-size: 12px;
|
color: #666;
|
line-height: 1.4;
|
}
|
}
|
|
.more {
|
cursor: pointer;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
padding: 4px;
|
border-radius: 4px;
|
transition: background-color 0.2s;
|
|
&:hover {
|
background-color: rgba(0, 0, 0, 0.1);
|
}
|
}
|
}
|
|
.project-details {
|
padding: 14px;
|
|
.custom-item {
|
margin-bottom: 15px;
|
display: flex;
|
flex-direction: column;
|
gap: 3px;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.label {
|
font-size: 14px;
|
color: #333;
|
font-weight: 500;
|
}
|
|
.text {
|
font-size: 12px;
|
color: #606266;
|
white-space: wrap;
|
word-break: break-all;
|
|
&.clickable-path {
|
cursor: pointer;
|
color: #409eff;
|
text-decoration: underline;
|
transition: color 0.2s;
|
|
&:hover {
|
color: #66b1ff;
|
}
|
}
|
}
|
}
|
}
|
}
|
</style>
|