| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <template>
- <div class="page_search" >
- <ul class=" search_content ">
- <template v-for="item in props.searchList" :key="item.key">
- <!-- v-for="item in props.searchList" :key="item.key" -->
- <li class="content_left" v-if="!item.hidden">
- <template v-if="item.type=='single'">
- <span class="label">{{ item.label }}:</span>
- <div class="search_option">
- <span
- v-for="categoryItem in item.options"
- :key="categoryItem?.value"
- @click="HandleBtnSearchItemChange(item.key,categoryItem?.value)"
- :class="[{'active':categoryItem?.value == buttonSearchData[item.key]}]"
- >
- {{ categoryItem?.label }}
- <!-- && categoryItem.value == buttonSearchData[item.key] -->
- <span v-if="categoryItem?.bubbleVal" class="bubble">{{ categoryItem?.bubbleVal }}</span>
- </span>
-
- <slot :name="'rowItem-'+item.key"></slot>
- </div>
- <div>
- <slot :name="item.key"></slot>
- </div>
- </template>
- <template v-else-if="item.type == 'form'">
- <span v-if="item.label" class="label" style="line-height: 36px !important;">{{ item.label }}:</span>
- <FormSearchGroup :searchList="item.searchFormItems" @searchChange="(params,key)=>HandleSearchChange(params,key)"/>
- </template>
- </li>
- </template>
- </ul>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref, watch } from 'vue'
- import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
- interface Options {
- label:String,
- value:String,
- bubbleVal?:String,
- }
- interface searchFormItem {
- key:String,
- type:'select'|'input' ,
- placeholder?:String,
- options?:Options,
- defaultValue?:String,
- }
- interface SearchBlockItem {
- label:String,
- key:String,
- type:'form' | 'single',
- searchFormItems?:Array<searchFormItem>,
- options?:Array<Options>,
- defaultValue?:String,
- hidden?:Boolean
- }
- const props = defineProps({
- searchList:{
- required:true,
- type:Array<SearchBlockItem>
- }
- })
- const emit = defineEmits(['searchChange'])
- const formSearchData = ref({})
- const buttonSearchData = ref({})
- const HandleSearchChange = (params,key)=>{
- formSearchData.value = params
- emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
- }
- const HandleBtnSearchItemChange = (key,val)=>{
- console.log('按钮触发')
- buttonSearchData.value[key] = val
- emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
- }
- // 只做初始化,不传递数据,初始数据传递的触发要等子组件触发,
- // 带form表单的要等 子组件触发
- // 不带form表单的要自己触发
- watch(()=>props.searchList,(newVal)=>{
- // console.log('watch触发')
- buttonSearchData.value = {}
- newVal.forEach(item=>{
- if(item.type == 'single'){
- if(item.defaultValue || item.defaultValue === 0){
- buttonSearchData.value[item.key] = item.defaultValue
- }
- }
- // else if(item.type == 'form'){
- // //
- // // formSearchData.value[item.key]
- // }
- })
- /*
- let findRes = newVal.find(item=>item.type == 'form')
- if(!findRes){
- // 判断是否有form表单的信息,如果没有,则自己触发
- emit('searchChange',{...formSearchData.value,...buttonSearchData.value})
- }
- */
- },{
- immediate:true,
- deep:true,
- })
- </script>
- <style lang="scss" scoped>
- .search_content{
- display: flex;
- flex-direction: column;
- gap:16px;
- li.content_left{
- width: 100% !important;
- display: flex;
- gap:8px !important;
- font-size: 14px;
- align-items: flex-start;
- line-height: 28px !important;
- :deep(.el-button) img{
- width: 16px;
- height: 16px;
- margin-right: 4px;
- vertical-align: middle;
- /* 使图标垂直居中 */
- }
- .label{
- font-weight: bold;
- }
- .search_option{
- display: flex;
- gap: 8px;
- flex-wrap: wrap;
- align-items: center;
- flex:1 1;
- span{
- position: relative;
- .bubble{
- padding:1px 2px;
- background-color: #F56C6C;
- border-radius: 50%;
- min-width: 20px;
- height: 20px;
- text-align: center;
- font-size: 12px;
- color: white;
- position: absolute;
- top:-4px;
- }
- line-height: 20px;
- padding:4px 8px;
- font-size: 14px;
- color:#999;
- border-radius: 4px;
- &:hover{
- cursor: pointer;
- }
- &.active{
- background-color: rgba(71, 113, 203,0.1);
- color:#2E64FA;
- }
- }
- }
- .simple_filter{
- flex:1 1;
- }
- }
-
-
- }
- </style>
|