Files
cz-web/src/views/home/cpns/HomeCaseShowcase.vue
2026-09-30 15:55:36 +08:00

261 lines
6.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref } from 'vue'
import { formatBusinessType } from '@/utils/format'
import type { BusinessType } from '@/types/api'
import type { Case } from '@/types/business/cases'
interface Props {
cases: Case[]
}
defineProps<Props>()
const emit = defineEmits<{ categoryChange: [category: BusinessType | 'all'] }>()
const activeCategory = ref<BusinessType | 'all'>('all')
const categories: Array<{ label: string; value: BusinessType | 'all' }> = [
{ label: '全部', value: 'all' },
{ label: '互联网软件', value: 'internet' },
{ label: '硬件电路', value: 'hardware' },
{ label: '物联网全案', value: 'iot' },
{ label: '生产制造', value: 'manufacturing' },
]
function switchCategory(value: BusinessType | 'all'): void {
activeCategory.value = value
emit('categoryChange', value)
}
</script>
<template>
<section class="home-cases">
<div class="home-cases__head">
<h3 class="home-cases__title">
案例库精选
</h3>
<div class="home-cases__tabs">
<button
v-for="cat in categories"
:key="cat.value"
class="home-cases__tab"
:class="{ 'is-active': activeCategory === cat.value }"
@click="switchCategory(cat.value)"
>
{{ cat.label }}
</button>
</div>
<RouterLink to="/cases" class="home-cases__more link">
查看全部 >
</RouterLink>
</div>
<div class="home-cases__grid">
<article
v-for="item in cases"
:key="item.id"
class="home-cases__card"
@click="$router.push(`/cases/${item.id}`)"
>
<div class="home-cases__cover">
<!-- TODO(蓝湖): 替换案例封面切图 -->
<img v-if="item.cover" v-lazy="item.cover" class="home-cases__img" :alt="item.title">
<div v-else class="home-cases__img home-cases__img--placeholder" />
<span class="home-cases__tag" :class="`home-cases__tag--${item.category}`">
{{ formatBusinessType(item.category) }}
</span>
</div>
<div class="home-cases__body">
<h4 class="home-cases__name">
{{ item.title }}
</h4>
<ul class="home-cases__meta">
<li>客户对象:{{ item.clientType }}</li>
<li>研发周期:{{ item.duration }}</li>
<li>团队规模:{{ item.teamSize }}人</li>
<li>完成时间:{{ item.finishDate }}</li>
</ul>
<span class="home-cases__view">查看详情</span>
</div>
</article>
</div>
</section>
</template>
<style lang="less" scoped>
.home-cases {
// 设计稿区块卡 1680×446 设计px:白底 + #E2E2E2 描边(内容区内左右缩 50 设计px)
max-width: 1294px;
margin-right: auto;
margin-left: auto;
padding: 32px 54px 44px;
border: 1px solid @home-section-border;
border-radius: @radius-lg;
background: @white;
&__head {
.flex(row, flex-start);
gap: 20px;
margin-bottom: 36px;
}
&__title {
// 设计稿栏目标题 36 设计px / 700 / #121212
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__tabs {
.flex(row, center);
// 设计稿分类紧跟标题左侧排布(间距 36 设计px ≈ 28)
gap: 28px;
}
&__tab {
position: relative;
height: auto;
padding: 0;
border: 0;
background: transparent;
// 设计稿分类 16 设计px / 500 / #121212(激活 #085DFF + 下划线)
color: @home-ink;
font-size: @font-size-sm;
font-weight: 500;
transition: color 0.2s;
&.is-active {
background: transparent;
color: @home-tab-active;
// 设计稿激活下划线 29×2 设计px(#1F67EF)
&::after {
content: '';
position: absolute;
right: 0;
bottom: -6px;
left: 0;
height: 2px;
background: @primary-color;
}
}
}
&__more {
margin-left: auto;
font-size: @font-size-sm;
}
&__grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
// 设计稿案例卡间距 24 设计px ≈ 18 CSS
gap: 18px;
}
&__card {
overflow: hidden;
// 设计稿案例卡 368×248 设计px:白底 + #E0DEDE 描边 + 0 4 10 黑 8% 投影
border: 1px solid @home-case-border;
border-radius: @radius-base;
background: @white;
box-shadow: 0 4px 10px fade(@black, 8%);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
box-shadow: 0 6px 14px fade(@black, 12%);
transform: translateY(-2px);
.home-cases__view {
color: @primary-color;
}
}
}
&__cover {
position: relative;
// 设计稿封面区 128 设计px 高 ≈ 99 CSS
height: 100px;
overflow: hidden;
}
&__img {
width: 100%;
height: 100%;
object-fit: cover;
&--placeholder {
background: linear-gradient(135deg, @primary-light, @bg-color);
}
}
&__tag {
position: absolute;
top: @spacing-sm;
left: @spacing-sm;
padding: 2px @spacing-sm;
border-radius: @radius-sm;
background: @primary-color;
color: @white;
font-size: 11px;
&--hardware {
background: @tag-hardware;
}
&--iot {
background: @tag-iot;
}
&--manufacturing {
background: @tag-manufacturing;
}
&--other {
background: @tag-other;
}
}
&__body {
padding: 12px 15px 6px;
}
&__name {
margin-bottom: 8px;
// 设计稿案例名 16 设计px / 500 / #333333
font-size: @font-size-sm;
font-weight: 500;
color: @home-body;
.multi-ellipsis(1);
}
&__meta {
display: grid;
grid-template-columns: 1fr 1fr;
// 设计稿元信息 10 设计px → 可读下限 11px / #333333
gap: 3px @spacing-sm;
font-size: 11px;
line-height: 1.5;
color: @home-body;
li {
.ellipsis();
}
}
&__view {
display: block;
width: fit-content;
margin: 10px 0 0 auto;
padding: 0;
border: 0;
// 设计稿「查看详情>」12 设计px / #024FFF(无按钮描边)
color: @primary-strong;
font-size: @font-size-sm;
transition: color 0.2s;
}
}
</style>