topMenu2.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. <template>
  2. <div class="menu_select menu_select-templater02" :class="{'fixed-top': headOver && basicSet.set.set_top == 1,'padding0': basicSet.set.set_top == 1}">
  3. <div v-html="css"></div>
  4. <div class="select_content m-auto flex">
  5. <!--商品分类-->
  6. <div class="item item-200 flex flex-j-c flex-a-c" v-if="basicCategory.data">
  7. <span>全部商品分类</span>
  8. <div class="classification-box" style="width:100%;" v-if="isHome == -1">
  9. <div class="classification-cell" v-for="(item,ind) in basicCategory.data.slice(0,10)" :key="ind" @click.stop="toCategoryChild({id: item.id})">
  10. <div class="first-class">{{item.name}}</div>
  11. <div class="secondary-class">
  12. <div class="secondary-name" @click.stop="toCategoryChild({id: obj.id})" v-for="(obj,bidx) in item.children" :key="bidx">{{obj.name}}</div>
  13. </div>
  14. </div>
  15. <div class="classification-cell" v-if="basicCategory.total > 10" @click.stop="toUrl('category')"><div class="first-class">查看更多分类</div></div>
  16. </div>
  17. </div>
  18. <!--商品分类end-->
  19. <!--后台自定义链接-->
  20. <div class="item item-1 flex flex-j-c flex-a-c" v-for="(item,index) in basicSet.nav_top" :key="index"
  21. @click="toLink(item)">
  22. <img :src="item.img_src" v-if="item.img_src" style="margin: 3px 10px 0 0;" class="nav-icon"> <span>{{item.nav_name}}</span>
  23. <img src="~/assets/images/icon/select.png" v-if="item.sub_nav && item.sub_nav.length>0" class="down_arrow">
  24. <div class="hide_menu">
  25. <template v-if="item.sub_nav && item.sub_nav.length>0">
  26. <div class="hide_item flex flex-j-c flex-a-c" v-for="(list,ind) in item.sub_nav" :key="ind"
  27. @click="toLink(list)">{{list.nav_name}}</div>
  28. </template>
  29. </div>
  30. </div>
  31. <!--后台自定义链接end-->
  32. </div>
  33. </div>
  34. </template>
  35. <script>
  36. import {mapState} from "vuex";
  37. // 自定义样式
  38. const css = function () {
  39. return `
  40. .menu_select {
  41. --dark_color: ${this.dark_color}
  42. }
  43. .menu_select .select_content .hide_menu{
  44. background-color: ${this.dark_color};
  45. }
  46. `;
  47. };
  48. export default {
  49. props: {
  50. menu: {
  51. type: Array
  52. }
  53. },
  54. data() {
  55. return {
  56. showClass: false,
  57. showChild: -1,
  58. isClick: false,
  59. isHome: -1,
  60. headOver: false,
  61. dark_color: "#ffffff",
  62. category_template: '01'
  63. };
  64. },
  65. computed: {
  66. ...mapState(["basicSet", "basicCategory", "basic_info"]),
  67. css() {
  68. return "<style>" + css.call(this) + "</style>";
  69. }
  70. },
  71. watch: {
  72. '$route'(res) {
  73. if (res.name == 'home') {
  74. this.isHome = 1;
  75. }else {
  76. this.isHome = -1
  77. if(res.name == 'catelist-id'){
  78. if(this.basicSet.set.pc_temp == 2){
  79. this.isHome = 1;
  80. }
  81. }
  82. }
  83. },
  84. },
  85. mounted() {
  86. let color =
  87. this.basicSet.set && this.basicSet.set.theme_color
  88. ? this.basicSet.set.theme_color
  89. : "#29ba9c";
  90. this.dark_color = this.changeColor(color, 0.15, true);
  91. // 获取分类模板
  92. if (this.basic_info.home && this.basic_info.home.item && this.basic_info.home.item.is_decorate === 1) {
  93. if (this.basic_info.home.item.ViewSet.category.is_default != 0) {
  94. this.category_template = this.basic_info.home.item.ViewSet.category.code.substring(8);
  95. } else {
  96. this.category_template = "01"
  97. }
  98. }
  99. this.isHome = window.location.href.indexOf('/home?') || window.location.href.indexOf('/home/?');
  100. window.addEventListener('scroll', this.handleScroll);
  101. if(this.$route.name == 'catelist-id'){
  102. // 分类模板2要求不显示下拉
  103. if(this.basicSet.set.pc_temp == 2){
  104. this.isHome = 1;
  105. }
  106. }
  107. },
  108. destroyed() {
  109. window.removeEventListener('scroll', this.handleScroll);
  110. },
  111. methods: {
  112. pad(num, totalChars) {
  113. var pad = "0";
  114. num = num + "";
  115. while (num.length < totalChars) {
  116. num = pad + num;
  117. }
  118. return num;
  119. },
  120. // Ratio is between 0 and 1
  121. changeColor(color, ratio, darker) {
  122. // Trim trailing/leading whitespace
  123. color = color.replace(/^\s*|\s*$/, "");
  124. // Expand three-digit hex
  125. color = color.replace(
  126. /^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i,
  127. "#$1$1$2$2$3$3"
  128. );
  129. // Calculate ratio
  130. let difference = Math.round(ratio * 256) * (darker ? -1 : 1),
  131. // Determine if input is RGB(A)
  132. rgb = color.match(
  133. new RegExp(
  134. "^rgba?\\(\\s*" +
  135. "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" +
  136. "\\s*,\\s*" +
  137. "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" +
  138. "\\s*,\\s*" +
  139. "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" +
  140. "(?:\\s*,\\s*" +
  141. "(0|1|0?\\.\\d+))?" +
  142. "\\s*\\)$",
  143. "i"
  144. )
  145. ),
  146. alpha = !!rgb && rgb[4] != null ? rgb[4] : null,
  147. // Convert hex to decimal
  148. decimal = !!rgb
  149. ? [rgb[1], rgb[2], rgb[3]]
  150. : color
  151. .replace(
  152. /^#?([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])/i,
  153. function () {
  154. return (
  155. parseInt(arguments[1], 16) +
  156. "," +
  157. parseInt(arguments[2], 16) +
  158. "," +
  159. parseInt(arguments[3], 16)
  160. );
  161. }
  162. )
  163. .split(/,/),
  164. returnValue;
  165. // Return RGB(A)
  166. return !!rgb
  167. ? "rgb" +
  168. (alpha !== null ? "a" : "") +
  169. "(" +
  170. Math[darker ? "max" : "min"](
  171. parseInt(decimal[0], 10) + difference,
  172. darker ? 0 : 255
  173. ) +
  174. ", " +
  175. Math[darker ? "max" : "min"](
  176. parseInt(decimal[1], 10) + difference,
  177. darker ? 0 : 255
  178. ) +
  179. ", " +
  180. Math[darker ? "max" : "min"](
  181. parseInt(decimal[2], 10) + difference,
  182. darker ? 0 : 255
  183. ) +
  184. (alpha !== null ? ", " + alpha : "") +
  185. ")"
  186. : // Return hex
  187. [
  188. "#",
  189. this.pad(
  190. Math[darker ? "max" : "min"](
  191. parseInt(decimal[0], 10) + difference,
  192. darker ? 0 : 255
  193. ).toString(16),
  194. 2
  195. ),
  196. this.pad(
  197. Math[darker ? "max" : "min"](
  198. parseInt(decimal[1], 10) + difference,
  199. darker ? 0 : 255
  200. ).toString(16),
  201. 2
  202. ),
  203. this.pad(
  204. Math[darker ? "max" : "min"](
  205. parseInt(decimal[2], 10) + difference,
  206. darker ? 0 : 255
  207. ).toString(16),
  208. 2
  209. )
  210. ].join("");
  211. },
  212. openClass() {
  213. this.showClass = !this.showClass;
  214. if(!this.showClass) {
  215. this.showChild = -1;
  216. }
  217. },
  218. openChild(ind) {
  219. if(this.showChild == ind) {
  220. this.showChild = -1;
  221. }else {
  222. this.showChild = ind;
  223. }
  224. },
  225. toCategoryChild(params) {
  226. this.isClick = true;
  227. this.showClass = false;
  228. this.showChild = -1;
  229. if (this.category_template === '03') {
  230. if(this.$baseURL) {
  231. // 静态部署环境下
  232. this.$router.push(this.fun.getUrl('category_child',{}, params));
  233. }else {
  234. this.$router.push(this.fun.getUrl('category_child-id', params));
  235. }
  236. }else {
  237. if(this.$baseURL) {
  238. // 静态部署环境下
  239. this.$router.push(this.fun.getUrl('catelist',{}, params));
  240. }else {
  241. this.$router.push(this.fun.getUrl('catelist-id', params));
  242. }
  243. }
  244. setTimeout(()=>{
  245. this.isClick = false;
  246. },500);
  247. },
  248. toUrl(url, params) {
  249. this.$router.push(this.fun.getUrl(url, params));
  250. },
  251. toLink(item) {
  252. this.showClass = false;
  253. this.showChild = -1;
  254. if(item.pc_adv_url) {
  255. window.open(item.pc_adv_url, "_blank");
  256. return;
  257. }
  258. if ((item.sub_nav && item.sub_nav.length > 0) || !item.url) {
  259. return;
  260. }
  261. if(item.url) {
  262. window.open(item.url, "_blank");
  263. }
  264. },
  265. handleScroll() {
  266. let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  267. if (scrollTop > 195) {
  268. this.headOver = true;
  269. } else {
  270. this.headOver = false;
  271. }
  272. },
  273. }
  274. };
  275. </script>
  276. <style lang="scss" scoped>
  277. .menu_select {
  278. width: 100%;
  279. /*margin: 0 auto 10px auto;*/
  280. padding-top: 175px;
  281. height: 45px;
  282. background-color: var(--color);
  283. .select_content {
  284. width: 1200px;
  285. .item:last-child {
  286. margin-right: 0;
  287. }
  288. .item {
  289. flex-shrink: 0;
  290. color: #fff;
  291. font-size: 16px;
  292. height: 45px;
  293. cursor: pointer;
  294. position: relative;
  295. padding: 0 20px;
  296. /*margin-right: 50px;*/
  297. .nav-icon {
  298. width: 20px;
  299. height: 20px;
  300. }
  301. .down_arrow {
  302. margin-left: 8px;
  303. /*display: none;*/
  304. }
  305. .hide_menu {
  306. opacity: 0;
  307. position: absolute;
  308. /*background-color: #2c7a60;*/
  309. top: 43px;
  310. white-space: nowrap;
  311. z-index: 99;
  312. transition: all 0.5s;
  313. width: 100%;
  314. .hide_item {
  315. transition: all 0.5s;
  316. min-height: 0px;
  317. height: 0px;
  318. opacity: 0;
  319. width: 100%;
  320. display: flex;
  321. font-size: 0;
  322. padding: 0 20px;
  323. box-sizing: border-box;
  324. word-break: break-all;
  325. white-space: pre-line;
  326. .hide_item_item::-webkit-scrollbar {display:none}
  327. .adv-img-box {
  328. display: none;
  329. position: absolute;
  330. width: 260px;
  331. height: 100%;
  332. left: 940px;
  333. z-index: 99;
  334. top: 0;
  335. img {
  336. width: 260px;
  337. height: 100%;
  338. }
  339. }
  340. .hide_item_item {
  341. transition: all 0.3s;
  342. display: none;
  343. background-color: #fff;
  344. box-shadow: 0px 2px 10px 0px rgba(171, 171, 171, 0.5);
  345. width: 720px;
  346. height: 100%;
  347. min-height: 300px;
  348. padding: 15px 40px;
  349. overflow-y: scroll;
  350. box-sizing: border-box;
  351. position: absolute;
  352. left: 220px;
  353. z-index: 99;
  354. top: 0;
  355. color: #333;
  356. .line {
  357. width: 3px;
  358. height: 15px;
  359. background-color: var(--color);
  360. display: inline-block;
  361. margin-right: 4px;
  362. }
  363. .title {
  364. font-weight: bold;
  365. font-size: 15px;
  366. }
  367. .icon-box {
  368. display: flex;
  369. flex-wrap: wrap;
  370. }
  371. .icon {
  372. display: inline-block;
  373. margin: 8px 15px;
  374. text-align: center;
  375. width: 90px;
  376. .img {
  377. width: 90px;
  378. height: 90px;
  379. border-radius: 50%;
  380. margin-bottom: 14px;
  381. img {
  382. border-radius: 50%;
  383. width: 100%;
  384. height: 100%;
  385. }
  386. }
  387. }
  388. .icon-name {
  389. width: 90px;
  390. overflow: hidden;
  391. white-space: nowrap;
  392. text-overflow: ellipsis;
  393. }
  394. }
  395. &:hover {
  396. background-color: #fff;
  397. color: var(--color);
  398. .hide_item_item {
  399. display: block;
  400. }
  401. .adv-img-box {
  402. display: block;
  403. }
  404. }
  405. &.showChild {
  406. background-color: #fff;
  407. color: var(--color);
  408. .hide_item_item {
  409. display: block;
  410. }
  411. .adv-img-box {
  412. display: block;
  413. }
  414. }
  415. .no-goods {
  416. margin: 20px;
  417. font-size: 16px;
  418. color: var(--color);
  419. }
  420. }
  421. }
  422. .classification-box{
  423. display: none;
  424. position: absolute;
  425. background-color: #fff;
  426. top: 43px;
  427. z-index: 99;
  428. width: 100%;
  429. height: 486px;
  430. padding: 16px;
  431. box-sizing: border-box;
  432. border-top: 6px solid var(--dark_color);
  433. box-shadow: 0px 0px 27px 0px rgba(4, 0, 0, 0.2);
  434. overflow-y: scroll;
  435. scrollbar-width: none; /* Firefox */
  436. -ms-overflow-style: none; /* IE 10+ */
  437. .classification-cell{
  438. display: flex;
  439. flex-direction: column;
  440. padding-top: 4px;
  441. .first-class{
  442. font-size: 14px;
  443. line-height: 28px;
  444. color: #000000;
  445. font-weight: bold;
  446. &:hover{
  447. cursor: pointer;
  448. color: var(--color);
  449. }
  450. }
  451. .secondary-class{
  452. display: flex;
  453. flex-wrap: wrap;
  454. .secondary-name{
  455. font-size: 12px;
  456. color: #8c8c8c;
  457. padding-right: 8px;
  458. text-align: left;
  459. min-width: 50%;
  460. box-sizing: border-box;
  461. line-height: 26px;
  462. &:hover{
  463. cursor: pointer;
  464. color: var(--color);
  465. }
  466. }
  467. }
  468. }
  469. .classification-cell:first-child{
  470. padding: 0;
  471. }
  472. }
  473. .classification-box::-webkit-scrollbar {
  474. display: none; /* Chrome Safari */
  475. }
  476. }
  477. .item-200 {
  478. background-color: var(--dark_color);
  479. min-width: 200px;
  480. padding: 0 10px;
  481. }
  482. .item:hover {
  483. background-color: var(--dark_color);
  484. .hide_menu {
  485. opacity: 1;
  486. .hide_item {
  487. min-height: 47px;
  488. height: auto;
  489. font-size: 14px;
  490. opacity: 1;
  491. }
  492. }
  493. .otherClass {
  494. height: 470px;
  495. }
  496. .down_arrow {
  497. display: block;
  498. }
  499. .double_hide_menu {
  500. display: flex;
  501. min-width: 200px;
  502. }
  503. }
  504. .item.showClass {
  505. background-color: var(--dark_color);
  506. .hide_menu {
  507. opacity: 1;
  508. .hide_item {
  509. min-height: 47px;
  510. height: auto;
  511. font-size: 14px;
  512. opacity: 1;
  513. }
  514. }
  515. .otherClass {
  516. height: 470px;
  517. }
  518. .down_arrow {
  519. display: block;
  520. }
  521. .double_hide_menu {
  522. display: flex;
  523. min-width: 200px;
  524. }
  525. }
  526. }
  527. }
  528. .menu_select.fixed-top {
  529. position: fixed;
  530. left: 50%;
  531. top: 0;
  532. z-index: 100;
  533. transform: translateX(-50%);
  534. }
  535. .padding0 {
  536. padding-top: 0;
  537. }
  538. .double_hide_menu.show-all {
  539. opacity: 1!important;
  540. display: flex;
  541. min-width: 200px;
  542. height: 470px;
  543. .hide_item {
  544. min-height: 47px!important;
  545. height: auto;
  546. font-size: 14px!important;
  547. opacity: 1!important;
  548. }
  549. }
  550. .menu_select-templater02{
  551. color: #000;
  552. background: #fff!important;
  553. border-bottom: 4px solid var(--dark_color);
  554. .select_content {
  555. .item{
  556. color: #000;
  557. &:hover{
  558. color: #fff;
  559. .classification-box{
  560. display: block;
  561. }
  562. }
  563. }
  564. .item:first-child{
  565. color: #fff;
  566. }
  567. }
  568. }
  569. </style>