dev 1 Minggu lalu
induk
melakukan
370cab5ee0
64 mengubah file dengan 400 tambahan dan 17 penghapusan
  1. TEMPAT SAMPAH
      backend/api/__pycache__/__init__.cpython-310.pyc
  2. TEMPAT SAMPAH
      backend/api/__pycache__/admin.cpython-310.pyc
  3. TEMPAT SAMPAH
      backend/api/__pycache__/api_alert.cpython-310.pyc
  4. TEMPAT SAMPAH
      backend/api/__pycache__/api_calculate.cpython-310.pyc
  5. TEMPAT SAMPAH
      backend/api/__pycache__/api_graph.cpython-310.pyc
  6. TEMPAT SAMPAH
      backend/api/__pycache__/api_prepare.cpython-310.pyc
  7. TEMPAT SAMPAH
      backend/api/__pycache__/api_rawDataTrans.cpython-310.pyc
  8. TEMPAT SAMPAH
      backend/api/__pycache__/api_results.cpython-310.pyc
  9. TEMPAT SAMPAH
      backend/api/__pycache__/api_system.cpython-310.pyc
  10. TEMPAT SAMPAH
      backend/api/__pycache__/api_user.cpython-310.pyc
  11. TEMPAT SAMPAH
      backend/api/__pycache__/apps.cpython-310.pyc
  12. TEMPAT SAMPAH
      backend/api/__pycache__/scheduler.cpython-310.pyc
  13. TEMPAT SAMPAH
      backend/api/__pycache__/serializers.cpython-310.pyc
  14. TEMPAT SAMPAH
      backend/api/__pycache__/tokenAuthentication.cpython-310.pyc
  15. TEMPAT SAMPAH
      backend/api/__pycache__/urls.cpython-310.pyc
  16. TEMPAT SAMPAH
      backend/api/__pycache__/utils.cpython-310.pyc
  17. 27 1
      backend/api/api_prepare.py
  18. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0001_initial.cpython-310.pyc
  19. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0002_alter_user_options_user_last_login.cpython-310.pyc
  20. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0003_view_file.cpython-310.pyc
  21. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0004_rename_display_name_user_displayname_file_usage.cpython-310.pyc
  22. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0005_file_associate_file_content.cpython-310.pyc
  23. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0006_alter_file_associate.cpython-310.pyc
  24. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0007_fileinfo.cpython-310.pyc
  25. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0008_mission_result.cpython-310.pyc
  26. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0009_alter_fileinfo_file_alter_mission_name.cpython-310.pyc
  27. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0010_algorithm_plan.cpython-310.pyc
  28. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0011_result_plan_result_state.cpython-310.pyc
  29. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0012_result_edgefile_result_nodefile_alter_result_plan.cpython-310.pyc
  30. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0013_remove_result_state_alter_file_usage.cpython-310.pyc
  31. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0014_result_progress.cpython-310.pyc
  32. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0015_mission_state.cpython-310.pyc
  33. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0016_alter_result_edgefile_alter_result_nodefile.cpython-310.pyc
  34. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0017_graph_graphtoken.cpython-310.pyc
  35. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0018_rename_edgemap_graph_edges_and_more.cpython-310.pyc
  36. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0019_alter_graph_user.cpython-310.pyc
  37. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0020_alert_systemperformance.cpython-310.pyc
  38. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/0021_rename_indicator_alert_metric.cpython-310.pyc
  39. TEMPAT SAMPAH
      backend/api/migrations/__pycache__/__init__.cpython-310.pyc
  40. TEMPAT SAMPAH
      backend/api/models/__pycache__/__init__.cpython-310.pyc
  41. TEMPAT SAMPAH
      backend/api/models/__pycache__/alert.cpython-310.pyc
  42. TEMPAT SAMPAH
      backend/api/models/__pycache__/algorithm.cpython-310.pyc
  43. TEMPAT SAMPAH
      backend/api/models/__pycache__/file.cpython-310.pyc
  44. TEMPAT SAMPAH
      backend/api/models/__pycache__/graph.cpython-310.pyc
  45. TEMPAT SAMPAH
      backend/api/models/__pycache__/mission.cpython-310.pyc
  46. TEMPAT SAMPAH
      backend/api/models/__pycache__/plan.cpython-310.pyc
  47. TEMPAT SAMPAH
      backend/api/models/__pycache__/result.cpython-310.pyc
  48. TEMPAT SAMPAH
      backend/api/models/__pycache__/system.cpython-310.pyc
  49. TEMPAT SAMPAH
      backend/api/models/__pycache__/user.cpython-310.pyc
  50. TEMPAT SAMPAH
      backend/api/models/__pycache__/view.cpython-310.pyc
  51. 6 0
      backend/api/models/file.py
  52. 2 1
      backend/api/urls.py
  53. TEMPAT SAMPAH
      backend/backend/__pycache__/__init__.cpython-310.pyc
  54. TEMPAT SAMPAH
      backend/backend/__pycache__/settings.cpython-310.pyc
  55. TEMPAT SAMPAH
      backend/backend/__pycache__/urls.cpython-310.pyc
  56. TEMPAT SAMPAH
      backend/backend/__pycache__/wsgi.cpython-310.pyc
  57. TEMPAT SAMPAH
      backend/db.sqlite3
  58. TEMPAT SAMPAH
      scheduler/__pycache__/processManager.cpython-310.pyc
  59. TEMPAT SAMPAH
      scheduler/__pycache__/utils.cpython-310.pyc
  60. 12 0
      viewer/src/router/index.ts
  61. 4 4
      viewer/src/store/analyzeInfo.js
  62. 2 4
      viewer/src/views/dashoard/analyze.vue
  63. 7 5
      viewer/src/views/dashoard/plan.vue
  64. 340 2
      viewer/src/views/dashoard/view.vue

