150 lines
4.2 KiB
Vue
150 lines
4.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue'
|
|
import AppTabBar from '@/components/AppTabBar.vue'
|
|
import { DEFAULT_CASE_FILTER } from '@/constants/case-library'
|
|
import {
|
|
PROJECT_CATEGORIES,
|
|
PROJECT_CENTER_LIST,
|
|
} from '@/constants/project-center'
|
|
import filterIcon from '@/static/icons/icon-filter.svg'
|
|
import type { CaseFilterValues } from '@/types/case-library'
|
|
import type { ProjectCategory } from '@/types/project-center'
|
|
import { cloneCaseFilter, matchCaseFilter } from '@/utils/case-filter'
|
|
import CaseFilterPanel from '../case-library/components/CaseFilterPanel.vue'
|
|
import ProjectCenterCard from './components/ProjectCenterCard.vue'
|
|
|
|
const keyword = ref('')
|
|
const activeCategory = ref<ProjectCategory>('全部')
|
|
const projectList = ref(PROJECT_CENTER_LIST.map(item => ({ ...item })))
|
|
const filterVisible = ref(false)
|
|
const appliedFilter = ref<CaseFilterValues>(cloneCaseFilter(DEFAULT_CASE_FILTER))
|
|
|
|
const filteredProjects = computed(() => {
|
|
const text = keyword.value.trim()
|
|
|
|
return projectList.value.filter((item) => {
|
|
const matchCategory = activeCategory.value === '全部' || item.category === activeCategory.value
|
|
const matchKeyword = !text
|
|
|| item.title.includes(text)
|
|
|| item.category.includes(text)
|
|
|| item.projectNo.includes(text)
|
|
|| item.status.includes(text)
|
|
|| item.industry.includes(text)
|
|
const matchFilter = matchCaseFilter(item, appliedFilter.value)
|
|
return matchCategory && matchKeyword && matchFilter
|
|
})
|
|
})
|
|
|
|
function handleSelectCategory(category: ProjectCategory) {
|
|
activeCategory.value = category
|
|
}
|
|
|
|
function handleOpenFilter() {
|
|
filterVisible.value = true
|
|
}
|
|
|
|
function handleCloseFilter() {
|
|
filterVisible.value = false
|
|
}
|
|
|
|
function handleConfirmFilter(value: CaseFilterValues) {
|
|
appliedFilter.value = cloneCaseFilter(value)
|
|
}
|
|
|
|
function handleViewDetail(id: string) {
|
|
uni.navigateTo({
|
|
url: `/pages/project-center/detail/index?id=${encodeURIComponent(id)}`,
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<view class="project-center">
|
|
<view class="project-center__header">
|
|
<text class="project-center__title">
|
|
项目中心
|
|
</text>
|
|
|
|
<view class="project-center__search">
|
|
<image
|
|
class="project-center__search-icon"
|
|
src="/static/icons/icon-search.svg"
|
|
mode="aspectFit"
|
|
/>
|
|
<input
|
|
v-model="keyword"
|
|
class="project-center__search-input"
|
|
placeholder="搜索案例标题、描述、标签..."
|
|
placeholder-class="project-center__search-placeholder"
|
|
>
|
|
</view>
|
|
|
|
<scroll-view
|
|
class="project-center__tabs"
|
|
scroll-x
|
|
:show-scrollbar="false"
|
|
>
|
|
<view class="project-center__tabs-inner">
|
|
<text
|
|
v-for="category in PROJECT_CATEGORIES"
|
|
:key="category"
|
|
class="project-center__tab"
|
|
:class="{ 'project-center__tab--active': activeCategory === category }"
|
|
@tap="handleSelectCategory(category)"
|
|
>
|
|
{{ category }}
|
|
</text>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="project-center__toolbar">
|
|
<text class="project-center__count">
|
|
共 {{ filteredProjects.length }}
|
|
</text>
|
|
<view
|
|
class="project-center__filter"
|
|
@tap="handleOpenFilter"
|
|
>
|
|
<image
|
|
class="project-center__filter-icon"
|
|
:src="filterIcon"
|
|
mode="aspectFit"
|
|
/>
|
|
<text class="project-center__filter-text">
|
|
筛选
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<scroll-view
|
|
class="project-center__scroll"
|
|
scroll-y
|
|
:show-scrollbar="false"
|
|
>
|
|
<view class="project-center__list">
|
|
<ProjectCenterCard
|
|
v-for="item in filteredProjects"
|
|
:key="item.id"
|
|
:item="item"
|
|
@detail="handleViewDetail"
|
|
/>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<AppTabBar active="project" />
|
|
|
|
<CaseFilterPanel
|
|
:visible="filterVisible"
|
|
:cases="projectList"
|
|
:value="appliedFilter"
|
|
@close="handleCloseFilter"
|
|
@confirm="handleConfirmFilter"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import './index.scss';
|
|
</style>
|