Browse Source

快捷导航新增最近打开功能

liuq 1 month ago
parent
commit
9d3d9c9140
1 changed files with 129 additions and 12 deletions
  1. 129 12
      frontend/src/views/PlatformLaunchpad.vue

+ 129 - 12
frontend/src/views/PlatformLaunchpad.vue

@@ -16,6 +16,25 @@
     </div>
     </div>
 
 
     <div v-loading="loading">
     <div v-loading="loading">
+      <!-- 最近打开 -->
+      <div v-if="recentApps.length > 0" class="recent-section">
+        <h3 class="section-title">最近打开</h3>
+        <div class="apps-grid">
+          <div
+            v-for="app in recentApps"
+            :key="app.app_id"
+            class="app-item"
+            :style="{ width: iconSize + 'px' }"
+          >
+            <PlatformIcon
+              :text="app.app_name"
+              :size="iconSize"
+              @click="handleAppClick(app)"
+            />
+          </div>
+        </div>
+      </div>
+
       <!-- 按分类显示 -->
       <!-- 按分类显示 -->
       <template v-if="showCategory">
       <template v-if="showCategory">
         <div
         <div
@@ -42,18 +61,21 @@
       </template>
       </template>
 
 
       <!-- 不按分类显示(原有方式) -->
       <!-- 不按分类显示(原有方式) -->
-      <div v-else class="apps-grid">
-        <div
-          v-for="app in activeApps"
-          :key="app.app_id"
-          class="app-item"
-          :style="{ width: iconSize + 'px' }"
-        >
-          <PlatformIcon
-            :text="app.app_name"
-            :size="iconSize"
-            @click="handleAppClick(app)"
-          />
+      <div v-else>
+        <h3 class="section-title">全部应用</h3>
+        <div class="apps-grid">
+          <div
+            v-for="app in activeApps"
+            :key="app.app_id"
+            class="app-item"
+            :style="{ width: iconSize + 'px' }"
+          >
+            <PlatformIcon
+              :text="app.app_name"
+              :size="iconSize"
+              @click="handleAppClick(app)"
+            />
+          </div>
         </div>
         </div>
       </div>
       </div>
 
 
@@ -105,6 +127,13 @@ interface CategoryGroup {
   apps: Mapping[]
   apps: Mapping[]
 }
 }
 
 
+interface RecentAppRecord {
+  app_id: string
+  app_name: string
+  count: number
+  lastOpenTime: number
+}
+
 // State
 // State
 const mappings = ref<Mapping[]>([])
 const mappings = ref<Mapping[]>([])
 const loading = ref(false)
 const loading = ref(false)
@@ -157,6 +186,78 @@ const categorizedApps = computed(() => {
   return result
   return result
 })
 })
 
 
+// 最近打开的应用记录
+const recentApps = computed<Mapping[]>(() => {
+  const records = loadRecentApps()
+  if (records.length === 0) return []
+  
+  // 按最近打开时间排序,时间越近的越靠前
+  const sortedRecords = records
+    .sort((a, b) => {
+      return b.lastOpenTime - a.lastOpenTime
+    })
+  
+  // 从mappings中获取最新的应用信息,只返回仍然存在且激活的应用
+  const result: Mapping[] = []
+  for (const record of sortedRecords) {
+    const app = mappings.value.find(a => a.app_id === record.app_id && a.is_active)
+    if (app) {
+      result.push(app)
+      if (result.length >= 5) break
+    }
+  }
+  
+  return result
+})
+
+// 加载最近打开的应用记录
+const loadRecentApps = (): RecentAppRecord[] => {
+  try {
+    const saved = localStorage.getItem('launchpad_recent_apps')
+    if (saved) {
+      return JSON.parse(saved)
+    }
+  } catch (e) {
+    console.error('Failed to parse recent apps', e)
+  }
+  return []
+}
+
+// 保存最近打开的应用记录
+const saveRecentApps = (records: RecentAppRecord[]) => {
+  try {
+    localStorage.setItem('launchpad_recent_apps', JSON.stringify(records))
+  } catch (e) {
+    console.error('Failed to save recent apps', e)
+  }
+}
+
+// 记录应用打开
+const recordAppOpen = (app: Mapping) => {
+  if (!app.is_active) return
+  
+  const records = loadRecentApps()
+  const existingIndex = records.findIndex(r => r.app_id === app.app_id)
+  
+  if (existingIndex >= 0) {
+    // 更新现有记录:增加打开次数,更新最后打开时间
+    records[existingIndex].count += 1
+    records[existingIndex].lastOpenTime = Date.now()
+    // 更新应用信息(名称等可能会变化)
+    records[existingIndex].app_name = app.app_name
+  } else {
+    // 添加新记录
+    records.push({
+      app_id: app.app_id,
+      app_name: app.app_name,
+      count: 1,
+      lastOpenTime: Date.now()
+    })
+  }
+  
+  saveRecentApps(records)
+}
+
 // Load Settings
 // Load Settings
 const loadSettings = () => {
 const loadSettings = () => {
   const saved = localStorage.getItem('launchpad_settings')
   const saved = localStorage.getItem('launchpad_settings')
@@ -208,6 +309,9 @@ const fetchMappings = async () => {
 const handleAppClick = async (app: Mapping) => {
 const handleAppClick = async (app: Mapping) => {
   if (!app.is_active) return
   if (!app.is_active) return
   
   
+  // 记录应用打开
+  recordAppOpen(app)
+  
   const loadingMsg = ElMessage.info({
   const loadingMsg = ElMessage.info({
     message: `正在进入 ${app.app_name}...`,
     message: `正在进入 ${app.app_name}...`,
     duration: 0
     duration: 0
@@ -304,6 +408,19 @@ onUnmounted(() => {
   margin-bottom: 40px;
   margin-bottom: 40px;
 }
 }
 
 
+.recent-section {
+  margin-bottom: 40px;
+}
+
+.section-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+  margin-bottom: 20px;
+  padding-bottom: 10px;
+  border-bottom: 2px solid #e4e7ed;
+}
+
 .category-title {
 .category-title {
   font-size: 18px;
   font-size: 18px;
   font-weight: 600;
   font-weight: 600;