SearchForm.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <template>
  2. <view class="search-popup-v">
  3. <u-popup v-model="showPopup" width="100%" height="100vh" mode="right" :mask="false" @close="close">
  4. <view class="search-popup-b">
  5. <view class="search-popup-h">
  6. <view class="search-popup-h-txt">
  7. <u-icon name="close" @click="showPopup=false" class="search-popup-h-icon" />
  8. </view>
  9. <u-input type="text" v-model="value" placeholder="请输入" @input="onInput" :clearable="clearable" />
  10. </view>
  11. </view>
  12. <view class="search-popup-item" v-if="showList.length>0">
  13. <view v-for="(item, index) in showList" :key="index" @tap="selectThisItem(item)"
  14. class="u-p-l-20 u-p-r-20">{{item[relationField]}}</view>
  15. </view>
  16. <view class="search-notData" v-if="showList.length<1">
  17. <view class="notData-box u-flex-col">
  18. <view class="u-flex-col notData-inner">
  19. <image :src="icon" class="iconImg"></image>
  20. <text class="notData-inner-text">{{$t('common.noData')}}</text>
  21. </view>
  22. </view>
  23. </view>
  24. </u-popup>
  25. </view>
  26. </template>
  27. <script>
  28. import resources from '@/libs/resources.js'
  29. import {
  30. getPopSelect
  31. } from '@/api/common.js'
  32. export default {
  33. props: {
  34. interfaceId: {
  35. type: String,
  36. default: ''
  37. },
  38. clearable: {
  39. type: Boolean,
  40. default: true
  41. },
  42. relationField: {
  43. type: String,
  44. default: 'fullName'
  45. },
  46. total: {
  47. type: [String, Number],
  48. default: 50
  49. },
  50. formData: {
  51. type: Object
  52. },
  53. templateJson: {
  54. type: Array,
  55. default: () => []
  56. },
  57. rowIndex: {
  58. default: null
  59. },
  60. },
  61. data() {
  62. return {
  63. istQuery: {
  64. keyword: '',
  65. pageSize: 1000
  66. },
  67. icon: resources.message.nodata,
  68. showPopup: false,
  69. value: '',
  70. showList: [],
  71. timer: ''
  72. }
  73. },
  74. methods: {
  75. init(val) {
  76. this.showPopup = true
  77. this.value = val
  78. this.getDataInterfaceList()
  79. },
  80. getDataInterfaceList() {
  81. this.showList = []
  82. const paramList = this.getParamList()
  83. let query = {
  84. interfaceId: this.interfaceId,
  85. relationField: this.relationField,
  86. pageSize: 10000,
  87. paramList
  88. }
  89. getPopSelect(this.interfaceId, query).then(res => {
  90. let list = JSON.parse(JSON.stringify(res.data.list)) || []
  91. if (list.length) list = this.unique(list, this.relationField)
  92. this.showList = list.splice(0, this.total)
  93. })
  94. },
  95. unique(arr, attrName) {
  96. const res = new Map();
  97. // 根据对象的某个属性值去重
  98. return arr.filter(o => !res.has(o[attrName]) && res.set(o[attrName], 1));
  99. },
  100. getParamList() {
  101. let templateJson = this.templateJson
  102. for (let i = 0; i < templateJson.length; i++) {
  103. if (templateJson[i].relationField && this.formData && templateJson[i].sourceType == 1) {
  104. if (templateJson[i].relationField.includes('-')) {
  105. let tableVModel = templateJson[i].relationField.split('-')[0]
  106. let childVModel = templateJson[i].relationField.split('-')[1]
  107. templateJson[i].defaultValue = this.formData[tableVModel] && this.formData[tableVModel][this
  108. .rowIndex
  109. ] && this.formData[tableVModel][this.rowIndex][childVModel] || ''
  110. } else {
  111. templateJson[i].defaultValue = this.formData[templateJson[i].relationField] || ''
  112. }
  113. }
  114. if (templateJson[i].relationField == '@keyword') templateJson[i].defaultValue = this.value
  115. }
  116. return templateJson
  117. },
  118. onInput(e) {
  119. this.value = e
  120. this.$emit('confirm', this.value);
  121. this.timer && clearTimeout(this.timer);
  122. this.timer = setTimeout(() => {
  123. this.list = [];
  124. this.getDataInterfaceList()
  125. }, 300);
  126. },
  127. close() {
  128. this.showPopup = false
  129. },
  130. selectThisItem(item) {
  131. this.value = item[this.relationField];
  132. this.$emit('confirm', this.value);
  133. this.close()
  134. }
  135. }
  136. }
  137. </script>
  138. <style lang="scss">
  139. .search-popup-v {
  140. .search-popup-b {
  141. height: 158rpx;
  142. .search-popup-h {
  143. padding: 0 20rpx;
  144. border-bottom: 1rpx solid #cbcbcb;
  145. position: fixed;
  146. width: 100%;
  147. background-color: #fff;
  148. z-index: 9;
  149. text-align: center;
  150. .search-popup-h-txt {
  151. height: 86rpx;
  152. width: 100%;
  153. padding: 15rpx 0;
  154. text-align: center;
  155. line-height: 54rpx;
  156. box-sizing: border-box;
  157. font-size: 32rpx;
  158. font-weight: 700;
  159. letter-spacing: 2rpx;
  160. .search-popup-h-icon {
  161. float: right;
  162. margin-top: 12rpx;
  163. }
  164. }
  165. }
  166. }
  167. .search-popup-item {
  168. width: 100%;
  169. height: 100%;
  170. z-index: 9997;
  171. }
  172. .search-notData {
  173. width: 100%;
  174. height: calc(100% - 160rpx);
  175. background-color: #fff;
  176. .notData-box {
  177. width: 100%;
  178. height: 100%;
  179. justify-content: center;
  180. align-items: center;
  181. .notData-inner {
  182. width: 280rpx;
  183. height: 340rpx;
  184. align-items: center;
  185. .iconImg {
  186. width: 100%;
  187. height: 100%;
  188. }
  189. .notData-inner-text {
  190. padding: 30rpx 0;
  191. color: #909399;
  192. }
  193. }
  194. }
  195. }
  196. }
  197. </style>