268 lines
5.8 KiB
Vue
268 lines
5.8 KiB
Vue
<template>
|
|
<GiPageLayout>
|
|
<div class="project-list-container">
|
|
<!-- 顶部搜索和操作区域 -->
|
|
<div class="header-section">
|
|
<div class="search-area">
|
|
<a-input-search
|
|
v-model="searchKeyword"
|
|
placeholder="搜索项目名称"
|
|
style="width: 300px"
|
|
@search="handleSearch"
|
|
@clear="handleClear"
|
|
allow-clear
|
|
>
|
|
<template #prefix>
|
|
<GiSvgIcon name="search" />
|
|
</template>
|
|
</a-input-search>
|
|
</div>
|
|
|
|
<div class="action-area">
|
|
<a-button @click="refreshData">
|
|
<template #icon>
|
|
<GiSvgIcon name="refresh" />
|
|
</template>
|
|
刷新
|
|
</a-button>
|
|
<a-button type="primary" @click="openAddModal">
|
|
<template #icon>
|
|
<GiSvgIcon name="plus" />
|
|
</template>
|
|
新建项目
|
|
</a-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 选项卡区域 -->
|
|
<div class="tabs-section">
|
|
<a-tabs
|
|
v-model:active-key="activeTab"
|
|
type="line"
|
|
size="large"
|
|
@change="handleTabChange"
|
|
>
|
|
<a-tab-pane key="all" tab="全部项目" title="全部项目">
|
|
<ProjectTable
|
|
:data="filteredProjects"
|
|
:loading="loading"
|
|
@view="handleView"
|
|
@enter="handleEnter"
|
|
/>
|
|
</a-tab-pane>
|
|
<a-tab-pane key="my" tab="我的项目" title="我的项目">
|
|
<ProjectTable
|
|
:data="myProjects"
|
|
:loading="loading"
|
|
@view="handleView"
|
|
@enter="handleEnter"
|
|
/>
|
|
</a-tab-pane>
|
|
<a-tab-pane key="pending" tab="待开工项目" title="待开工项目">
|
|
<ProjectTable
|
|
:data="pendingProjects"
|
|
:loading="loading"
|
|
@view="handleView"
|
|
@enter="handleEnter"
|
|
/>
|
|
</a-tab-pane>
|
|
</a-tabs>
|
|
</div>
|
|
</div>
|
|
</GiPageLayout>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
import { Message } from '@arco-design/web-vue'
|
|
import ProjectTable from './components/ProjectTable.vue'
|
|
import type { ProjectData, TabKey } from './types'
|
|
import { ProjectStatus } from './types'
|
|
|
|
defineOptions({ name: 'ProjectList' })
|
|
|
|
// 响应式数据
|
|
const loading = ref(false)
|
|
const activeTab = ref<TabKey>('all')
|
|
const searchKeyword = ref('')
|
|
|
|
// 项目数据
|
|
const projectList = ref<ProjectData[]>([
|
|
{
|
|
id: 1,
|
|
projectName: 'A风场2023年检查',
|
|
unitCount: 15,
|
|
startDate: '2023-10-01',
|
|
endDate: '2023-12-31',
|
|
status: ProjectStatus.IN_PROGRESS,
|
|
progress: 65,
|
|
manager: '张三',
|
|
isMyProject: true
|
|
},
|
|
{
|
|
id: 2,
|
|
projectName: 'B风场维修项目',
|
|
unitCount: 8,
|
|
startDate: '2023-09-15',
|
|
endDate: '2023-11-30',
|
|
status: ProjectStatus.IN_PROGRESS,
|
|
progress: 45,
|
|
manager: '李四',
|
|
isMyProject: false
|
|
},
|
|
{
|
|
id: 3,
|
|
projectName: 'C风场年度检查',
|
|
unitCount: 20,
|
|
startDate: '2023-08-01',
|
|
endDate: '2023-10-31',
|
|
status: ProjectStatus.COMPLETED,
|
|
progress: 100,
|
|
manager: '王五',
|
|
isMyProject: true
|
|
},
|
|
{
|
|
id: 4,
|
|
projectName: 'D风场初步检查',
|
|
unitCount: 12,
|
|
startDate: '2023-11-10',
|
|
endDate: '2023-12-15',
|
|
status: ProjectStatus.NOT_STARTED,
|
|
progress: 0,
|
|
manager: '赵六',
|
|
isMyProject: false
|
|
}
|
|
])
|
|
|
|
// 计算属性 - 根据搜索关键词过滤项目
|
|
const filteredProjects = computed(() => {
|
|
if (!searchKeyword.value) {
|
|
return projectList.value
|
|
}
|
|
return projectList.value.filter(project =>
|
|
project.projectName.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
|
)
|
|
})
|
|
|
|
// 计算属性 - 我的项目
|
|
const myProjects = computed(() => {
|
|
return filteredProjects.value.filter(project => project.isMyProject)
|
|
})
|
|
|
|
// 计算属性 - 待开工项目
|
|
const pendingProjects = computed(() => {
|
|
return filteredProjects.value.filter(project => project.status === 'not_started')
|
|
})
|
|
|
|
// 搜索处理
|
|
const handleSearch = (value: string) => {
|
|
searchKeyword.value = value
|
|
}
|
|
|
|
const handleClear = () => {
|
|
searchKeyword.value = ''
|
|
}
|
|
|
|
// 选项卡切换
|
|
const handleTabChange = (key: string) => {
|
|
activeTab.value = key as TabKey
|
|
}
|
|
|
|
// 刷新数据
|
|
const refreshData = async () => {
|
|
loading.value = true
|
|
try {
|
|
// 模拟API请求
|
|
await new Promise(resolve => setTimeout(resolve, 800))
|
|
Message.success('数据已刷新')
|
|
} catch (error) {
|
|
Message.error('刷新失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 新建项目
|
|
const openAddModal = () => {
|
|
Message.info('打开新建项目对话框')
|
|
}
|
|
|
|
// 查看项目
|
|
const handleView = (project: any) => {
|
|
Message.info(`查看项目: ${project.projectName}`)
|
|
}
|
|
|
|
// 进入项目
|
|
const handleEnter = (project: any) => {
|
|
Message.info(`进入项目: ${project.projectName}`)
|
|
}
|
|
|
|
onMounted(() => {
|
|
// 初始化加载数据
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.project-list-container {
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.header-section {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 24px;
|
|
padding: 0 4px;
|
|
}
|
|
|
|
.search-area {
|
|
flex: 1;
|
|
}
|
|
|
|
.action-area {
|
|
display: flex;
|
|
gap: 12px;
|
|
align-items: center;
|
|
}
|
|
|
|
.tabs-section {
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
:deep(.arco-tabs-content) {
|
|
height: 100%;
|
|
}
|
|
|
|
:deep(.arco-tabs-pane) {
|
|
height: 100%;
|
|
}
|
|
|
|
:deep(.arco-tabs-nav-tab) {
|
|
font-weight: 500;
|
|
font-size: 16px;
|
|
}
|
|
|
|
:deep(.arco-tabs-nav-tab-list) {
|
|
padding: 0 4px;
|
|
}
|
|
|
|
// 响应式处理
|
|
@media (max-width: 768px) {
|
|
.header-section {
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.search-area {
|
|
flex: none;
|
|
}
|
|
|
|
.action-area {
|
|
justify-content: center;
|
|
}
|
|
}
|
|
</style> |