From 91bfcf61f44f353dfebc54a57b5b774721de3e9a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 19 十月 2026 09:39:22 +0800
Subject: [PATCH] feat(auth): 更新门户认证页面布局和样式

---
 src/views/dashboard/analytics/modules/todo-panel.vue |  207 ++-------------------------------------------------
 1 files changed, 11 insertions(+), 196 deletions(-)

diff --git a/src/views/dashboard/analytics/modules/todo-panel.vue b/src/views/dashboard/analytics/modules/todo-panel.vue
index 916b434..8c840ed 100644
--- a/src/views/dashboard/analytics/modules/todo-panel.vue
+++ b/src/views/dashboard/analytics/modules/todo-panel.vue
@@ -1,208 +1,23 @@
-<script lang="ts" setup>
+<script setup lang="ts">
 import { onMounted, ref } from 'vue';
-
 import { IconifyIcon } from '@vben/icons';
-
+import { usePortalMenus } from '#/components/portal/use-portal-menus';
 import { getTaskTodoPage } from '#/api/bpm/task';
 
-defineOptions({ name: 'DashboardTodoPanel' });
-
-const emit = defineEmits<{
-  navigate: [name: string];
-}>();
-
-interface TodoItem {
-  id: string;
-  name: string;
-  createTime?: number;
-}
-
-const loading = ref(true);
-const items = ref<TodoItem[]>([]);
-
-/** createTime 涓烘绉掓椂闂存埑锛屾牸寮忓寲鎴愭槗璇绘枃鏈� */
-function formatTime(ts?: number) {
-  if (!ts) return '-';
-  const d = new Date(ts);
-  const p = (n: number) => String(n).padStart(2, '0');
-  return `${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
-}
-
+const { features, goMenu } = usePortalMenus();
+const loading = ref(true), failed = ref(false);
+const tasks = ref<{ id: string; name: string }[]>([]);
 async function load() {
-  loading.value = true;
-  try {
-    const result = await getTaskTodoPage({ pageNo: 1, pageSize: 6 });
-    items.value = (result.list ?? []).map((t: any) => ({
-      id: String(t.id),
-      name: t.name ?? '鏈懡鍚嶄换鍔�',
-      createTime: t.createTime,
-    }));
-  } catch {
-    items.value = [];
-  } finally {
-    loading.value = false;
-  }
+  loading.value = true; failed.value = false;
+  try { const result = await getTaskTodoPage({ pageNo: 1, pageSize: 6 }); tasks.value = (result.list ?? []).map((task) => ({ id: String(task.id), name: task.name || '鏈懡鍚嶄换鍔�' })); }
+  catch { failed.value = true; tasks.value = []; }
+  finally { loading.value = false; }
 }
-
 onMounted(load);
 </script>
 
-<template>
-  <div class="elite-section h-full">
-    <div class="elite-head">
-      <h3 class="elite-title">
-        <span class="elite-bar"></span>
-        鎴戠殑寰呭姙
-      </h3>
-      <span class="elite-more" @click="emit('navigate', 'BpmTaskTodo')">
-        鍏ㄩ儴
-        <IconifyIcon class="size-3.5" icon="lucide:chevron-right" />
-      </span>
-    </div>
-
-    <!-- 楠ㄦ灦 -->
-    <div v-if="loading" class="elite-empty">鍔犺浇涓��</div>
-
-    <!-- 绌虹姸鎬� -->
-    <div v-else-if="items.length === 0" class="elite-empty">
-      <IconifyIcon class="mb-2 size-8 opacity-40" icon="lucide:inbox" />
-      <div>鏆傛棤寰呭姙浠诲姟</div>
-    </div>
-
-    <!-- 鍒楄〃 -->
-    <ul v-else class="elite-list">
-      <li
-        v-for="item in items"
-        :key="item.id"
-        class="elite-row"
-        @click="emit('navigate', 'BpmTaskTodo')"
-      >
-        <span class="elite-dot"></span>
-        <span class="elite-row-name">{{ item.name }}</span>
-        <span class="elite-row-time">{{ formatTime(item.createTime) }}</span>
-      </li>
-    </ul>
-  </div>
-</template>
+<template><article class="portal-todo-panel"><div class="todo-heading"><h2><IconifyIcon icon="lucide:list-todo" />鎴戠殑寰呭姙</h2><button type="button" @click="goMenu(features.todo)">鏇村 <IconifyIcon icon="lucide:chevron-right" /></button></div><div v-if="loading" class="todo-status" role="status">姝e湪鍔犺浇寰呭姙鈥�</div><div v-else-if="failed" class="todo-status" role="status"><span>寰呭姙鍔犺浇澶辫触</span><button type="button" @click="load">閲嶆柊鍔犺浇</button></div><div v-else-if="!tasks.length" class="todo-status"><IconifyIcon icon="lucide:inbox" /><span>鏆傛棤寰呭姙浠诲姟</span></div><ul v-else><li v-for="task in tasks" :key="task.id"><button type="button" @click="goMenu(features.todo)"><span>{{ task.name }}</span><IconifyIcon icon="lucide:chevron-right" /></button></li></ul></article></template>
 
 <style scoped>
-.elite-section {
-  border-radius: 14px;
-  padding: 20px;
-  background: #fdfcfa;
-  border: 1px solid rgba(212, 175, 55, 0.22);
-  box-shadow: 0 2px 14px rgba(15, 36, 64, 0.05);
-}
-
-.dark .elite-section {
-  background: #101a2b;
-  border-color: rgba(212, 175, 55, 0.2);
-  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.3);
-}
-
-.elite-head {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  margin-bottom: 14px;
-}
-
-.elite-title {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  margin: 0;
-  font-size: 15px;
-  font-weight: 600;
-  letter-spacing: 1px;
-  color: #0f2440;
-}
-
-.dark .elite-title {
-  color: #f0ead8;
-}
-
-.elite-bar {
-  display: inline-block;
-  width: 3px;
-  height: 15px;
-  border-radius: 2px;
-  background: linear-gradient(180deg, #e3c567, #b8901f);
-}
-
-.elite-more {
-  display: inline-flex;
-  cursor: pointer;
-  align-items: center;
-  gap: 2px;
-  font-size: 12px;
-  color: #b8901f;
-  transition: color 0.2s ease;
-}
-
-.elite-more:hover {
-  color: #8a6a12;
-}
-
-.elite-empty {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  padding: 34px 0;
-  font-size: 13px;
-  color: #8a94a6;
-}
-
-.elite-list {
-  margin: 0;
-  padding: 0;
-  list-style: none;
-}
-
-.elite-row {
-  display: flex;
-  cursor: pointer;
-  align-items: center;
-  gap: 10px;
-  padding: 11px 10px;
-  border-radius: 8px;
-  border-bottom: 1px solid rgba(15, 36, 64, 0.05);
-  transition: background-color 0.2s ease;
-}
-
-.elite-row:last-child {
-  border-bottom: none;
-}
-
-.elite-row:hover {
-  background: rgba(212, 175, 55, 0.07);
-}
-
-.elite-dot {
-  width: 6px;
-  height: 6px;
-  flex-shrink: 0;
-  border-radius: 999px;
-  background: #d4af37;
-}
-
-.elite-row-name {
-  overflow: hidden;
-  flex: 1;
-  font-size: 13.5px;
-  color: #0f2440;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.dark .elite-row-name {
-  color: #e6e9ef;
-}
-
-.elite-row-time {
-  flex-shrink: 0;
-  font-size: 12px;
-  color: #8a94a6;
-}
+.portal-todo-panel { padding: 18px; border: 1px solid #e1ebf5; border-radius: 6px; background: #fff; }.todo-heading { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; }.todo-heading h2 { display: flex; align-items: center; gap: 9px; margin: 0; color: #153a62; font-size: 17px; font-weight: 700; }.todo-heading h2 :deep(svg) { width: 19px; color: #b7242d; }.todo-heading button { display: flex; align-items: center; color: #5c7187; font-size: 11px; }.todo-status { display: flex; min-height: 230px; flex-direction: column; align-items: center; justify-content: center; gap: 12px; color: #5c7187; font-size: 13px; }.todo-status > :deep(svg) { width: 32px; height: 32px; color: #b6c9dc; }.todo-status button { min-height: 30px; padding: 4px 12px; border: 1px solid #d8e5f3; border-radius: 4px; color: #2b6094; background: #f6faff; }ul { margin: 0; padding: 0; list-style: none; }li + li { border-top: 1px solid #edf3f8; }li button { display: flex; width: 100%; min-height: 39px; align-items: center; justify-content: space-between; gap: 12px; color: #315273; font-size: 12px; text-align: left; }li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }li :deep(svg) { width: 14px; flex: none; }button { cursor: pointer; }button:focus-visible { outline: 2px solid #2c70b2; outline-offset: 3px; }
 </style>

--
Gitblit v1.9.3