app-navigation-two-icon.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. <template>
  2. <view class="app-navigation-two-icon" :style="bgStyle">
  3. <view v-if="navType === 'fixed'" class="dir-top-nowrap nav-fixed u-border-box"
  4. :class="{'nav-fixed-text' : modeType === 'text'}">
  5. <view v-for="(navs, index1) in newNavs" :key="index1" class="dir-left-nowrap">
  6. <view v-for="(nav, index2) in navs" :key="index2"
  7. :style="{marginRight: index2 === navs.length - 1 ? 'auto' : '0',marginLeft: 'auto'}">
  8. <!-- #ifdef MP -->
  9. <app-jump-button form :url="nav.link_url" :open_type="nav.open_type" arrangement="column"
  10. class="cross-top">
  11. <view class="nav-list dir-top-nowrap main-center cross-center u-border-box"
  12. :class="{'nav-list-text' : modeType === 'text'}">
  13. <image v-if="modeType === 'img'" class="nav-image" :src="nav.icon_url" lazy-load></image>
  14. <view v-if="nav.name" class="nav-name u-border-box" :style="{color: color}"
  15. :class="{'nav-name-text': modeType === 'text'}">
  16. {{ nav.name.substring(0, columns > 5 ? 4 : 5) }}
  17. </view>
  18. </view>
  19. </app-jump-button>
  20. <!-- #endif -->
  21. <!-- #ifdef H5 -->
  22. <app-jump-button :id="nav.id" v-if="nav.open_type === 'app'" class="cross-top" style="width: 100rpx">
  23. </app-jump-button>
  24. <app-jump-button v-else form :url="nav.link_url" :open_type="nav.open_type" arrangement="column"
  25. class="cross-top">
  26. <view class="nav-list dir-top-nowrap main-center cross-center u-border-box"
  27. :class="{'nav-list-text' : modeType === 'text'}">
  28. <image v-if="modeType === 'img'" class="nav-image" :src="nav.icon_url" lazy-load></image>
  29. <view v-if="nav.name" class="nav-name u-border-box" :style="{color: color}"
  30. :class="{'nav-name-text': modeType === 'text'}">
  31. {{ nav.name.substring(0, columns > 5 ? 4 : 5) }}
  32. </view>
  33. </view>
  34. </app-jump-button>
  35. <!-- #endif -->
  36. </view>
  37. </view>
  38. </view>
  39. <block v-if="navType === 'alone'">
  40. <!-- #ifdef MP-BAIDU -->
  41. <scroll-view scroll-x class="dir-left-nowrap" :style="{'height': modeType === 'img'? '192rpx': '100rpx'}">
  42. <!-- #endif -->
  43. <!-- #ifndef MP-BAIDU -->
  44. <scroll-view scroll-x class="dir-left-nowrap" :style="{'max-height': modeType === 'img'? '192rpx': '100rpx'}">
  45. <!-- #endif -->
  46. <view v-for="(nav, index) in aloneNav" :key="index" :style="[formatB(index)]" class="box-list">
  47. <!-- #ifdef MP -->
  48. <app-jump-button style="height: 100%" form :url="nav.link_url" :open_type="nav.open_type"
  49. arrangement="column"
  50. class="cross-top">
  51. <image v-if="modeType === 'img'" :src="nav.icon_url"
  52. :style="{height:'88rpx',width: '88rpx','margin-bottom': 'auto'}"
  53. lazy-load></image>
  54. <view v-if="nav.name" class="t-omit nav-name" :style="{color: color}"
  55. :class="{'nav-name-alone': modeType === 'text'}">
  56. {{ nav.name.substring(0, aloneNum > 5 ? 4 : 5) }}
  57. </view>
  58. </app-jump-button>
  59. <!-- #endif -->
  60. <!-- #ifdef H5 -->
  61. <app-jump-button :id="nav.id" v-if="nav.open_type === 'app'" style="height: 88rpx;" class="cross-top">
  62. </app-jump-button>
  63. <app-jump-button v-else style="height: 100%" form :url="nav.link_url" :open_type="nav.open_type"
  64. arrangement="column"
  65. class="cross-top">
  66. <image v-if="modeType === 'img'" :src="nav.icon_url"
  67. :style="{height:'88rpx',width: '88rpx','margin-bottom': 'auto'}"
  68. lazy-load></image>
  69. <view v-if="nav.name" class="t-omit nav-name" :style="{color: color}"
  70. :class="{'nav-name-alone': modeType === 'text'}">
  71. {{ nav.name.substring(0, aloneNum > 5 ? 4 : 5) }}
  72. </view>
  73. </app-jump-button>
  74. <!-- #endif -->
  75. </view>
  76. <!-- #ifdef MP-ALIPAY -->
  77. <view class="box-list box-grow-0" style="width:1px"></view>
  78. <!-- #endif -->
  79. </scroll-view>
  80. </block>
  81. <block v-if="navType === 'multi'">
  82. <swiper @change="changeSwiper" :style="{height: multiswiper}">
  83. <swiper-item v-for="(navlist, index0) in muitiNavs" :key="index0" :item-id="index0.toString()">
  84. <view class="dir-top-nowrap nav-fixed" :class="'nav-swiper-' + tempIndex">
  85. <view v-for="(navs, index1) in navlist" :key="index1" class="dir-left-nowrap">
  86. <view v-for="(nav, index2) in navs" :key="index2"
  87. :style="{marginRight: index2 === navs.length - 1 ? 'auto' : '0',marginLeft: 'auto'}">
  88. <!-- #ifdef MP -->
  89. <app-jump-button form :url="nav.link_url" :open_type="nav.open_type"
  90. arrangement="column"
  91. class="cross-top">
  92. <view class="nav-list dir-top-nowrap main-center cross-center"
  93. :class="{'nav-list-text' : modeType === 'text'}">
  94. <image v-if="modeType === 'img'" class="nav-image" :src="nav.icon_url"
  95. lazy-load></image>
  96. <view v-if="nav.name" class="nav-name" :style="{color: color}"
  97. :class="{'nav-name-text': modeType === 'text'}">
  98. {{ nav.name.substring(0, columns > 5 ? 4 : 5) }}
  99. </view>
  100. </view>
  101. </app-jump-button>
  102. <!-- #endif -->
  103. <!-- #ifdef H5 -->
  104. <view :id="nav.id" v-if="nav.open_type === 'app'" class="cross-top" style="width: 100rpx">
  105. </view>
  106. <app-jump-button v-else form :url="nav.link_url" :open_type="nav.open_type"
  107. arrangement="column"
  108. class="cross-top">
  109. <view class="nav-list dir-top-nowrap main-center cross-center"
  110. :class="{'nav-list-text' : modeType === 'text'}">
  111. <image v-if="modeType === 'img'" class="nav-image" :src="nav.icon_url"
  112. lazy-load></image>
  113. <view v-if="nav.name" class="nav-name" :style="{color: color}"
  114. :class="{'nav-name-text': modeType === 'text'}">
  115. {{ nav.name.substring(0, columns > 5 ? 4 : 5) }}
  116. </view>
  117. </view>
  118. </app-jump-button>
  119. <!-- #endif -->
  120. </view>
  121. </view>
  122. </view>
  123. </swiper-item>
  124. </swiper>
  125. <!-- 指示点 -->
  126. <view class="main-center cross-center indicator u-border-box">
  127. <block v-if="swiperType === 'rectangle'">
  128. <view class="dir-left-nowrap">
  129. <view v-for="(i,index) in muitiNavs" :key="index" class="rectangletwo"
  130. :style="{backgroundColor: current === index ? swiperColor : swiperNoColor}">
  131. </view>
  132. </view>
  133. <!--<view :style="{width: `${muitiNavs.length * 44}rpx`}" class="rectangle">-->
  134. <!-- <view class="rectangle active"-->
  135. <!-- :style="{left: `${current * 44}rpx`,backgroundColor: swiperColor}"></view>-->
  136. <!--</view>-->
  137. </block>
  138. <block v-if="swiperType === 'circle'">
  139. <view class="dir-left-nowrap">
  140. <view v-for="(i,index) in muitiNavs" :key="index" class="circle"
  141. :style="{backgroundColor: current === index ? swiperColor : swiperNoColor}">
  142. </view>
  143. </view>
  144. </block>
  145. </view>
  146. </block>
  147. </view>
  148. </template>
  149. <script>
  150. export default {
  151. name: 'app-navigation-two-icon',
  152. props: {
  153. background: {
  154. type: String,
  155. default() {
  156. return '#ffffff';
  157. }
  158. },
  159. modeType: {
  160. type: String,
  161. default() {
  162. return 'img';
  163. }
  164. },
  165. color: {
  166. type: String,
  167. default() {
  168. return '#333333';
  169. }
  170. },
  171. //每行个数
  172. columns: {
  173. type: Number,
  174. default() {
  175. return 3;
  176. }
  177. },
  178. navs: {
  179. type: Array,
  180. default() {
  181. return []
  182. }
  183. },
  184. navType: String,
  185. aloneNum: Number, //一屏显示
  186. lineNum: Number, //一屏行数
  187. swiperType: String,
  188. swiperColor: String,
  189. swiperNoColor: String,
  190. tempIndex: Number,
  191. bgType: String,
  192. backgroundPicUrl: String,
  193. },
  194. data() {
  195. return {
  196. current: 0,
  197. multiswiper: '80px',
  198. defaultInfo: {
  199. imageHeight: 88,
  200. left: 32,
  201. limit: 30,
  202. }
  203. }
  204. },
  205. onLoad() {
  206. // #ifdef H5
  207. this.$jwx.config();
  208. // #endif
  209. },
  210. methods: {
  211. calcHeight: function () {
  212. let time;
  213. // #ifndef MP-BAIDU
  214. time = 500;
  215. // #endif
  216. // #ifndef MP-BAIDU
  217. time = 0;
  218. // #endif
  219. setTimeout(() => {
  220. let query;
  221. // #ifndef MP-WEIXIN || MP-TOUTIAO
  222. query = uni.createSelectorQuery();
  223. // #endif
  224. // #ifdef MP-WEIXIN || MP-TOUTIAO
  225. query = uni.createSelectorQuery().in(this);
  226. // #endif
  227. query.select(`.nav-swiper-${this.tempIndex}`).boundingClientRect(item => {
  228. if (item) {
  229. this.multiswiper = item.height + 'px';
  230. }
  231. }).exec();
  232. }, 500)
  233. },
  234. changeSwiper: function (e) {
  235. this.current = e.detail.current;
  236. },
  237. group: function (array, subGroupLength) {
  238. subGroupLength = parseInt(subGroupLength);
  239. let index = 0;
  240. let newArray = [];
  241. while (index < array.length) {
  242. newArray.push(array.slice(index, index += subGroupLength));
  243. }
  244. return newArray;
  245. },
  246. addNull: function () {
  247. // #ifdef H5
  248. this.navs.forEach(nav => {
  249. if (nav.open_type === 'app') {
  250. nav.id = this.$utils.guid('app-swiper')
  251. let username = this.$utils.getUrlParamApp(nav.link_url, 'username');
  252. let path = this.$utils.getUrlParamApp(nav.link_url, 'path');
  253. let text = '';
  254. function changePx(num){
  255. return uni.upx2px(num)+ 'px';
  256. };
  257. switch (this.navType) {
  258. case 'fixed':
  259. text += `<div style="box-sizing: border-box;width: ${changePx(100)};display: -webkit-box;display: -webkit-flex;display: flex; -webkit-box-orient: vertical; -webkit-flex-direction: column;flex-direction: column; flex-wrap: nowrap; display: -webkit-box;display: -webkit-flex;display: flex;-webkit-box-pack: center;-webkit-justify-content: center;-ms-flex-pack: center;justify-content: center; display: -webkit-box;display: -webkit-flex;display: flex;-webkit-align-items: center;align-items: center;padding-top: ${this.modeType === 'text' ? 0 : changePx(28)}">`;
  260. text += this.modeType === 'img' ? `<img style="height:${changePx(88)};width: ${changePx(88)};display: block;margin-bottom: auto;" src="${nav.icon_url}" lazy-load />` : '';
  261. text += nav.name ? `<div style="box-sizing: border-box;font-size: ${changePx(24)};color: #353535;display: block;white-space: nowrap;line-height: 1;text-align: center;color: ${this.color};padding-top: ${this.modeType === 'text' ? changePx(32) : changePx(16)};padding-bottom: ${this.modeType === 'text' ? changePx(4) : changePx(4)}">${ nav.name.substring(0, columns > 5 ? 4 : 5)}</div>`:'';
  262. text += `</div>`;
  263. break;
  264. case 'alone':
  265. text += this.modeType === 'img' ? `<img src="${nav.icon_url}" style="height: ${changePx(88)};width:${changePx(88)};margin-bottom: auto" lazy-load />` : '';
  266. text += nav.name ? `<div style="padding: ${this.modeType === 'text' ? "changePx(88) 0" : 'auto'};color:${this.color};word-break: break-all; text-overflow: ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;overflow: hidden;font-size: ${changePx(24)};color: #353535;padding-top: ${changePx(16)};padding-bottom: ${changePx(4)};display: block; white-space: nowrap;line-height: 1;text-align: center;">${nav.name.substring(0, this.aloneNum > 5 ? 4 : 5)}</div>` : '';
  267. break;
  268. case 'multi':
  269. text += `<div style="width: ${changePx(100)};display: -webkit-box;display: -webkit-flex;display: flex; -webkit-box-orient: vertical; -webkit-flex-direction: column;flex-direction: column; flex-wrap: nowrap; display: -webkit-box;display: -webkit-flex;display: flex;-webkit-box-pack: center;-webkit-justify-content: center;-ms-flex-pack: center;justify-content: center; display: -webkit-box;display: -webkit-flex;display: flex;-webkit-align-items: center;align-items: center;padding-top: ${this.modeType === 'text' ? 0 : changePx(28)}">`;
  270. text += this.modeType === 'img' ? `<img style="height:${changePx(88)};width: ${changePx(88)};display: block;margin-bottom: auto;" src="${nav.icon_url}" lazy-load />` : '';
  271. text += nav.name ? `<div style="font-size: ${changePx(24)};color: #353535;display: block;white-space: nowrap;line-height: 1;text-align: center;color: ${this.color};padding-top: ${this.modeType === 'text' ? changePx(32) : changePx(16)};padding-bottom: ${this.modeType === 'text' ? changePx(4) : changePx(4)}">${ nav.name.substring(0, columns > 5 ? 4 : 5)}</div>`:'';
  272. text += `</div>`;
  273. break;
  274. }
  275. console.error(nav.id, username, path, text);
  276. this.$utils.createWxOpenLaunchWeapp(nav.id, username, path, text);
  277. }
  278. });
  279. // #endif
  280. let columns = this.columns;
  281. let length = this.navs.length;
  282. let addNum = length % columns === 0 ? 0 : columns - length % columns;
  283. return this.navs.concat(new Array(addNum).fill({
  284. 'url': '',
  285. 'openType': '',
  286. 'icon_url': '',
  287. 'name': '',
  288. }))
  289. }
  290. },
  291. created() {
  292. this.calcHeight();
  293. },
  294. beforeUpdate() {
  295. this.calcHeight();
  296. },
  297. computed: {
  298. aloneNav(){
  299. // #ifdef H5
  300. this.navs.forEach(nav => {
  301. if (nav.open_type === 'app') {
  302. nav.id = this.$utils.guid('app-swiper')
  303. let username = this.$utils.getUrlParamApp(nav.link_url, 'username');
  304. let path = this.$utils.getUrlParamApp(nav.link_url, 'path');
  305. let text = '';
  306. function changePx(num){
  307. return uni.upx2px(num)+ 'px';
  308. };
  309. switch (this.navType) {
  310. case 'alone':
  311. text += this.modeType === 'img' ? `<img src="${nav.icon_url}" style="height: ${changePx(88)};width:${changePx(88)};margin-bottom: auto" lazy-load />` : '';
  312. text += nav.name ? `<div style="padding: ${this.modeType === 'text' ? "changePx(88) 0" : 'auto'};color:${this.color};word-break: break-all; text-overflow: ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;overflow: hidden;font-size: ${changePx(24)};color: #353535;padding-top: ${changePx(16)};padding-bottom: ${changePx(4)};display: block; white-space: nowrap;line-height: 1;text-align: center;">${nav.name.substring(0, this.aloneNum > 5 ? 4 : 5)}</div>` : '';
  313. break;
  314. }
  315. console.error(nav.id, username, path, text);
  316. this.$utils.createWxOpenLaunchWeapp(nav.id, username, path, text);
  317. }
  318. });
  319. // #endif
  320. return this.navs;
  321. },
  322. bgStyle(){
  323. if(this.bgType === 'color'){
  324. return `background-color: ${this.background};`;
  325. }
  326. if(this.bgType === 'pic'){
  327. return `background-size: 100% 100%;background-repeat: no-repeat;background-position: center center;background-image: url(${this.backgroundPicUrl})`;
  328. }
  329. },
  330. newNavs() {
  331. let arr = this.addNull();
  332. return this.group(arr, this.columns)
  333. },
  334. muitiNavs() {
  335. let arr = this.addNull();
  336. arr = this.group(arr, this.columns);
  337. arr = this.group(arr, this.lineNum)
  338. return arr;
  339. },
  340. aloneWidth() {
  341. return `100rpx`;
  342. /*
  343. let aloneNum = Number(this.aloneNum);
  344. let width = 0;
  345. if (aloneNum < 5) {
  346. width = this.defaultInfo.imageHeight;
  347. } else {
  348. width = (750 - this.defaultInfo.left - (aloneNum - 1) * this.defaultInfo.limit) / (aloneNum * 2 - 1) * 2;
  349. }
  350. return `${uni.upx2px(width)}px`;
  351. */
  352. },
  353. formatB() {
  354. return (index) => {
  355. let aloneNum = Number(this.aloneNum);
  356. let extra = {width: this.aloneWidth,'min-width': this.aloneWidth};
  357. if (aloneNum < 5) {
  358. extra = Object.assign(extra, {
  359. marginLeft : `${uni.upx2px(750 - parseFloat(this.aloneWidth) * aloneNum) / (aloneNum + 1)}px`,
  360. })
  361. } else {
  362. extra = Object.assign(extra, {
  363. marginLeft: `${uni.upx2px((750 - parseFloat(this.aloneWidth) * aloneNum + parseFloat(this.aloneWidth) / 2) / aloneNum)}px`,
  364. })
  365. }
  366. if (index === this.navs.length - 1) extra = Object.assign(extra, {'margin-right': extra.marginLeft})
  367. return extra;
  368. }
  369. },
  370. },
  371. }
  372. </script>
  373. <style scoped lang="scss">
  374. .app-navigation-two-icon {
  375. ::-webkit-scrollbar {
  376. display: none;
  377. width: 0;
  378. height: 0;
  379. color: transparent;
  380. }
  381. .nav-fixed {
  382. padding: 0 0 #{24rpx};
  383. }
  384. .nav-fixed.nav-fixed-text {
  385. padding-bottom: #{32rpx - 36rpx + 32rpx};
  386. }
  387. .nav-list {
  388. padding-top: #{28rpx};
  389. width: #{100rpx};
  390. }
  391. .nav-list.nav-list-text {
  392. padding-top: 0;
  393. }
  394. .nav-image {
  395. height: #{88rpx};
  396. width: #{88rpx};
  397. display: block;
  398. margin-bottom: auto;
  399. }
  400. .nav-name {
  401. font-size: #{24rpx};
  402. color: #353535;
  403. padding-top: #{16rpx};
  404. padding-bottom: calc(#{32rpx} - #{28rpx});
  405. display: block;
  406. white-space: nowrap;
  407. line-height: 1;
  408. /*width: 100%;*/
  409. /*overflow: hidden;*/
  410. /*text-overflow: clip;*/
  411. text-align: center;
  412. }
  413. .nav-name.nav-name-text {
  414. padding-top: #{32rpx};
  415. padding-bottom: calc(#{36rpx} - #{32rpx});
  416. }
  417. .nav-name-alone {
  418. padding: calc(#{32rpx - 28rpx}) 0;
  419. }
  420. scroll-view {
  421. white-space: nowrap;
  422. padding: #{28rpx} 0;
  423. .box-list {
  424. display: inline-block;
  425. }
  426. image {
  427. width: 100%;
  428. display: block;
  429. }
  430. text {
  431. width: 100%;
  432. text-align: center;
  433. padding-top: #{12rpx};
  434. display: block;
  435. line-height: 1;
  436. padding-bottom: #{18rpx};
  437. font-size: #{12px};
  438. text-overflow: clip;
  439. }
  440. }
  441. .indicator {
  442. height: #{10rpx};
  443. margin-top: calc(#{16rpx - 24rpx});
  444. padding-bottom: #{12rpx};
  445. width: 100%;
  446. .rectangle {
  447. border-radius: #{6rpx};
  448. height: #{8rpx};
  449. background-color: #BCBCBC;
  450. position: relative;
  451. }
  452. .rectangle .active {
  453. position: absolute;
  454. top: 0;
  455. width: #{44rpx};
  456. }
  457. .rectangletwo {
  458. height: #{8rpx};
  459. margin: 0 #{2rpx};
  460. width: #{24rpx};
  461. border-radius: #{16rpx};
  462. }
  463. .circle {
  464. height: #{8rpx};
  465. margin: 0 #{5rpx};
  466. width: #{8rpx};
  467. border-radius: 50%;
  468. }
  469. }
  470. }
  471. </style>