|
@@ -1,7 +1,345 @@
|
|
<template>
|
|
<template>
|
|
- <div>
|
|
|
|
- this is view page
|
|
|
|
|
|
+ <div v-if="showMissions" class="mission-container">
|
|
|
|
+ <el-row :gutter="20" class="grid-container">
|
|
|
|
+ <el-col v-for="mission in currentPageData" :key="mission.id" :xs="24" :sm="12" :md="8" :lg="6">
|
|
|
|
+ <el-tooltip :content="mission.description" placement="bottom" popper-class="mission-tooltip">
|
|
|
|
+ <el-card class="mission-card" @click="handleCardClick(mission.id)">
|
|
|
|
+ <!-- 状态指示灯 -->
|
|
|
|
+ <div class="status-indicator">
|
|
|
|
+ <el-tooltip effect="dark" :content="statusText[mission.status]" placement="top">
|
|
|
|
+ <div class="status-light" :style="{ backgroundColor: statusColor[mission.status] }" />
|
|
|
|
+ </el-tooltip>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="card-content">
|
|
|
|
+ <h3 class="title">{{ mission.name }}</h3>
|
|
|
|
+ <div class="meta">
|
|
|
|
+ <el-icon>
|
|
|
|
+ <Calendar />
|
|
|
|
+ </el-icon>
|
|
|
|
+ <span>{{ formatTime(mission.createTime) }}</span>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="stats">
|
|
|
|
+ <!-- 节点行 -->
|
|
|
|
+ <div class="stat-item node-row">
|
|
|
|
+ <div class="label-box">
|
|
|
|
+ <span class="label">节点</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="node-stats">
|
|
|
|
+ <span class="node-count">S:{{ mission.nodesInfo.S }}</span>
|
|
|
|
+ <span class="node-count">D:{{ mission.nodesInfo.D }}</span>
|
|
|
|
+ <span class="node-count">I:{{ mission.nodesInfo.I }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- 边行 -->
|
|
|
|
+ <div class="stat-item edge-row">
|
|
|
|
+ <div class="label-box">
|
|
|
|
+ <span class="label">边</span>
|
|
|
|
+ </div>
|
|
|
|
+ <span class="edge-count">{{ mission.edgesInfo.num }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-card>
|
|
|
|
+ </el-tooltip>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ <!-- 分页控件 -->
|
|
|
|
+ <el-pagination background layout="total, sizes, prev, pager, next" :page-sizes="[8, 16, 24]"
|
|
|
|
+ :current-page="pagination.currentPage" :page-size="pagination.pageSize" :total="pagination.total"
|
|
|
|
+ @size-change="handleSizeChange" @current-change="handleCurrentChange" class="pagination" />
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else>
|
|
|
|
+ <router-view></router-view>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
+
|
|
<script setup>
|
|
<script setup>
|
|
|
|
+import { ref, reactive, computed, onMounted, inject } from 'vue'
|
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
|
+import { Calendar, User, Connection } from '@element-plus/icons-vue'
|
|
|
|
+import { postData, getData } from '@/api/axios'
|
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
|
+
|
|
|
|
+// 保存选中的mission
|
|
|
|
+const useAnalyzeInfo = inject('analyzeInfo')
|
|
|
|
+// 任务数据
|
|
|
|
+const missions = ref([])
|
|
|
|
+// 任务状态对应颜色
|
|
|
|
+const statusColor = {
|
|
|
|
+ 'init': '#ff4d4f', // 未开始或暂停、停止
|
|
|
|
+ 'pause': '#ff4d4f', // 未开始或暂停、停止
|
|
|
|
+ 'calculating': '#faad14', // 计算中
|
|
|
|
+ 'done': '#52c41a' // 已完成
|
|
|
|
+}
|
|
|
|
+// 任务状态提示语句
|
|
|
|
+const statusText = {
|
|
|
|
+ 'init': '尚未执行计算',
|
|
|
|
+ 'pause': '计算暂停中',
|
|
|
|
+ 'calculating': '计算进行中',
|
|
|
|
+ 'done': '计算已完成',
|
|
|
|
+}
|
|
|
|
+// 用于区分显示missions或plan
|
|
|
|
+const showMissions = ref(false)
|
|
|
|
+
|
|
|
|
+// 分页配置
|
|
|
|
+const pagination = ref({
|
|
|
|
+ currentPage: 1,
|
|
|
|
+ pageSize: 8,
|
|
|
|
+ total: missions.value.length
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 当前页数据计算
|
|
|
|
+const currentPageData = computed(() => {
|
|
|
|
+ const start = (pagination.value.currentPage - 1) * pagination.value.pageSize
|
|
|
|
+ return missions.value.slice(start, start + pagination.value.pageSize)
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 分页事件处理
|
|
|
|
+const handleSizeChange = (size) => {
|
|
|
|
+ pagination.pageSize = size
|
|
|
|
+ pagination.value.currentPage = 1
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const handleCurrentChange = (page) => {
|
|
|
|
+ pagination.value.currentPage = page
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 时间格式化
|
|
|
|
+const formatTime = (isoString) => {
|
|
|
|
+ return new Date(isoString).toLocaleDateString('zh-CN', {
|
|
|
|
+ year: 'numeric',
|
|
|
|
+ month: '2-digit',
|
|
|
|
+ day: '2-digit'
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 路由跳转
|
|
|
|
+const router = useRouter()
|
|
|
|
+const handleCardClick = (id) => {
|
|
|
|
+ preparePlan(missions.value.find(mission => mission.id == id))
|
|
|
|
+ // 切换显示plan的routeview
|
|
|
|
+ showMissions.value = false
|
|
|
|
+ router.push(`/dashboard/view/plan`)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const preparePlan = (mission) => {
|
|
|
|
+ console.log("选中的Mission:")
|
|
|
|
+ console.log(mission)
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.nodeFile.amount = mission.nodesInfo.S + mission.nodesInfo.D + mission.nodesInfo.I
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.nodeFile.sNode = mission.nodesInfo.S
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.nodeFile.dNode = mission.nodesInfo.D
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.nodeFile.iNode = mission.nodesInfo.I
|
|
|
|
+
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.edgeFile.amount = mission.edgesInfo.num
|
|
|
|
+ useAnalyzeInfo.analyzeInfo.value.mission = {
|
|
|
|
+ id: mission.id,
|
|
|
|
+ name: mission.name,
|
|
|
|
+ createTime: mission.createTime,
|
|
|
|
+ status: mission.status,
|
|
|
|
+ }
|
|
|
|
+ console.log(useAnalyzeInfo.analyzeInfo.value)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//加载数据
|
|
|
|
+onMounted(async () => {
|
|
|
|
+ // 获取missions
|
|
|
|
+ missions.value = []
|
|
|
|
+ // 显示missions
|
|
|
|
+ showMissions.value = true
|
|
|
|
+ try {
|
|
|
|
+ const response = await getData('/missions/')
|
|
|
|
+ response.data.forEach(mission => {
|
|
|
|
+ missions.value.push({
|
|
|
|
+ id: mission.id,
|
|
|
|
+ name: mission.name,
|
|
|
|
+ createTime: mission.createTime,
|
|
|
|
+ nodesInfo: mission.nodesInfo,
|
|
|
|
+ edgesInfo: mission.edgesInfo,
|
|
|
|
+ status: mission.status,
|
|
|
|
+ description: "This is description",
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ pagination.value.total = missions.value.length
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.log(error)
|
|
|
|
+ ElMessage.error("获取任务列表错误")
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
</script>
|
|
</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.mission-container {
|
|
|
|
+ padding: 20px;
|
|
|
|
+ max-width: 1400px;
|
|
|
|
+ margin: 0 auto;
|
|
|
|
+ background: #f8fafc;
|
|
|
|
+
|
|
|
|
+ .grid-container {
|
|
|
|
+ min-height: 60vh;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .mission-card {
|
|
|
|
+
|
|
|
|
+ position: relative;
|
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
|
+ border-radius: 12px;
|
|
|
|
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
|
|
|
|
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
+ background: white;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ transform: translateY(-3px);
|
|
|
|
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.08);
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .label-box {
|
|
|
|
+ display: inline-flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ width: 48px;
|
|
|
|
+ height: 24px;
|
|
|
|
+ background: #f1f5f9;
|
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
|
+ border-radius: 4px;
|
|
|
|
+ margin-right: 8px;
|
|
|
|
+
|
|
|
|
+ .label {
|
|
|
|
+ color: #475569;
|
|
|
|
+ font-size: 0.85rem;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ transform: scale(0.9);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .status-indicator {
|
|
|
|
+ position: absolute;
|
|
|
|
+ right: 16px;
|
|
|
|
+ top: 16px;
|
|
|
|
+ z-index: 2;
|
|
|
|
+
|
|
|
|
+ .status-light {
|
|
|
|
+ width: 12px;
|
|
|
|
+ height: 12px;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
|
+ position: relative;
|
|
|
|
+
|
|
|
|
+ &::after {
|
|
|
|
+ content: '';
|
|
|
|
+ position: absolute;
|
|
|
|
+ inset: 0;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ background: inherit;
|
|
|
|
+ filter: brightness(1.2);
|
|
|
|
+ opacity: 0.3;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .card-content {
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ font-family: "Microsoft YaHei", system-ui;
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ color: #1e293b;
|
|
|
|
+ margin: 0 0 8px; // 减少上下间距
|
|
|
|
+ font-size: 1.15rem;
|
|
|
|
+ line-height: 1.3;
|
|
|
|
+ position: relative;
|
|
|
|
+ padding-left: 24px;
|
|
|
|
+
|
|
|
|
+ &::before {
|
|
|
|
+ content: '📌';
|
|
|
|
+ position: absolute;
|
|
|
|
+ left: -4px;
|
|
|
|
+ top: -2px;
|
|
|
|
+ font-size: 0.9em;
|
|
|
|
+ opacity: 0.8;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .meta {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
+ color: #64748b;
|
|
|
|
+ font-size: 0.9rem;
|
|
|
|
+
|
|
|
|
+ .el-icon {
|
|
|
|
+ margin-right: 8px;
|
|
|
|
+ font-size: 1.1em;
|
|
|
|
+ color: #94a3b8;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .stats {
|
|
|
|
+ .stat-item {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+
|
|
|
|
+ &.node-row {
|
|
|
|
+ .node-stats {
|
|
|
|
+ display: flex;
|
|
|
|
+ gap: 12px;
|
|
|
|
+ align-items: center;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &.edge-row {
|
|
|
|
+ .edge-count {
|
|
|
|
+ color: #334155;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .pagination {
|
|
|
|
+ margin-top: 30px;
|
|
|
|
+ justify-content: center;
|
|
|
|
+
|
|
|
|
+ ::v-deep(.el-pagination__total) {
|
|
|
|
+ color: #64748b;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @media (max-width: 768px) {
|
|
|
|
+ .mission-card {
|
|
|
|
+ margin: 8px 0;
|
|
|
|
+
|
|
|
|
+ .card-content {
|
|
|
|
+ padding: 12px;
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ font-size: 1.1rem;
|
|
|
|
+ padding-left: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .node-stats {
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ gap: 4px !important;
|
|
|
|
+
|
|
|
|
+ span::after {
|
|
|
|
+ display: none !important;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|