SearchBlock.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <template>
  2. <div class="page_search" >
  3. <ul class=" search_content ">
  4. <template v-for="item in props.searchList" :key="item.key">
  5. <!-- v-for="item in props.searchList" :key="item.key" -->
  6. <li class="content_left" v-if="!item.hidden">
  7. <template v-if="item.type=='single'">
  8. <span class="label">{{ item.label }}:</span>
  9. <div class="search_option">
  10. <span
  11. v-for="categoryItem in item.options"
  12. :key="categoryItem?.value"
  13. @click="HandleBtnSearchItemChange(item.key,categoryItem?.value)"
  14. :class="[{'active':categoryItem?.value == buttonSearchData[item.key]}]"
  15. >
  16. {{ categoryItem?.label }}
  17. <!-- && categoryItem.value == buttonSearchData[item.key] -->
  18. <span v-if="categoryItem?.bubbleVal" class="bubble">{{ categoryItem?.bubbleVal }}</span>
  19. </span>
  20. <slot :name="'rowItem-'+item.key"></slot>
  21. </div>
  22. <div>
  23. <slot :name="item.key"></slot>
  24. </div>
  25. </template>
  26. <template v-else-if="item.type == 'form'">
  27. <span v-if="item.label" class="label" style="line-height: 36px !important;">{{ item.label }}:</span>
  28. <FormSearchGroup :searchList="item.searchFormItems" @searchChange="(params,key)=>HandleSearchChange(params,key)"/>
  29. </template>
  30. </li>
  31. </template>
  32. </ul>
  33. </div>
  34. </template>
  35. <script lang="ts" setup>
  36. import { ref, watch } from 'vue'
  37. import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
  38. interface Options {
  39. label:String,
  40. value:String,
  41. bubbleVal?:String,
  42. }
  43. interface searchFormItem {
  44. key:String,
  45. type:'select'|'input' ,
  46. placeholder?:String,
  47. options?:Options,
  48. defaultValue?:String,
  49. }
  50. interface SearchBlockItem {
  51. label:String,
  52. key:String,
  53. type:'form' | 'single',
  54. searchFormItems?:Array<searchFormItem>,
  55. options?:Array<Options>,
  56. defaultValue?:String,
  57. hidden?:Boolean
  58. }
  59. const props = defineProps({
  60. searchList:{
  61. required:true,
  62. type:Array<SearchBlockItem>
  63. }
  64. })
  65. const emit = defineEmits(['searchChange'])
  66. const formSearchData = ref({})
  67. const buttonSearchData = ref({})
  68. const HandleSearchChange = (params,key)=>{
  69. formSearchData.value = params
  70. emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
  71. }
  72. const HandleBtnSearchItemChange = (key,val)=>{
  73. console.log('按钮触发')
  74. buttonSearchData.value[key] = val
  75. emit('searchChange',{...formSearchData.value,...buttonSearchData.value},key)
  76. }
  77. // 只做初始化,不传递数据,初始数据传递的触发要等子组件触发,
  78. // 带form表单的要等 子组件触发
  79. // 不带form表单的要自己触发
  80. watch(()=>props.searchList,(newVal)=>{
  81. // console.log('watch触发')
  82. buttonSearchData.value = {}
  83. newVal.forEach(item=>{
  84. if(item.type == 'single'){
  85. if(item.defaultValue || item.defaultValue === 0){
  86. buttonSearchData.value[item.key] = item.defaultValue
  87. }
  88. }
  89. // else if(item.type == 'form'){
  90. // //
  91. // // formSearchData.value[item.key]
  92. // }
  93. })
  94. /*
  95. let findRes = newVal.find(item=>item.type == 'form')
  96. if(!findRes){
  97. // 判断是否有form表单的信息,如果没有,则自己触发
  98. emit('searchChange',{...formSearchData.value,...buttonSearchData.value})
  99. }
  100. */
  101. },{
  102. immediate:true,
  103. deep:true,
  104. })
  105. </script>
  106. <style lang="scss" scoped>
  107. .search_content{
  108. display: flex;
  109. flex-direction: column;
  110. gap:16px;
  111. li.content_left{
  112. width: 100% !important;
  113. display: flex;
  114. gap:8px !important;
  115. font-size: 14px;
  116. align-items: flex-start;
  117. line-height: 28px !important;
  118. :deep(.el-button) img{
  119. width: 16px;
  120. height: 16px;
  121. margin-right: 4px;
  122. vertical-align: middle;
  123. /* 使图标垂直居中 */
  124. }
  125. .label{
  126. font-weight: bold;
  127. }
  128. .search_option{
  129. display: flex;
  130. gap: 8px;
  131. flex-wrap: wrap;
  132. align-items: center;
  133. flex:1 1;
  134. span{
  135. position: relative;
  136. .bubble{
  137. padding:1px 2px;
  138. background-color: #F56C6C;
  139. border-radius: 50%;
  140. min-width: 20px;
  141. height: 20px;
  142. text-align: center;
  143. font-size: 12px;
  144. color: white;
  145. position: absolute;
  146. top:-4px;
  147. }
  148. line-height: 20px;
  149. padding:4px 8px;
  150. font-size: 14px;
  151. color:#999;
  152. border-radius: 4px;
  153. &:hover{
  154. cursor: pointer;
  155. }
  156. &.active{
  157. background-color: rgba(71, 113, 203,0.1);
  158. color:#2E64FA;
  159. }
  160. }
  161. }
  162. .simple_filter{
  163. flex:1 1;
  164. }
  165. }
  166. }
  167. </style>