147 lines
6.2 KiB
Vue
147 lines
6.2 KiB
Vue
<template>
|
|
<div class="p-8 bg-slate-50 min-h-screen animate-fade-in">
|
|
<!-- Header -->
|
|
<div class="flex justify-between items-center mb-8">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-slate-900">项目列表 (Projects)</h1>
|
|
<p class="text-slate-500 text-sm mt-1">管理所有正在进行和已交付的咨询项目</p>
|
|
</div>
|
|
<div class="flex space-x-4">
|
|
<div class="relative">
|
|
<Search :size="18" class="absolute left-3 top-2.5 text-slate-400" />
|
|
<input
|
|
type="text"
|
|
placeholder="搜索项目、客户..."
|
|
class="pl-10 pr-4 py-2 bg-white border border-slate-200 rounded-md text-sm w-64 focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
|
|
/>
|
|
</div>
|
|
<!-- New Project Button -> Goes to Engagement Setup -->
|
|
<button
|
|
@click="handleNewProject"
|
|
class="flex items-center px-4 py-2 bg-blue-600 text-white rounded-md shadow-sm text-sm font-bold hover:bg-blue-700 transition-colors"
|
|
>
|
|
<Plus :size="18" class="mr-2" /> 新建项目
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Projects Table -->
|
|
<div class="bg-white rounded-lg border border-slate-200 shadow-sm overflow-hidden">
|
|
<div class="px-6 py-4 border-b border-slate-100 flex justify-between items-center bg-slate-50/50">
|
|
<div class="flex space-x-4">
|
|
<span class="text-sm font-bold text-slate-800 border-b-2 border-blue-500 pb-1 cursor-pointer">全部项目 (12)</span>
|
|
<span class="text-sm font-medium text-slate-500 hover:text-slate-700 cursor-pointer">进行中</span>
|
|
<span class="text-sm font-medium text-slate-500 hover:text-slate-700 cursor-pointer">已完成</span>
|
|
</div>
|
|
<button class="text-slate-400 hover:text-slate-600"><Settings :size="16" /></button>
|
|
</div>
|
|
|
|
<table class="min-w-full text-left text-sm">
|
|
<thead class="bg-slate-50 text-slate-500 font-medium">
|
|
<tr>
|
|
<th class="px-6 py-3">项目名称</th>
|
|
<th class="px-6 py-3">客户名称</th>
|
|
<th class="px-6 py-3">项目类型</th>
|
|
<th class="px-6 py-3">项目进度</th>
|
|
<th class="px-6 py-3">负责人</th>
|
|
<th class="px-6 py-3">最近更新</th>
|
|
<th class="px-6 py-3 text-right">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100">
|
|
<tr
|
|
v-for="project in projectsList"
|
|
:key="project.id"
|
|
class="hover:bg-slate-50 transition-colors group cursor-pointer"
|
|
@click="handleProjectClick(project, $event)"
|
|
>
|
|
<td class="px-6 py-4">
|
|
<div class="flex items-center">
|
|
<div class="w-8 h-8 rounded bg-blue-50 flex items-center justify-center text-blue-600 mr-3">
|
|
<Layers :size="16"/>
|
|
</div>
|
|
<div class="font-bold text-slate-800">{{ project.name }}</div>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 text-slate-600">
|
|
{{ project.client }}
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-slate-100 text-slate-600">
|
|
{{ project.type }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 w-48">
|
|
<div class="flex items-center justify-between mb-1 text-xs text-slate-500">
|
|
<span>{{ project.progress }}%</span>
|
|
</div>
|
|
<ProgressBar :percent="project.progress" :status="project.status" />
|
|
</td>
|
|
<td class="px-6 py-4 text-slate-600">
|
|
<div class="flex items-center">
|
|
<div class="w-5 h-5 rounded-full bg-slate-200 text-xs flex items-center justify-center mr-2">{{ project.owner[0] }}</div>
|
|
{{ project.owner }}
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 text-slate-400 text-xs">
|
|
{{ project.lastUpdate }}
|
|
</td>
|
|
<td class="px-6 py-4 text-right" @click.stop>
|
|
<button
|
|
@click="() => handleProjectClick(project)"
|
|
class="text-blue-600 hover:text-blue-800 font-medium text-xs mr-3"
|
|
>
|
|
进入作业
|
|
</button>
|
|
<button class="text-slate-400 hover:text-slate-600"><MoreHorizontal :size="16" /></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- Pagination Mockup -->
|
|
<div class="px-6 py-4 border-t border-slate-100 flex items-center justify-between bg-slate-50/30">
|
|
<span class="text-xs text-slate-500">显示 1-5 共 12 条记录</span>
|
|
<div class="flex space-x-1">
|
|
<button class="px-3 py-1 border border-slate-200 rounded text-xs text-slate-600 hover:bg-slate-100 disabled:opacity-50">上一页</button>
|
|
<button class="px-3 py-1 border border-slate-200 rounded text-xs text-slate-600 hover:bg-slate-100">下一页</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { Search, Plus, Settings, MoreHorizontal, Layers } from 'lucide-vue-next';
|
|
import ProgressBar from '@/components/ProgressBar.vue';
|
|
import { projectsList } from '@/data/mockData';
|
|
import type { ViewMode, Step, Project } from '@/types';
|
|
|
|
interface Props {
|
|
setCurrentView: (view: ViewMode) => void;
|
|
setCurrentStep: (step: Step) => void;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
const handleNewProject = () => {
|
|
props.setCurrentStep('setup');
|
|
props.setCurrentView('engagement');
|
|
};
|
|
|
|
const handleProjectClick = (project: Project, event?: Event) => {
|
|
// Don't trigger if clicking on action buttons (except the "进入作业" button)
|
|
if (event) {
|
|
const target = event.target as HTMLElement;
|
|
// Prevent double-trigger if clicking on other buttons
|
|
if (target.closest('button') && !target.closest('button')?.textContent?.includes('进入作业')) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Always go to engagement view with setup step (project configuration)
|
|
props.setCurrentView('engagement');
|
|
props.setCurrentStep('setup');
|
|
};
|
|
</script>
|