TEMPAT SAMPAH
backend/api/__pycache__/__init__.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/admin.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_alert.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_calculate.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_graph.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_prepare.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_rawDataTrans.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_results.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_system.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/api_user.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/apps.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/scheduler.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/serializers.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/tokenAuthentication.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/urls.cpython-310.pyc


TEMPAT SAMPAH
backend/api/__pycache__/utils.cpython-310.pyc


+ 27 - 1
backend/api/api_prepare.py

@@ -283,4 +283,30 @@ class PlanAPI(APIView):
         if overWritePlans:
             return success(message="规划已覆盖", data=createdPlans)
         else:
-            return success(message="规划已提交", data=createdPlans)
+            return success(message="规划已提交", data=createdPlans)
+
+class MissionsAPI(APIView):
+    def get(self, request):
+        user =  request.user
+        missions = Mission.objects.filter(user=user).all()
+        response = []
+        for mission in missions:
+            nodesInfo = mission.nodeFile.own_file_info
+            edgesInfo = mission.edgeFile.own_file_info
+            response.append({
+                'id': mission.id,
+                'name': mission.name,
+                'createTime': mission.create_time,
+                'nodesInfo': {
+                    'S': nodesInfo.sNodes,
+                    'D': nodesInfo.dNodes,
+                    'I': nodesInfo.iNodes,
+                },
+                'edgesInfo': {
+                    'num': edgesInfo.edges,
+                },
+                # 防止近义词错误
+                'status': mission.state,
+                'state': mission.state,
+            })
+        return success(data=response)

TEMPAT SAMPAH
backend/api/migrations/__pycache__/0001_initial.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0002_alter_user_options_user_last_login.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0003_view_file.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0004_rename_display_name_user_displayname_file_usage.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0005_file_associate_file_content.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0006_alter_file_associate.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0007_fileinfo.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0008_mission_result.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0009_alter_fileinfo_file_alter_mission_name.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0010_algorithm_plan.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0011_result_plan_result_state.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0012_result_edgefile_result_nodefile_alter_result_plan.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0013_remove_result_state_alter_file_usage.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0014_result_progress.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0015_mission_state.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0016_alter_result_edgefile_alter_result_nodefile.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0017_graph_graphtoken.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0018_rename_edgemap_graph_edges_and_more.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0019_alter_graph_user.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0020_alert_systemperformance.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/0021_rename_indicator_alert_metric.cpython-310.pyc


TEMPAT SAMPAH
backend/api/migrations/__pycache__/__init__.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/__init__.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/alert.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/algorithm.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/file.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/graph.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/mission.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/plan.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/result.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/system.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/user.cpython-310.pyc


TEMPAT SAMPAH
backend/api/models/__pycache__/view.cpython-310.pyc


+ 6 - 0
backend/api/models/file.py

@@ -115,6 +115,12 @@ class File(models.Model):
             self.delete()
             return FILE_ALREADY_EXIST
         else:
+            try:
+                os.mkdir(path)
+            except Exception as error:
+                if not error.args[0] == 17:
+                    print(error)
+                    return FILE_FAILED_CREATE_DIR
             if self.content == 'node':
                 nodes = []
                 file = open(os.path.join(path, str(self.id)), 'w', newline='')

+ 2 - 1
backend/api/urls.py

@@ -1,7 +1,7 @@
 from django.urls import path
 from .api_user import UserRegisterAPI, UserLoginAPI
 from .api_user import getDashboard
-from .api_prepare import UploadFileAPI, PlanAPI, InputFileAPI
+from .api_prepare import UploadFileAPI, PlanAPI, InputFileAPI, MissionsAPI
 from .api_calculate import CalculateAPI
 from .api_rawDataTrans import RawDataTrans
 from .api_results import Results
@@ -24,4 +24,5 @@ urlpatterns = [
     path('alertCheck/', AlertCheck.as_view(), name="alert_check_api"),
     path('systemPerformance/', SystemPerformanceAPI.as_view(), name="system_performance_api"),
     path('inputFile/', InputFileAPI.as_view(), name='input_file_api'),
+    path('missions/', MissionsAPI.as_view(), name="missions_api"),
 ]

