261 lines
6.1 KiB
Vue
261 lines
6.1 KiB
Vue
<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>
|