You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
8.2 KiB

3 months ago
  1. <template>
  2. <!-- 搜索框 -->
  3. <view>
  4. <view class="mp-header">
  5. <!-- #ifdef MP || APP-PLUS -->
  6. <view class="sys-head tui-skeleton" :style="{ height: `${isSmallPage?0:statusBarHeight}px` }"></view>
  7. <!-- #endif -->
  8. <!-- #ifdef APP -->
  9. <view class="serch-box tui-skeleton" :style="[boxStyle]" style="height: 43px;">
  10. <!-- #endif -->
  11. <!-- #ifndef APP -->
  12. <view class="serch-box tui-skeleton" :style="[boxStyle]">
  13. <!-- #endif -->
  14. <view class="serch-wrapper flex">
  15. <view v-if="logoConfig" class="logo skeleton-rect">
  16. <image :src="logoUrl" mode=""></image>
  17. </view>
  18. <navigator :style="[contentStyle]" v-if="hotWords.length > 0"
  19. :url="'/pages/goods/goods_search/index?searchVal='+searchVal"
  20. :class="logoConfig&&!isSmallPage ? 'input' : logoConfig&&isSmallPage?'uninput':!logoConfig&&!isSmallPage?'uninput':'maxInput'" hover-class="none" class=" input skeleton-rect">
  21. <view class='swiperTxt'>
  22. <swiper :indicator-dots="indicatorDots" :autoplay="autoplay" :interval="interval"
  23. :duration="duration" vertical="true" circular="true" @change="textChange">
  24. <block v-for="(item,index) in hotWords" :key='index'>
  25. <swiper-item catchtouchmove='catchTouchMove'>
  26. <view class='acea-row row-between-wrapper'>
  27. <view class='text'>
  28. <view class='newsTitle line1'><text class="iconfont icon-sousuo"></text><text>{{item.val}}</text></view>
  29. </view>
  30. </view>
  31. </swiper-item>
  32. </block>
  33. </swiper>
  34. </view>
  35. </navigator>
  36. <navigator :style="[contentStyle]" hover-class="none" v-else url="/pages/goods/goods_search/index"
  37. :class="logoConfig&&!isSmallPage ? 'input' : logoConfig&&isSmallPage?'uninput':!logoConfig&&!isSmallPage?'uninput':'maxInput'" class="skeleton-rect">
  38. <text class="line1">{{placeWords}}</text>
  39. <text class="iconfont icon-xiazai5"></text>
  40. </navigator>
  41. </view>
  42. </view>
  43. </view>
  44. <view :style="'height:'+marTop+'px;'"></view>
  45. </view>
  46. </template>
  47. <script>
  48. // +----------------------------------------------------------------------
  49. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  50. // +----------------------------------------------------------------------
  51. // | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
  52. // +----------------------------------------------------------------------
  53. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  54. // +----------------------------------------------------------------------
  55. // | Author: CRMEB Team <admin@crmeb.com>
  56. // +----------------------------------------------------------------------
  57. let app = getApp();
  58. export default {
  59. name: 'headerSerch',
  60. props: {
  61. dataConfig: {
  62. type: Object,
  63. default: () => {}
  64. },
  65. //是否为微页面
  66. isSmallPage: {
  67. type: Boolean,
  68. default: false
  69. },
  70. //是否开始滚动
  71. isScrolled: {
  72. type: Boolean,
  73. default: false
  74. },
  75. },
  76. data() {
  77. return {
  78. statusBarHeight: app.globalData.statusBarHeight,
  79. indicatorDots: false,
  80. autoplay: true,
  81. duration: 500,
  82. marTop: 0,
  83. searchH: 0,
  84. searchVal: '',
  85. searchTop:0,
  86. searchRight:0,
  87. searchHeight:0,
  88. statusWidth:0,
  89. searchBoxHeight:0
  90. };
  91. },
  92. computed: {
  93. //轮播切换时间
  94. interval(){
  95. return this.dataConfig.titleConfig.val * 1000
  96. },
  97. //判断logo图是否展示
  98. logoConfig() {
  99. return this.dataConfig.logoConfig.url && this.dataConfig.searConfig.tabVal === 1
  100. },
  101. //logo图
  102. logoUrl() {
  103. if(this.isScrolled&&this.dataConfig.logoFixConfig.url){
  104. return this.dataConfig.logoFixConfig.url
  105. }else{
  106. return this.dataConfig.logoConfig.url
  107. }
  108. },
  109. //最外层盒子的样式
  110. boxStyle() {
  111. return {
  112. borderRadius: this.dataConfig.bgStyle.val * 2 + 'rpx',
  113. background: `linear-gradient(${this.dataConfig.bgColor.color[0].item}, ${this.dataConfig.bgColor.color[1].item})`,
  114. margin: 0 + ' ' + this.dataConfig.lrConfig.val * 2 + 'rpx' +
  115. ' ' + 0,
  116. // #ifdef MP
  117. height:this.searchBoxHeight + 'px',
  118. // #endif
  119. }
  120. },
  121. //搜索热词
  122. hotWords() {
  123. return this.dataConfig.hotWords.list
  124. },
  125. //内容圆角
  126. contentStyle() {
  127. return {
  128. borderRadius: this.dataConfig.contentStyle.val ? this.dataConfig.contentStyle.val + 'px' : '0',
  129. background: this.dataConfig.borderColor.color[0].item,
  130. color: this.dataConfig.textColor.color[0].item,
  131. textAlign: this.dataConfig.textPosition.list[this.dataConfig.textPosition.tabVal].style,
  132. // #ifdef MP
  133. height:this.searchHeight + 'px',
  134. flex:!this.isSmallPage?1:'',
  135. marginRight:!this.isSmallPage?(this.statusWidth + this.searchRight+'px'):'',
  136. // #endif
  137. }
  138. },
  139. //搜索提示语
  140. placeWords(){
  141. return this.dataConfig.placeWords.val;
  142. }
  143. },
  144. mounted() {
  145. // 使用nextTick,确保页面更新结束后,再请求高度
  146. // #ifdef MP || APP-PLUS
  147. this.$nextTick(() => {
  148. setTimeout(() => {
  149. // 获取小程序头部高度
  150. let info = uni.createSelectorQuery().in(this).select(".serch-box");
  151. info.boundingClientRect((data)=> {
  152. this.marTop = this.isSmallPage ? data.height :data.height + this.statusBarHeight
  153. }).exec()
  154. }, 100)
  155. })
  156. // #endif
  157. // #ifdef MP
  158. const res = uni.getMenuButtonBoundingClientRect()
  159. const statusHeight = res.top //胶囊距离顶部
  160. const statusRight = res.right //胶囊右边界坐标
  161. const jnHeight = res.height //胶囊高度
  162. this.statusWidth= res.width
  163. this.searchTop=statusHeight-this.statusBarHeight
  164. this.searchHeight=jnHeight
  165. this.searchBoxHeight = this.searchTop*2 + jnHeight
  166. //搜索框宽度计算
  167. uni.getSystemInfo({
  168. success:res=>{
  169. this.searchRight=res.windowWidth-statusRight-this.dataConfig.lrConfig.val
  170. }
  171. })
  172. // #endif
  173. // #ifdef H5
  174. this.marTop = 43
  175. // #endif
  176. },
  177. methods: {
  178. textChange(e) {
  179. let {
  180. current,
  181. source
  182. } = e.detail;
  183. if (source === 'autoplay' || source === 'touch') {
  184. this.searchVal = this.hotWords[e.detail.current]['val'];
  185. }
  186. },
  187. }
  188. }
  189. </script>
  190. <style lang="scss" scoped>
  191. .ml40 {
  192. margin-left: 40rpx;
  193. }
  194. .sys-head{
  195. background: #f5f5f5;
  196. }
  197. .header {
  198. width: 100%;
  199. background: #ffffff;
  200. .btn {
  201. position: relative;
  202. .iconfont {
  203. font-size: 45rpx;
  204. }
  205. }
  206. .iconnum {
  207. min-width: 6px;
  208. color: #fff;
  209. border-radius: 15rpx;
  210. position: absolute;
  211. right: -10rpx;
  212. top: -10rpx;
  213. font-size: 10px;
  214. padding: 0 4px;
  215. }
  216. .serch-wrapper {
  217. align-items: center;
  218. padding: 20rpx 24rpx 20rpx 24rpx;
  219. .logo {
  220. width: 152rpx;
  221. height: 60rpx;
  222. }
  223. }
  224. }
  225. .swiperTxt {
  226. width: 100%;
  227. height: 100%;
  228. line-height: 58rpx;
  229. overflow: hidden;
  230. }
  231. .swiperTxt .text {
  232. width: 100%;
  233. }
  234. .swiperTxt .text .label {
  235. font-size: 20rpx;
  236. color: #ff4c48;
  237. width: 64rpx;
  238. height: 30rpx;
  239. border-radius: 40rpx;
  240. text-align: center;
  241. line-height: 28rpx;
  242. border: 2rpx solid #ff4947;
  243. }
  244. .swiperTxt .text .newsTitle {
  245. // width: 300rpx;
  246. font-size: 24rpx;
  247. // text-align: center;
  248. /* #ifdef MP */
  249. // width: 260rpx !important;
  250. /* #endif */
  251. }
  252. .swiperTxt swiper {
  253. height: 100%;
  254. }
  255. .mp-header {
  256. z-index: 90;
  257. position: fixed;
  258. left: 0;
  259. top: 0;
  260. width: 100%;
  261. .logo {
  262. line-height: 0;
  263. }
  264. .serch-wrapper {
  265. height: 100%;
  266. align-items: center;
  267. padding: 20rpx 30rpx;
  268. image {
  269. width: 152rpx;
  270. height: 60rpx;
  271. margin-right: 20rpx;
  272. }
  273. .input,
  274. .uninput {
  275. display: flex;
  276. align-items: center;
  277. /* #ifdef MP*/
  278. width: 50%;
  279. /* #endif */
  280. /* #ifdef H5 || APP*/
  281. width: 100%;
  282. flex: 1;
  283. /* #endif */
  284. height: 58rpx;
  285. line-height: 58rpx;
  286. padding: 0 20rpx 0 54rpx;
  287. background: rgba(0, 0, 0, 0.22);
  288. border: 1px solid #E4E4E4;
  289. border-radius: 29rpx;
  290. color: #fff;
  291. font-size: 28rpx;
  292. position: relative;
  293. box-sizing: border-box;
  294. .iconfont {
  295. // position: absolute;
  296. left: 14rpx;
  297. font-size: 26rpx;
  298. //top: 10rpx;
  299. }
  300. .line1{
  301. display: inline-block;
  302. width: 400rpx;
  303. }
  304. }
  305. .uninput {
  306. /* #ifdef MP */
  307. width: 75% ;
  308. /* #endif */
  309. /* #ifndef MP */
  310. width: 100%;
  311. /* #endif */
  312. }
  313. }
  314. }
  315. .maxInput{
  316. width: 100% !important;
  317. }
  318. </style>