TEMPAT SAMPAH
backend/backend/__pycache__/__init__.cpython-310.pyc


TEMPAT SAMPAH
backend/backend/__pycache__/settings.cpython-310.pyc


TEMPAT SAMPAH
backend/backend/__pycache__/urls.cpython-310.pyc


TEMPAT SAMPAH
backend/backend/__pycache__/wsgi.cpython-310.pyc


TEMPAT SAMPAH
backend/db.sqlite3


TEMPAT SAMPAH
scheduler/__pycache__/processManager.cpython-310.pyc


TEMPAT SAMPAH
scheduler/__pycache__/utils.cpython-310.pyc


+ 12 - 0
viewer/src/router/index.ts

@@ -38,6 +38,18 @@ const router = createRouter({
         {
           path: 'view',
           component: () => import('../views/dashoard/view.vue'),
+          children: [
+            {
+              path: 'plan',
+              component: () => import('../views/dashoard/plan.vue'),
+              children: [
+                {
+                  path: 'calculate',
+                  component: () => import('../views/dashoard/calculate.vue'),
+                }
+              ]
+            }
+          ],
         },
         {
           path: 'monitor',

+ 4 - 4
viewer/src/store/analyzeInfo.js

@@ -4,20 +4,20 @@ export function useAnalyzeInfo() {
     const analyzeInfo = ref({
         nodeFile: {
             id: null, 
-            name: null,
-            amount: 0,
+            num: 0,
             sNodes: 0,
             dNodes: 0,
             iNodes: 0,
         },
         edgeFile: {
             id: null,
-            name: null,
-            amount: 0,
+            num: 0,
         },
         mission: {
             id: null,
             name: null,
+            createTime: null,
+            status: null,
         }
     });
     return {

+ 2 - 4
viewer/src/views/dashoard/analyze.vue

@@ -464,16 +464,14 @@ const preparePlan = (response) => {
   response.data.forEach(file => {
     if (file.content === 'node') {
       useAnalyzeInfo.analyzeInfo.value.nodeFile.id = file.id
-      useAnalyzeInfo.analyzeInfo.value.nodeFile.name = file.name
-      useAnalyzeInfo.analyzeInfo.value.nodeFile.amount = file.ndoes
+      useAnalyzeInfo.analyzeInfo.value.nodeFile.num = file.ndoes
       useAnalyzeInfo.analyzeInfo.value.nodeFile.sNodes = file.sNodes
       useAnalyzeInfo.analyzeInfo.value.nodeFile.dNodes = file.dNodes
       useAnalyzeInfo.analyzeInfo.value.nodeFile.iNodes = file.iNodes
     }
     if (file.content === 'edge') {
       useAnalyzeInfo.analyzeInfo.value.edgeFile.id = file.id
-      useAnalyzeInfo.analyzeInfo.value.edgeFile.name = file.name
-      useAnalyzeInfo.analyzeInfo.value.edgeFile.amount = file.edges
+      useAnalyzeInfo.analyzeInfo.value.edgeFile.num = file.edges
     }
     // 获取创建的分析任务ID
     if (file.content === 'mission') {

+ 7 - 5
viewer/src/views/dashoard/plan.vue

@@ -16,13 +16,13 @@
           <el-form-item>
             <div class="stats-item">
               <el-tooltip content="聚焦节点说明" placement="top">
-                <span>聚焦节点数: {{ nodeData.amount }}</span>
+                <span>聚焦节点数: {{ nodeData.num }}</span>
               </el-tooltip>
               <el-tooltip content="孤立节点说明" placement="top">
-                <span>孤立节点数: {{ nodeData.amount }}</span>
+                <span>孤立节点数: {{ nodeData.num }}</span>
               </el-tooltip>
               <el-tooltip content="总节点说明" placement="top">
-                <span>总节点数: {{ nodeData.amount }}</span>
+                <span>总节点数: {{ nodeData.num }}</span>
               </el-tooltip>
             </div>
           </el-form-item>
@@ -32,7 +32,7 @@
               <el-tooltip content="边集中度说明" placement="top">
                 <span>边集中度: {{ edgeData.concentration }}</span>
               </el-tooltip>
-              <span>总边数: {{ edgeData.amount }}</span>
+              <span>总边数: {{ edgeData.num }}</span>
             </div>
           </el-form-item>
         </el-form>
@@ -567,7 +567,9 @@ const submitPlan = async () => {
       btn.id = p.id
       btn.parentId = p.parentId
     })
-    router.push(`/dashboard/analyze/plan/calculate`)
+    const currentPath = router.currentRoute.value.path;
+    const newPath = currentPath.endsWith('/') ? currentPath + 'calculate' : currentPath + '/calculate';
+    router.push(newPath)
   } catch (e) {
       ElMessage.error(e.response.data.message)
   }

+ 340 - 2
viewer/src/views/dashoard/view.vue

@@ -1,7 +1,345 @@
 <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>
 </template>
+
 <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>
+
+<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>