feat 搭建架构骨架
This commit is contained in:
162
src/components/FilterPanel.vue
Normal file
162
src/components/FilterPanel.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<script setup lang="ts">
|
||||
export interface FilterChip {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
chips?: FilterChip[]
|
||||
keywordPlaceholder?: string
|
||||
searchLabel?: string
|
||||
showResultCount?: boolean
|
||||
resultCount?: number
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
chips: () => [],
|
||||
keywordPlaceholder: '关键字搜索',
|
||||
searchLabel: '搜索',
|
||||
showResultCount: false,
|
||||
resultCount: 0,
|
||||
})
|
||||
|
||||
const keyword = defineModel<string>('keyword', { default: '' })
|
||||
|
||||
const emit = defineEmits<{
|
||||
search: []
|
||||
reset: []
|
||||
removeChip: [key: string]
|
||||
clearChips: []
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="filter-panel">
|
||||
<div class="filter-panel__bar">
|
||||
<input
|
||||
v-model="keyword"
|
||||
class="filter-panel__input"
|
||||
:placeholder="keywordPlaceholder"
|
||||
@keyup.enter="emit('search')"
|
||||
>
|
||||
<button class="filter-panel__btn filter-panel__btn--primary" @click="emit('search')">
|
||||
{{ searchLabel }}<template v-if="showResultCount">({{ resultCount }}个结果)</template>
|
||||
</button>
|
||||
<button class="filter-panel__btn" @click="emit('reset')">
|
||||
重置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="chips.length > 0" class="filter-panel__chips">
|
||||
<span class="filter-panel__chips-label text-secondary">已选条件({{ chips.length }}个)</span>
|
||||
<button
|
||||
v-for="chip in chips"
|
||||
:key="chip.key"
|
||||
class="filter-panel__chip"
|
||||
:title="`移除 ${chip.label}`"
|
||||
@click="emit('removeChip', chip.key)"
|
||||
>
|
||||
{{ chip.label }} ×
|
||||
</button>
|
||||
<button class="filter-panel__chip filter-panel__chip--clear" @click="emit('clearChips')">
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="filter-panel__body">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.filter-panel {
|
||||
padding: @spacing-base @spacing-lg;
|
||||
border-radius: @radius-lg;
|
||||
background: @white;
|
||||
box-shadow: @shadow-base;
|
||||
|
||||
&__bar {
|
||||
.flex(row, flex-start);
|
||||
gap: @spacing-sm;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 240px;
|
||||
height: 34px;
|
||||
padding: 0 @spacing-base;
|
||||
border: 1px solid @border-color;
|
||||
border-radius: @radius-base;
|
||||
background: @bg-color-light;
|
||||
font-size: @font-size-base;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__btn {
|
||||
height: 34px;
|
||||
padding: 0 @spacing-base;
|
||||
border: 1px solid @border-color-dark;
|
||||
border-radius: @radius-base;
|
||||
background: @white;
|
||||
color: @text-color;
|
||||
font-size: @font-size-base;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
border-color: @primary-color;
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
border-color: @primary-color;
|
||||
background: @primary-color;
|
||||
color: @white;
|
||||
|
||||
&:hover {
|
||||
background: @primary-hover;
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__chips {
|
||||
.flex(row, flex-start, center);
|
||||
flex-wrap: wrap;
|
||||
gap: @spacing-sm;
|
||||
margin-top: @spacing-base;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
&__chip {
|
||||
height: 26px;
|
||||
padding: 0 @spacing-sm;
|
||||
border: 1px solid @primary-light;
|
||||
border-radius: @radius-round;
|
||||
background: @primary-light;
|
||||
color: @primary-color;
|
||||
font-size: @font-size-sm;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
&--clear {
|
||||
border-color: @border-color;
|
||||
background: @white;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
margin-top: @spacing-base;
|
||||
.flex(column, flex-start);
|
||||
gap: @spacing-base;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user