Files
cz-web/src/components/CasesSearchBar.vue
2026-10-10 09:57:56 +08:00

170 lines
3.6 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 { computed } from 'vue'
interface Props {
keyword: string
favoriteOnly: boolean
/** 是否显示「收藏列表」切换按钮(案例库显示,收藏页本身不显示) */
showFavoriteToggle?: boolean
}
const props = withDefaults(defineProps<Props>(), { showFavoriteToggle: true })
const emit = defineEmits<{
'update:keyword': [keyword: string]
search: []
reset: []
toggleFavoriteOnly: []
}>()
const keyword = computed<string>({
get: () => props.keyword,
set: (value) => emit('update:keyword', value),
})
</script>
<template>
<div class="case-search">
<div class="case-search__field">
<svg class="case-search__icon" viewBox="0 0 24 24" aria-hidden="true">
<circle cx="11" cy="11" r="7" />
<path d="m20 20-3.7-3.7" />
</svg>
<input
v-model="keyword"
class="case-search__input"
placeholder="关键字搜索"
@keyup.enter="emit('search')"
>
</div>
<button class="case-search__btn" @click="emit('reset')">
重置
</button>
<button class="case-search__btn case-search__btn--primary" @click="emit('search')">
搜索
</button>
<button
v-if="showFavoriteToggle"
class="case-search__fav"
:class="{ 'is-active': favoriteOnly }"
@click="emit('toggleFavoriteOnly')"
>
<svg class="case-search__fav-icon" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 20.5s-7.2-4.6-8.4-9A5.1 5.1 0 0 1 12 5.6a5.1 5.1 0 0 1 8.4 5.9c-1.2 4.4-8.4 9-8.4 9Z" />
</svg>
收藏列表
</button>
</div>
</template>
<style lang="less" scoped>
.case-search {
.flex(row, flex-start, center);
gap: 24px;
width: 100%;
height: 128px;
box-sizing: border-box;
// 设计稿 #31:输入框 x=653(栏左 606 + 47),重置 1305,搜索 1429
padding: 0 47px;
border-radius: @radius-base;
background: @white;
&__field {
position: relative;
// 输入框右边界 1245 → 重置按钮 1305,设计稿间距 60
margin-right: 36px;
flex: 0 0 592px;
}
&__icon {
position: absolute;
top: 50%;
right: 16px;
left: auto;
width: 27px;
height: 27px;
transform: translateY(-50%);
fill: none;
stroke: @cases-icon;
stroke-width: 1.8;
}
&__input {
width: 100%;
height: 49px;
padding: 0 52px 0 20px;
border: 1px solid @cases-input-border;
border-radius: @radius-sm;
background: @white;
color: @cases-text;
font-size: 20px;
outline: none;
transition: border-color 0.2s;
&::placeholder {
color: @text-color-disabled;
}
&:focus {
border-color: @cases-accent;
}
}
&__btn {
min-width: 100px;
height: 49px;
padding: 0 @spacing-base;
border-radius: @radius-sm;
background: @cases-accent;
color: @white;
font-size: 20px;
font-weight: 400;
transition: all 0.2s;
&:hover {
background: @primary-hover;
}
&--primary {
background: @cases-accent;
color: @white;
&:hover {
background: @primary-hover;
color: @white;
}
}
}
&__fav {
.flex(row, center);
gap: @spacing-xs;
margin-left: auto;
color: @heading-color;
font-size: 16px;
transition: color 0.2s;
&:hover,
&.is-active {
color: @primary-color;
}
&.is-active .case-search__fav-icon {
fill: @danger-color;
stroke: @danger-color;
}
&-icon {
width: 18px;
height: 18px;
fill: none;
stroke: currentColor;
stroke-width: 1.8;
transition: all 0.2s;
}
}
}
</style>