search-form.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <template>
  2. <!-- 搜索框入口 -->
  3. <wd-search
  4. :placeholder="searchPlaceholder"
  5. :hide-cancel="true"
  6. disabled
  7. @click="visible = true"
  8. />
  9. <!-- 搜索弹窗 -->
  10. <wd-popup
  11. v-model="visible"
  12. position="top"
  13. custom-style="border-radius: 0 0 24rpx 24rpx;"
  14. safe-area-inset-top
  15. @close="visible = false"
  16. >
  17. <view class="p-32rpx">
  18. <view class="mb-24rpx text-32rpx text-[#333] font-semibold">
  19. 搜索角色
  20. </view>
  21. <view class="mb-24rpx">
  22. <view class="mb-12rpx text-28rpx text-[#666]">
  23. 角色名称
  24. </view>
  25. <wd-input
  26. v-model="formData.name"
  27. placeholder="请输入角色名称"
  28. clearable
  29. />
  30. </view>
  31. <view class="mb-24rpx">
  32. <view class="mb-12rpx text-28rpx text-[#666]">
  33. 角色标识
  34. </view>
  35. <wd-input
  36. v-model="formData.code"
  37. placeholder="请输入角色标识"
  38. clearable
  39. />
  40. </view>
  41. <view class="mb-32rpx">
  42. <view class="mb-12rpx text-28rpx text-[#666]">
  43. 状态
  44. </view>
  45. <wd-radio-group v-model="formData.status" shape="button" size="medium">
  46. <wd-radio :value="-1">
  47. 全部
  48. </wd-radio>
  49. <wd-radio
  50. v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
  51. :key="dict.value"
  52. :value="dict.value"
  53. >
  54. {{ dict.label }}
  55. </wd-radio>
  56. </wd-radio-group>
  57. </view>
  58. <view class="w-full flex justify-center gap-24rpx">
  59. <wd-button class="flex-1" plain @click="handleReset">
  60. 重置
  61. </wd-button>
  62. <wd-button class="flex-1" type="primary" @click="handleSearch">
  63. 搜索
  64. </wd-button>
  65. </view>
  66. </view>
  67. </wd-popup>
  68. </template>
  69. <script lang="ts" setup>
  70. import { computed, reactive, ref, watch } from 'vue'
  71. import { getDictLabel, getIntDictOptions } from '@/hooks/useDict'
  72. import { DICT_TYPE } from '@/utils/constants'
  73. /** 搜索表单数据 */
  74. export interface SearchFormData {
  75. name?: string
  76. code?: string
  77. status: number // -1 表示全部
  78. }
  79. const props = defineProps<{
  80. searchParams?: Partial<SearchFormData> // 初始搜索参数
  81. }>()
  82. const emit = defineEmits<{
  83. 'search': [data: SearchFormData]
  84. 'reset': []
  85. }>()
  86. const visible = ref(false)
  87. /** 搜索条件 placeholder 拼接 */
  88. const searchPlaceholder = computed(() => {
  89. const conditions: string[] = []
  90. if (props.searchParams?.name) {
  91. conditions.push(`名称:${props.searchParams.name}`)
  92. }
  93. if (props.searchParams?.code) {
  94. conditions.push(`标识:${props.searchParams.code}`)
  95. }
  96. if (props.searchParams?.status !== undefined && props.searchParams.status !== -1) {
  97. conditions.push(`状态:${getDictLabel(DICT_TYPE.COMMON_STATUS, props.searchParams.status)}`)
  98. }
  99. return conditions.length > 0 ? conditions.join(' | ') : '搜索角色'
  100. })
  101. const formData = reactive<SearchFormData>({
  102. name: undefined,
  103. code: undefined,
  104. status: -1,
  105. })
  106. /** 监听弹窗打开,同步外部参数 */
  107. watch(visible, (val) => {
  108. if (val && props.searchParams) {
  109. formData.name = props.searchParams.name
  110. formData.code = props.searchParams.code
  111. formData.status = props.searchParams.status ?? -1
  112. }
  113. })
  114. /** 搜索 */
  115. function handleSearch() {
  116. visible.value = false
  117. emit('search', { ...formData })
  118. }
  119. /** 重置 */
  120. function handleReset() {
  121. formData.name = undefined
  122. formData.code = undefined
  123. formData.status = -1
  124. visible.value = false
  125. emit('reset')
  126. }
  127. </script>