zy-search.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <template name="zy-search">
  2. <view>
  3. <view class="search">
  4. <!-- #ifdef APP-PLUS -->
  5. <image src="../../static/zy-search/voice.svg" mode="aspectFit" @click="startRecognize()" class="voice-icon"></image>
  6. <!-- #endif -->
  7. <template v-if="isFocus">
  8. <input maxlength="20" focus type="text" value="" confirm-type="search" @confirm="searchStart()" placeholder="请输入关键词搜索" v-model.trim="searchText"/>
  9. </template>
  10. <template v-else>
  11. <input maxlength="20" type="text" value="" confirm-type="search" @confirm="searchStart()" placeholder="请输入关键词搜索" v-model.trim="searchText"/>
  12. </template>
  13. <image src="../../static/zy-search/search.svg" mode="aspectFit" @click="searchStart()" class="search-icon"></image>
  14. </view>
  15. <view :class="'s-' + theme" v-if="hList.length > 0">
  16. <view class="header">
  17. 历史记录
  18. <image src="../../static/zy-search/delete.svg" mode="aspectFit" @click="delhistory"></image>
  19. </view>
  20. <view class="list">
  21. <view v-for="(item,index) in hList" :key="index" @click="keywordsClick(item)">{{item}}</view>
  22. </view>
  23. </view>
  24. <view :class="'wanted-' + theme" v-if="showWant">
  25. <view class="header">猜你想搜的</view>
  26. <view class="list">
  27. <view v-for="(item,index) in hotList" :key="index" @click="keywordsClick(item)">{{item}}</view>
  28. </view>
  29. </view>
  30. </view>
  31. </template>
  32. <script>
  33. export default{
  34. name:"zy-search",
  35. props:{
  36. isFocus:{ //是否自动获取焦点
  37. type: Boolean,
  38. default: false
  39. },
  40. theme:{ //选择块级显示还是圆形显示
  41. type: String,
  42. default: 'block'
  43. },
  44. showWant:{ //是否展示推荐菜单
  45. type: Boolean,
  46. default: false
  47. },
  48. hotList: { //推荐列表数据
  49. type: Array,
  50. default () {
  51. return []
  52. }
  53. },
  54. speechEngine: { //语音引擎=>讯飞:iFly,百度:'baidu'
  55. type: String,
  56. default: 'baidu'
  57. }
  58. },
  59. data() {
  60. return {
  61. searchText:'', //搜索关键词
  62. hList:uni.getStorageSync('search_cache') //历史记录
  63. };
  64. },
  65. methods: {
  66. searchStart: function() { //触发搜索
  67. let _this = this;
  68. if (_this.searchText == '') {
  69. uni.showToast({
  70. title: '请输入关键字',
  71. icon: 'none',
  72. duration: 1000
  73. });
  74. }else{
  75. _this.$emit('getSearchText', _this.searchText);
  76. uni.getStorage({
  77. key:'search_cache',
  78. success(res){
  79. let list = res.data;
  80. if(list.length > 5){
  81. for(let item of list){
  82. if(item == _this.searchText){
  83. return;
  84. }
  85. }
  86. list.pop();
  87. list.unshift(_this.searchText);
  88. }else{
  89. for(let item of list){
  90. if(item == _this.searchText){
  91. return;
  92. }
  93. }
  94. list.unshift(_this.searchText);
  95. }
  96. _this.hList = list;
  97. uni.setStorage({
  98. key: 'search_cache',
  99. data: _this.hList
  100. });
  101. },
  102. fail() {
  103. _this.hList = [];
  104. _this.hList.push(_this.searchText);
  105. uni.setStorage({
  106. key: 'search_cache',
  107. data: _this.hList
  108. });
  109. _this.$emit('getSearchText', _this.searchText);
  110. }
  111. })
  112. }
  113. },
  114. keywordsClick (item) { //关键词搜索与历史搜索
  115. this.searchText = item;
  116. this.searchStart();
  117. },
  118. delhistory () { //清空历史记录
  119. this.hList = [];
  120. uni.setStorage({
  121. key: 'search_cache',
  122. data: []
  123. });
  124. },
  125. startRecognize: function() { //语音输入
  126. let _this = this;
  127. let options = {};
  128. options.engine = _this.speechEngine;
  129. options.punctuation = false; // 是否需要标点符号
  130. options.timeout = 10 * 1000;
  131. plus.speech.startRecognize(options, function(s) {
  132. _this.searchText = _this.searchText + s;
  133. });
  134. }
  135. }
  136. }
  137. </script>
  138. <style scoped>
  139. .search{
  140. width: 640upx;
  141. margin: 30upx auto 0;
  142. position: relative;
  143. input{
  144. background-color: #F7F7F7;
  145. padding: 10upx 74upx;
  146. font-size: 28upx;
  147. border-radius: 50upx;
  148. }
  149. .voice-icon{
  150. width: 36upx;
  151. height: 36upx;
  152. padding: 16upx 20upx 16upx 0;
  153. position: absolute;
  154. left: 16upx;
  155. top: 4upx;
  156. z-index: 10;
  157. }
  158. .search-icon{
  159. width: 36upx;
  160. height: 36upx;
  161. padding: 16upx 20upx 16upx 0;
  162. position: absolute;
  163. right: 0;
  164. top: -2upx;
  165. z-index: 10;
  166. }
  167. }
  168. .s-block{
  169. margin-top: 30upx;
  170. .header{
  171. font-size: 32upx;
  172. padding: 30upx;
  173. position: relative;
  174. image{
  175. width: 36upx;
  176. height: 36upx;
  177. padding: 10upx;
  178. position: absolute;
  179. right: 40upx;
  180. top: 24upx;
  181. }
  182. }
  183. .list{
  184. display: flex;
  185. flex-wrap: wrap;
  186. view{
  187. width: 50%;
  188. color: #8A8A8A;
  189. font-size: 28upx;
  190. box-sizing: border-box;
  191. text-align: center;
  192. padding: 20upx 0;
  193. border-top: 2upx solid #FFF;
  194. border-left: 2upx solid #FFF;
  195. overflow: hidden;
  196. white-space: nowrap;
  197. text-overflow: ellipsis;
  198. background-color: #F7F7F7;
  199. }
  200. }
  201. }
  202. .s-circle{
  203. margin-top: 30upx;
  204. .header{
  205. font-size: 32upx;
  206. padding: 30upx;
  207. border-bottom: 2upx solid #F9F9F9;
  208. position: relative;
  209. image{
  210. width: 36upx;
  211. height: 36upx;
  212. padding: 10upx;
  213. position: absolute;
  214. right: 40upx;
  215. top: 24upx;
  216. }
  217. }
  218. .list{
  219. display: flex;
  220. flex-wrap: wrap;
  221. padding: 0 30upx 20upx;
  222. view{
  223. padding: 8upx 30upx;
  224. margin: 20upx 30upx 0 0;
  225. font-size: 28upx;
  226. color: #8A8A8A;
  227. background-color: #F7F7F7;
  228. box-sizing: border-box;
  229. text-align: center;
  230. border-radius: 20upx;
  231. }
  232. }
  233. }
  234. .wanted-block{
  235. margin-top: 30upx;
  236. .header{
  237. font-size: 32upx;
  238. padding: 30upx;
  239. }
  240. .list{
  241. display: flex;
  242. flex-wrap: wrap;
  243. view{
  244. width: 50%;
  245. color: #8A8A8A;
  246. font-size: 28upx;
  247. box-sizing: border-box;
  248. text-align: center;
  249. padding: 20upx 0;
  250. border-top: 2upx solid #FFF;
  251. border-left: 2upx solid #FFF;
  252. background-color: #F7F7F7;
  253. overflow: hidden;
  254. white-space: nowrap;
  255. text-overflow: ellipsis;
  256. }
  257. }
  258. }
  259. .wanted-circle{
  260. margin-top: 30upx;
  261. .header{
  262. font-size: 32upx;
  263. padding: 30upx;
  264. }
  265. .list{
  266. display: flex;
  267. flex-wrap: wrap;
  268. padding: 0 30upx 20upx;
  269. view{
  270. padding: 8upx 30upx;
  271. margin: 20upx 30upx 0 0;
  272. font-size: 28upx;
  273. color: #8A8A8A;
  274. background-color: #F7F7F7;
  275. box-sizing: border-box;
  276. text-align: center;
  277. border-radius: 20upx;
  278. }
  279. }
  280. }
  281. </style>