SearchHeader.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <div class="search-content com-mobile-header">
  3. <a @click="goLastPage"><i class="iconfont icon-fanhui"></i></a>
  4. <input type="text" v-model="keyword" @input="onKeywordInput()" :placeholder="placeholder" @keyup.13="onSearch()">
  5. <span @click="onSearch()"><i class="iconfont icon-sousuo"></i></span>
  6. <ul v-if="emptyStatus && type == 'supplier' && keyword && keyword !== '' && showSimilarWord">
  7. <template v-if="similarList.pBrandEn && similarList.pBrandEn.length">
  8. <li class="title text-ellipse">品牌</li>
  9. <li class="text-ellipse" v-for="brand in similarList.pBrandEn.slice(0, 4)" @click="onSearch(brand.nameEn, 'pBrandEn', $event)">{{brand.nameEn}}</li>
  10. </template>
  11. <template v-if="similarList.kind && similarList.kind.length">
  12. <li class="title text-ellipse">类目(产品名称)</li>
  13. <li class="text-ellipse" v-for="kind in similarList.kind.slice(0, 4)" @click="onSearch(kind.kind, 'kind', $event)">{{kind.kind}}</li>
  14. </template>
  15. <template v-if="similarList.pCmpCode && similarList.pCmpCode.length">
  16. <li class="title text-ellipse">型号</li>
  17. <li class="text-ellipse" v-for="code in similarList.pCmpCode.slice(0, 4)" @click="onSearch(code.pCmpCode, 'pCmpCode', $event)">{{code.pCmpCode}}</li>
  18. </template>
  19. </ul>
  20. <ul v-if="emptyStatus && type == 'default' && keyword && keyword !== '' && showSimilarWord">
  21. <template v-if="similarList.brand && similarList.brand.length && (similarType == 'all' || similarType == 'brand')">
  22. <li class="title text-ellipse" v-if="similarType == 'all'">品牌</li>
  23. <li class="text-ellipse" v-for="brand in similarList.brand.slice(0, 4)" @click="onSearch(brand.nameEn, 'brand', $event)">{{brand.nameEn}}</li>
  24. </template>
  25. <template v-if="similarList.kind && similarList.kind.length && (similarType == 'all' || similarType == 'kind')">
  26. <li class="title text-ellipse" v-if="similarType == 'all'">类目(产品名称)</li>
  27. <li class="text-ellipse" v-for="kind in similarList.kind.slice(0, 4)" @click="onSearch(kind.nameCn, 'kind', $event)">{{kind.nameCn}}</li>
  28. </template>
  29. <template v-if="similarList.component && similarList.component.length && (similarType == 'all' || similarType == 'code')">
  30. <li class="title text-ellipse" v-if="similarType == 'all'">型号</li>
  31. <li class="text-ellipse" v-for="code in similarList.component.slice(0, 4)" @click="onSearch(code.code, 'code', $event)">{{code.code}}</li>
  32. </template>
  33. </ul>
  34. </div>
  35. </template>
  36. <script>
  37. import {scrollTo} from '~utils/scroll'
  38. export default {
  39. props: {
  40. placeholder: {
  41. type: String,
  42. default: '请输入要查找的内容'
  43. },
  44. similarUrl: { // 联想词url
  45. type: String,
  46. default: '/search/similarKeywords'
  47. },
  48. type: { // 搜索类型
  49. type: String,
  50. default: 'default'
  51. },
  52. showSimilar: { // 是否显示联想词
  53. type: Boolean,
  54. default: true
  55. },
  56. outerKeyword: { // 提示keyword
  57. type: String,
  58. default: ''
  59. },
  60. similarType: { // 选择出现的联想词类型
  61. type: String,
  62. default: 'all'
  63. },
  64. useMatchRule: {
  65. type: Boolean,
  66. default: true
  67. }
  68. },
  69. data () {
  70. return {
  71. keyword: '',
  72. similarList: {},
  73. showSimilarWord: false,
  74. searchKeyword: '',
  75. clickCount: 0
  76. }
  77. },
  78. watch: {
  79. outerKeyword: {
  80. handler: function (val) {
  81. this.keyword = val
  82. },
  83. immediate: true
  84. }
  85. },
  86. mounted () {
  87. this.$nextTick(() => {
  88. document.onclick = () => {
  89. this.showSimilarWord = false
  90. }
  91. })
  92. },
  93. computed: {
  94. emptyStatus () {
  95. let similarList = this.similarList
  96. if (this.type === 'supplier') {
  97. return (similarList.pCmpCode && similarList.pCmpCode.length) ||
  98. (similarList.pBrandEn && similarList.pBrandEn.length) ||
  99. (similarList.kind && similarList.kind.length)
  100. } else if (this.type === 'default') {
  101. return (similarList.component && similarList.component.length) ||
  102. (similarList.brand && similarList.brand.length) ||
  103. (similarList.kind && similarList.kind.length)
  104. }
  105. }
  106. },
  107. methods: {
  108. onSearch: function (key, type, e) {
  109. if (e) {
  110. e.stopPropagation()
  111. }
  112. // if (key === this.searchKeyword || this.keyword === this.searchKeyword) {
  113. // return
  114. // }
  115. if (key || !this.useMatchRule) {
  116. this.keyword = key || this.keyword
  117. this.$emit('searchAction', {
  118. keyword: this.keyword,
  119. type: type
  120. })
  121. } else {
  122. let sType = null
  123. if (this.type === 'default' && this.keyword && this.keyword !== '' && this.similarList.brand) { // 防止接口报错无法搜索
  124. if (this.similarList.brand[0] && this.keyword === this.similarList.brand[0].nameEn) {
  125. sType = 'brand'
  126. } else if (this.similarList.kind[0] && this.keyword === this.similarList.kind[0].nameCn) {
  127. sType = 'kind'
  128. } else if (this.similarList.component[0] && this.keyword === this.similarList.component[0].code) {
  129. sType = 'code'
  130. } else {
  131. let arr = [...this.similarList.brand, ...this.similarList.kind, ...this.similarList.component]
  132. if (arr[0]) {
  133. if (arr[0].nameEn) {
  134. this.keyword = arr[0].nameEn
  135. sType = 'brand'
  136. } else if (arr[0].nameCn) {
  137. this.keyword = arr[0].nameCn
  138. sType = 'kind'
  139. } else if (arr[0].code) {
  140. this.keyword = arr[0].code
  141. sType = 'code'
  142. }
  143. }
  144. }
  145. } else if (this.type === 'supplier' && this.keyword && this.keyword !== '' && this.similarList.pBrandEn) { // 防止接口报错无法搜索
  146. if (this.similarList.pBrandEn[0] && this.keyword === this.similarList.pBrandEn[0].nameEn) {
  147. sType = 'pBrandEn'
  148. } else if (this.similarList.kind[0] && this.keyword === this.similarList.kind[0].kind) {
  149. sType = 'kind'
  150. } else if (this.similarList.pCmpCode[0] && this.keyword === this.similarList.pCmpCode[0].pCmpCode) {
  151. sType = 'pCmpCode'
  152. } else {
  153. let arr = [...this.similarList.pBrandEn, ...this.similarList.kind, ...this.similarList.pCmpCode]
  154. if (arr[0]) {
  155. if (arr[0].nameEn) {
  156. this.keyword = arr[0].nameEn
  157. sType = 'pBrandEn'
  158. } else if (arr[0].kind) {
  159. this.keyword = arr[0].kind
  160. sType = 'kind'
  161. } else if (arr[0].pCmpCode) {
  162. this.keyword = arr[0].pCmpCode
  163. sType = 'pCmpCode'
  164. }
  165. }
  166. }
  167. }
  168. this.$emit('searchAction', {
  169. keyword: this.keyword,
  170. type: sType
  171. })
  172. }
  173. this.searchKeyword = this.keyword
  174. scrollTo('body', 10)
  175. this.showSimilarWord = false
  176. },
  177. onKeywordInput: function () {
  178. this.clickCount ++
  179. let count = this.clickCount
  180. let timer = setTimeout(() => {
  181. this.getSimilarList(count, timer)
  182. }, 300)
  183. },
  184. getSimilarList: function (clickCount, timer) {
  185. clearTimeout(timer)
  186. if (this.showSimilar && this.keyword && this.keyword !== '' && clickCount === this.clickCount) {
  187. this.$http.get(this.similarUrl, {params: {keyword: this.keyword}}).then(
  188. res => {
  189. this.similarList = res.data
  190. this.showSimilarWord = true
  191. }
  192. )
  193. }
  194. }
  195. }
  196. }
  197. </script>
  198. <style lang="scss" scoped>
  199. .search-content {
  200. color: #333;
  201. input {
  202. margin: 0 0 0 .5rem;
  203. line-height: normal;
  204. }
  205. ul {
  206. width: 6.48rem;
  207. background: #fff;
  208. position: absolute;
  209. left: .6rem;
  210. top: .72rem;
  211. border: 1px solid #ccc;
  212. border-radius: .05rem;
  213. max-height: 4.5rem;
  214. overflow-y: auto;
  215. li {
  216. height: .6rem;
  217. line-height: .6rem;
  218. padding: 0 .1rem;
  219. font-size: .26rem;
  220. &.title {
  221. color: #666;
  222. border-bottom: 1px solid #ddd;
  223. font-weight: bold;
  224. background: #f6f5f5;
  225. }
  226. }
  227. }
  228. }
  229. </style>