PcbNavSearch.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <div class="input-group">
  3. <input v-model="keyword" type="text" class="search-input form-control"
  4. @focus.stop.prevent="onFocus()"
  5. @blur.stop.prevent="onBlur()"
  6. @keyup.40="onSelectChange(1)"
  7. @keyup.38="onSelectChange(-1)"
  8. @keyup.13="onSearch()"/>
  9. <span @click="onSearch()">
  10. <button class="btn search-btn" type="button"><span class="glyphicon glyphicon-search" aria-hidden="true"></span> </button>
  11. </span>
  12. <div class="angle"></div>
  13. <a class="close" @click="close"><img src="/images/search/search-close.png"></a>
  14. <ul class="association" v-show="showAssociate">
  15. <li v-for="(k, index) in similarKeywords.data" class="item"
  16. :class="{'active': index==associate.activeIndex}"
  17. @click.stop.prevent="onAssociateClick(k)">{{ k }}
  18. </li>
  19. </ul>
  20. </div>
  21. </template>
  22. <script>
  23. export default {
  24. name: 'search',
  25. data () {
  26. return {
  27. keyword: '',
  28. inputValue: '',
  29. select: 'product',
  30. searchType: 'product',
  31. associate: {
  32. show: false,
  33. activeIndex: null
  34. }
  35. }
  36. },
  37. computed: {
  38. similarKeywords () {
  39. return this.$store.state.search.keywords
  40. },
  41. showAssociate () {
  42. return this.associate.show && this.similarKeywords.data && this.similarKeywords.data.length
  43. },
  44. floors () {
  45. return this.$store.state.floor.list.data
  46. },
  47. bgUrl () {
  48. return this.background && this.background !== '' ? this.background : this.floors[1].items[0].pictureUrl
  49. }
  50. },
  51. watch: {
  52. 'keyword': {
  53. handler (val, oldVal) {
  54. let keywords = this.similarKeywords.data
  55. if (!keywords || !keywords.length || this.associate.activeIndex === null || val !== keywords[this.associate.activeIndex]) {
  56. this.onChange()
  57. }
  58. }
  59. }
  60. },
  61. methods: {
  62. close: function () {
  63. this.keyword = ''
  64. },
  65. onFocus () {
  66. this.associate.show = true
  67. },
  68. onBlur () {
  69. this.associate.show = false
  70. },
  71. onSelectChange (count) {
  72. let keywords = this.similarKeywords.data
  73. if (keywords && keywords.length) {
  74. let index = this.associate.activeIndex
  75. if (index === null) {
  76. index = -1
  77. }
  78. index += count
  79. if (index >= keywords.length) {
  80. index = 0
  81. } else if (index < 0) {
  82. index = keywords.length - 1
  83. }
  84. this.associate.activeIndex = index
  85. this.keyword = keywords[index]
  86. }
  87. },
  88. onChange () {
  89. this.associate.activeIndex = null
  90. if (!this.keyword) {
  91. this.associate.show = false
  92. this.$store.dispatch('resetSearchKeywords')
  93. } else {
  94. this.searchKeywords()
  95. }
  96. },
  97. searchKeywords () {
  98. this.associate.show = true
  99. this.$store.dispatch('searchKeywords', { keyword: this.keyword })
  100. },
  101. onSearch () {
  102. document.getElementsByClassName('search-input')[0].blur()
  103. if (this.keyword) {
  104. this.associate.show = false
  105. this.$store.dispatch('resetSearchKeywords')
  106. this.$router.push({path: '/pcb/search?w=' + encodeURIComponent(this.keyword)})
  107. }
  108. },
  109. onAssociateClick (word) {
  110. this.keyword = word
  111. this.onSearch()
  112. }
  113. }
  114. }
  115. </script>
  116. <style lang="scss" scoped>
  117. @import '~assets/scss/variables';
  118. .input-group {
  119. width: 540px;
  120. position: relative;
  121. }
  122. .select {
  123. font-size: 16px;
  124. color: #333;
  125. width: 70px;
  126. height: 30px;
  127. border-radius: 25px 0 0 25px;
  128. border: 1px solid #fff;
  129. float: left;
  130. padding-left: 2%;
  131. line-height: 30px;
  132. }
  133. .close {
  134. position: absolute;
  135. top: 3px;
  136. right: 55px;
  137. z-index: 1000;
  138. color: #000;
  139. }
  140. .angle {
  141. position: absolute;
  142. top: 13px;
  143. left: 52px;
  144. width: 0;
  145. height: 0;
  146. border-left: 5px solid transparent;
  147. border-right: 5px solid transparent;
  148. border-top: 5px solid #3c7cf5;
  149. &:after{
  150. content:'';
  151. position: relative;
  152. display: block;
  153. width: 3px;
  154. height: 24px;
  155. top: -15px;
  156. left: 9px;
  157. border-right: 2px solid #3c7cf5;
  158. }
  159. }
  160. .search-input {
  161. font-size: 16px;
  162. height: 30px;
  163. border-radius: 25px 0 0 25px;
  164. width: 488px !important;
  165. border: 1px solid #fff;
  166. padding-right: 25px;
  167. }
  168. .btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus {
  169. outline: none;
  170. border-color: transparent;
  171. box-shadow:none;
  172. }
  173. .search-btn {
  174. height: 30px;
  175. font-size: 22px;
  176. width: 50px;
  177. margin-left: 0;
  178. background: #fff;
  179. border: 1px solid #fff;
  180. border-radius: 0 25px 25px 0;
  181. }
  182. .glyphicon-search{
  183. color: #3c7cf5;
  184. }
  185. .association {
  186. position: absolute;
  187. background: $white;
  188. border: $border;
  189. border-top-width: 0;
  190. z-index: 21;
  191. width: 606px;
  192. top: 214px;
  193. left: 2px;
  194. .item {
  195. padding: 0 15px;
  196. line-height: 30px;
  197. cursor: pointer;
  198. text-align: left;
  199. &.active {
  200. background-color: $dark-bg;
  201. }
  202. &:hover {
  203. background-color: $grey-bg;
  204. }
  205. }
  206. }
  207. </style>