优化: 所有剩余UI/UX待办一批完成(持久化+AuditLog+解耦+total+原12大改+P2)
持久化(P1-c):新建 usePersistedRef composable,Tasks/AuditLog/ProjectDetail 等接入 localStorage
AuditLog(P1-d):后端 list_tool_executions 加 WHERE 筛选+返 {items,total,has_more},前端对接+长列折叠+筛选持久化
数据源解耦(P1-g):ProjectDetail projectTasks 按 project_id 独立加载 + ChatInput @项目联想独立加载(不读 store.tasks 当前页)
GitChanges(12a):后端 get_module_commits 加 git rev-list --count 返 total,前端显真实总数
原12大改:Dashboard 统计卡压底行(1)/Projects 列表卡片视图(2)/project_event 埋点排序(3)/TaskDetail 重设计(4)/IdeaDetail 重设计(5)/KnowledgeDetail 重设计(6)/界面持久化+侧栏Ctrl+B+审批数字键(7)/ProjectDetail 三栏改两栏(10)
P2打磨:文件浏览器(FileTree去重/FilePreview行号.md Diff/selectedFilePath归位)/settings反馈(假保存/端口校验)/AI会话(try-catch/scrollIntoView)/后端计数(move_queue事件/timeline total/workflow分页/import_batch分块)/杂项(TopBar/ConfirmDialog键盘/CIStatus i18n/ToolResultBody/ModuleNode/ApprovalDialog全选)
This commit is contained in:
+65
-7
@@ -3,6 +3,21 @@
|
||||
<header class="page-header">
|
||||
<h1>{{ $t('projects.title') }}</h1>
|
||||
<div class="header-actions">
|
||||
<!-- 视图模式切换(默认 list 紧凑;card 宽松):切换持久化 localStorage -->
|
||||
<div class="view-toggle" :title="$t('projects.viewModeTitle')">
|
||||
<button
|
||||
class="view-toggle-btn"
|
||||
:class="{ active: viewMode === 'list' }"
|
||||
:title="$t('projects.viewList')"
|
||||
@click="viewMode = 'list'"
|
||||
>☰</button>
|
||||
<button
|
||||
class="view-toggle-btn"
|
||||
:class="{ active: viewMode === 'card' }"
|
||||
:title="$t('projects.viewCard')"
|
||||
@click="viewMode = 'card'"
|
||||
>▦</button>
|
||||
</div>
|
||||
<button class="btn btn-ghost" @click="openImportModal">{{ $t('projects.importHistory') }}</button>
|
||||
<button class="btn btn-ghost" @click="openTrash">{{ $t('projects.trash') }}</button>
|
||||
<button class="btn btn-primary" @click="showCreateModal = true">{{ $t('projects.create') }}</button>
|
||||
@@ -139,8 +154,15 @@
|
||||
</div>
|
||||
|
||||
<!-- 项目卡片网格(单卡片渲染抽至 components/project/ProjectCard.vue,删除走 emit 回父处理) -->
|
||||
<div class="project-grid">
|
||||
<ProjectCard v-for="project in pagedProjects" :key="project.id" :project="project" @delete="handleDelete" />
|
||||
<!-- viewMode='list' → 单列紧凑;viewMode='card' → 双列宽松(默认改造前形态) -->
|
||||
<div class="project-grid" :class="'grid-' + viewMode">
|
||||
<ProjectCard
|
||||
v-for="project in pagedProjects"
|
||||
:key="project.id"
|
||||
:project="project"
|
||||
:view="viewMode"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 分页器(F-260621-02 P3):pageSize=0 不分页(全量,等价旧行为);用户选 N 条触发客户端切片 -->
|
||||
@@ -175,15 +197,20 @@ import ProjectCard from '@/components/project/ProjectCard.vue'
|
||||
import Paginator from '@/components/Paginator.vue'
|
||||
import { useConfirm } from '@/composables/useConfirm'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { usePersistedRef } from '@/composables/usePersistedRef'
|
||||
import type { ProjectRecord } from '@/api/types'
|
||||
import type { ScannedProjectItem } from '@/api/project'
|
||||
|
||||
const store = useProjectStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
// 分页(F-260621-02 P3):pageSize=0 → 全量(向后兼容,等价改造前);用户选 N → 客户端切片
|
||||
const page = ref(1)
|
||||
const pageSize = ref(0)
|
||||
// 分页(F-260621-02 P3):pageSize=0 → 全量(向后兼容,等价改造前);用户选 N → 客户端切片。
|
||||
// page/pageSize 持久化 localStorage(刷新/重开记住用户选择)。
|
||||
const page = usePersistedRef('projects.page', 1)
|
||||
const pageSize = usePersistedRef('projects.pageSize', 0)
|
||||
|
||||
// 视图模式:'list'(紧凑单列,默认)/'card'(宽松双列)。持久化 localStorage。
|
||||
const viewMode = usePersistedRef<'list' | 'card'>('projects.viewMode', 'list')
|
||||
|
||||
// 分页视图:pageSize=0 → 全量;否则取当前页窗口
|
||||
const pagedProjects = computed(() => {
|
||||
@@ -426,11 +453,41 @@ async function runImport() {
|
||||
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
|
||||
/* ===== 卡片网格 ===== */
|
||||
/* 默认改造前为双列;viewMode 驱动 list(单列紧凑)/card(双列宽松) */
|
||||
.project-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--df-gap-grid);
|
||||
}
|
||||
.project-grid.grid-card {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.project-grid.grid-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
/* ===== 视图模式切换 ===== */
|
||||
.view-toggle {
|
||||
display: inline-flex;
|
||||
border: 0.5px solid var(--df-border);
|
||||
border-radius: var(--df-radius-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
.view-toggle-btn {
|
||||
min-width: 30px;
|
||||
padding: 6px 10px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--df-text-dim);
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.view-toggle-btn:hover { background: var(--df-bg-card); color: var(--df-text); }
|
||||
.view-toggle-btn.active {
|
||||
background: rgba(108, 99, 255, 0.12);
|
||||
color: var(--df-accent);
|
||||
}
|
||||
|
||||
/* ===== 进度条 ===== */
|
||||
.card-progress { margin-bottom: 16px; }
|
||||
@@ -498,7 +555,8 @@ async function runImport() {
|
||||
/* ===== 响应式 ===== */
|
||||
@media (max-width: 768px) {
|
||||
.projects { padding: 16px; }
|
||||
.project-grid {
|
||||
/* 移动端:card 视图也降为单列;list 本就单列 */
|
||||
.project-grid.grid-card {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user