Dashboard.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <template>
  2. <div>
  3. <el-card shadow="never" style="padding: 18px">
  4. <el-row :gutter="16" justify="start">
  5. <el-col :span="4" v-for="(card, idx) in cards" :key="idx">
  6. <div
  7. style="
  8. background: #fff;
  9. padding: 12px;
  10. border-radius: 6px;
  11. box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  12. "
  13. >
  14. <div style="font-size: 13px; color: #888">{{ card.title }}</div>
  15. <div style="font-size: 20px; margin-top: 6px">{{ card.value }}</div>
  16. </div>
  17. </el-col>
  18. </el-row>
  19. </el-card>
  20. <el-card style="margin-top: 16px">
  21. <el-tabs v-model:active-name="activeTab">
  22. <el-tab-pane label="工作流程" name="flows"></el-tab-pane>
  23. <el-tab-pane label="证书" name="certs"></el-tab-pane>
  24. <el-tab-pane label="执行" name="execs"></el-tab-pane>
  25. <el-tab-pane label="变量" name="vars"></el-tab-pane>
  26. <el-tab-pane label="数据表" name="tables"></el-tab-pane>
  27. </el-tabs>
  28. <div
  29. style="display: flex; justify-content: space-between; align-items: center; margin-top: 12px"
  30. >
  31. <div style="display: flex; gap: 8px; align-items: center">
  32. <el-input placeholder="搜索" v-model="filter" clearable style="width: 260px" />
  33. <el-select v-model="sort" placeholder="Sort" size="small" style="width: 160px">
  34. <el-option label="Sort by last updated" value="updated" />
  35. <el-option label="Sort by name" value="name" />
  36. </el-select>
  37. </div>
  38. <div>
  39. <el-button type="text" size="small">筛选</el-button>
  40. </div>
  41. </div>
  42. <div style="margin-top: 12px">
  43. <el-empty v-if="filtered.length === 0" description="无工作流" />
  44. <div v-else>
  45. <div v-for="item in paged" :key="item.id" style="margin-bottom: 12px">
  46. <el-card>
  47. <div style="display: flex; justify-content: space-between; align-items: center">
  48. <div>
  49. <div style="font-weight: 700">{{ item.title }}</div>
  50. <div style="color: #999; font-size: 12px">上次更新时间: {{ item.created }}</div>
  51. </div>
  52. <div style="display: flex; gap: 8px; align-items: center">
  53. <el-tag size="small">个人的</el-tag>
  54. <el-button type="primary" size="small">运行</el-button>
  55. <el-dropdown>
  56. <span class="el-dropdown-link">•••</span>
  57. <template #dropdown>
  58. <el-dropdown-menu>
  59. <el-dropdown-item>编辑</el-dropdown-item>
  60. <el-dropdown-item>删除</el-dropdown-item>
  61. </el-dropdown-menu>
  62. </template>
  63. </el-dropdown>
  64. </div>
  65. </div>
  66. </el-card>
  67. </div>
  68. </div>
  69. </div>
  70. <div style="display: flex; justify-content: flex-end; margin-top: 12px">
  71. <el-pagination
  72. background
  73. :page-size="pageSize"
  74. :current-page.sync="page"
  75. :total="filtered.length"
  76. layout="prev, pager, next"
  77. />
  78. </div>
  79. </el-card>
  80. </div>
  81. </template>
  82. <script setup lang="ts">
  83. import { ref, computed } from 'vue'
  84. const cards = [
  85. { title: '生产执行', value: 0 },
  86. { title: '执行失败', value: 0 },
  87. { title: '故障率', value: '0%' },
  88. { title: '运行时间(平均)', value: '0s' }
  89. ]
  90. const workflows = ref([
  91. { id: 1, title: '与新同事人才交流', created: '1 月 23 日' },
  92. { id: 2, title: 'RAG 同步机器人,基于 Supabase', created: '1 月 23 日' },
  93. { id: 3, title: '利用 Gemini AI, OCR 和 Google Sheets', created: '1 月 23 日' }
  94. ])
  95. const filter = ref('')
  96. const sort = ref('updated')
  97. const activeTab = ref('flows')
  98. const page = ref(1)
  99. const pageSize = 10
  100. const filtered = computed(() => {
  101. const q = filter.value.trim().toLowerCase()
  102. if (!q) return workflows.value
  103. return workflows.value.filter((w) => w.title.toLowerCase().includes(q))
  104. })
  105. const paged = computed(() => {
  106. const start = (page.value - 1) * pageSize
  107. return filtered.value.slice(start, start + pageSize)
  108. })
  109. </script>
  110. <style lang="less" scoped></style>