Commit c8b1a9695651d3ecc2ffa27f914172de21ae87ed

Authored by boyang
1 parent 52612a6a

fix: 热销样式,prod2-47/48

components/CategoryList.vue
... ... @@ -70,6 +70,63 @@
70 70 </v-col>
71 71 </v-row>
72 72 </div>
  73 + <v-tabs
  74 + class="tabs"
  75 + v-model="tabRecom"
  76 + style="margin-top: 25px"
  77 + color="white"
  78 + bg-color="#eeeeee"
  79 + slider-color="blue-lighten-1"
  80 + selected-class="active"
  81 + v-if="recommendImages[0] !== null && !isMobile()"
  82 + >
  83 + <v-tab :value="1">Best Sellers</v-tab>
  84 + <!-- <v-tab :value="3">商品百科</v-tab> -->
  85 + </v-tabs>
  86 + <div id="image-container" v-if="recommendImages[0] !== null && !isMobile()">
  87 + <div class="recommend-left-box">
  88 + <v-img
  89 + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/76c987e13a334be481a346c19c2284f3qy4tjnxps7.png"
  90 + alt="往左移"
  91 + class="recommend-img-left"
  92 + @click="toggleRowLeft"
  93 + />
  94 + </div>
  95 + <div class="image-row" id="row1">
  96 + <!-- <img
  97 + v-for="(imageObj, index) in recommendImages.slice(0, 5)"
  98 + :key="'row1-' + index"
  99 + :src="imageObj[0]?.url"
  100 + :alt="'Image ' + (index + 1)"
  101 + style="margin: 0 5px; width: 200px; height: 200px"
  102 + /> -->
  103 + <div
  104 + v-for="(imageObj, index) in recommendImages"
  105 + :key="'row1-' + index"
  106 + class="imageTotal"
  107 + >
  108 + <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank">
  109 + <img
  110 + :src="imageObj[0]?.url"
  111 + :alt="'Image ' + (index + 1)"
  112 + class="item-imgHot"
  113 + />
  114 + <span class="image-name">
  115 + {{ imageObj[0]?.name }}
  116 + </span>
  117 + </a>
  118 + <div v-else style="width: 200px; height: 200px"></div>
  119 + </div>
  120 + </div>
  121 + <div class="recommend-right-box">
  122 + <v-img
  123 + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/b5daa0a8f2f140f5b406e984c730a453iznzlekysg.png"
  124 + alt="往右移"
  125 + class="recommend-img-right"
  126 + @click="toggleRowRight"
  127 + />
  128 + </div>
  129 + </div>
73 130 </v-container>
74 131 </template>
75 132  
... ... @@ -311,4 +368,474 @@ const funcCategoryList = computed(() =&gt; {
311 368 }
312 369 return [];
313 370 });
  371 +
  372 +import type { ProductImage } from "~/type";
  373 +import { isMobile, isEqual } from "~/utils";
  374 +import { watchEffect, ref } from "vue";
  375 +
  376 +const loading = ref(false);
  377 +const hotLoading = ref(false);
  378 +const title = ref("");
  379 +const keywordTitle = ref("");
  380 +const maxPage = ref(1);
  381 +const tabRecom = ref();
  382 +const recommendList = ref({});
  383 +const recommendImages = ref({});
  384 +const currentIndex = ref(1);
  385 +const hotTotal = ref(10);
  386 +const isOrNotMobile = ref(isMobile());
  387 +const maxPageMobile = ref(1);
  388 +const recommendListMobile = ref({});
  389 +const recommendImagesMobile = ref({});
  390 +const currentIndexMobile = ref(1);
  391 +const hotLoadingMobile = ref(false);
  392 +const hotTotalMobile = ref(10);
  393 +
  394 +const loadHotProducts = async () => {
  395 + const pageSize = 5;
  396 + let { data: hotProducts } = await useAsyncData(
  397 + "hotProducts",
  398 + () =>
  399 + $fetch("/shop/product/hotProducts", {
  400 + method: "GET",
  401 + params: {
  402 + pageNo: currentIndex.value,
  403 + pageSize: pageSize,
  404 + },
  405 + }),
  406 + {
  407 + server: true, // 仅在服务器端获取数据
  408 + }
  409 + );
  410 + hotTotal.value = hotProducts.value.data.total;
  411 + recommendList.value = hotProducts.value.data.records;
  412 + maxPage.value = hotProducts.value.data.pages;
  413 + // recommendImages.value = recommendList.value.slice(0, 10).map((item) => {
  414 + recommendImages.value = Array.from({ length: 5 }).map((_, index) => {
  415 + const item = recommendList.value[index];
  416 + if (!item) {
  417 + return null;
  418 + }
  419 + // 检查 productimageliststore 是否为字符串格式,如果是,则尝试解析
  420 + if (typeof item.productimageliststore === "string") {
  421 + try {
  422 + item.productimageliststore = JSON.parse(item.productimageliststore);
  423 + } catch (error) {
  424 + item.productimageliststore = []; // 解析失败时,设置为空数组
  425 + }
  426 + }
  427 + const ree = (item.productimageliststore = item?.productimageliststore.map(
  428 + (productItem: ProductImage) => ({
  429 + ...productItem,
  430 + // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`,
  431 + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`,
  432 + name: item.name,
  433 + productUrl: `https://www.canrud.com/products/detail/${item.id}`,
  434 + })
  435 + ));
  436 + return ree;
  437 + });
  438 +};
  439 +
  440 +const toggleRowLeft = () => {
  441 + if (currentIndex.value !== 1) {
  442 + currentIndex.value--;
  443 + } else if (currentIndex.value == 1) {
  444 + currentIndex.value = maxPage.value;
  445 + }
  446 + startTimer();
  447 +};
  448 +let intervalId: any;
  449 +const toggleRowRight = () => {
  450 + if (currentIndex.value < maxPage.value) {
  451 + currentIndex.value++;
  452 + } else if (currentIndex.value == maxPage.value) {
  453 + currentIndex.value = 1;
  454 + }
  455 + startTimer();
  456 +};
  457 +const startTimer = () => {
  458 + // 清除已有计时器,防止重复
  459 + clearInterval(intervalId);
  460 + intervalId = setInterval(() => {
  461 + toggleRowRight();
  462 + }, 5000); // 每6秒调用一次
  463 +};
  464 +
  465 +onMounted(() => {
  466 + startTimer();
  467 +});
  468 +
  469 +const toggleRowMobile = (value: number) => {
  470 + currentIndexMobile.value = value;
  471 +};
  472 +const { width } = useDisplay();
  473 +const firstHotIndex = ref(true);
  474 +
  475 +// // 监听屏幕宽度变化
  476 +// watch(width, async (newWidth) => {
  477 +// console.log(newWidth, "5656widthvalue");
  478 +// if (firstHotIndex.value) {
  479 +// if (newWidth > 600) {
  480 +// await loadHotProducts();
  481 +// } else {
  482 +// await loadHotProductsMobile();
  483 +// }
  484 +// }
  485 +// });
  486 +
  487 +// // 监听路由变化
  488 +// watch(
  489 +// () => route.fullPath,
  490 +// async () => {
  491 +// if (firstHotIndex.value) {
  492 +// if (width.value > 600) {
  493 +// await loadHotProducts();
  494 +// } else {
  495 +// await loadHotProductsMobile();
  496 +// }
  497 +// }
  498 +// }
  499 +// );
  500 +
  501 +watch(currentIndex, (newIndex) => {
  502 + loadHotProducts(); // Call loadHotProducts when currentIndex changes
  503 +});
  504 +
  505 +const loadHotProductsMobile = async () => {
  506 + hotLoadingMobile.value = true;
  507 + let { data: hotProductsMobile } = await useAsyncData(
  508 + "hotProducts",
  509 + () =>
  510 + $fetch("/shop/product/hotProducts", {
  511 + method: "GET",
  512 + params: {
  513 + pageNo: currentIndexMobile.value,
  514 + pageSize: 4,
  515 + },
  516 + }),
  517 + {
  518 + server: true, // 仅在服务器端获取数据
  519 + }
  520 + );
  521 + hotTotalMobile.value = hotProductsMobile.value.data.total;
  522 + recommendListMobile.value = hotProductsMobile.value.data.records;
  523 + maxPageMobile.value = hotProductsMobile.value.data.pages;
  524 + // recommendImages.value = recommendList.value.slice(0, 10).map((item) => {
  525 + recommendImagesMobile.value = Array.from({ length: 4 }).map((_, index) => {
  526 + const item = recommendListMobile.value[index];
  527 + if (!item) {
  528 + return null;
  529 + }
  530 + // 检查 productimageliststore 是否为字符串格式,如果是,则尝试解析
  531 + if (typeof item.productimageliststore === "string") {
  532 + try {
  533 + item.productimageliststore = JSON.parse(item.productimageliststore);
  534 + } catch (error) {
  535 + item.productimageliststore = []; // 解析失败时,设置为空数组
  536 + }
  537 + }
  538 + const ree = (item.productimageliststore = item?.productimageliststore.map(
  539 + (productItem: ProductImage) => ({
  540 + ...productItem,
  541 + // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`,
  542 + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`,
  543 + name: item.name,
  544 + productUrl: `https://www.canrud.com/products/detail/${item.id}`,
  545 + })
  546 + ));
  547 + return ree;
  548 + });
  549 + hotLoadingMobile.value = false;
  550 +};
  551 +watch(currentIndexMobile, (newIndex) => {
  552 + loadHotProductsMobile(); // Call loadHotProducts when currentIndex changes
  553 +});
  554 +watchEffect(async () => {
  555 + console.log("Current route:", route.fullPath, "Width:", width.value);
  556 +
  557 + if (firstHotIndex.value) {
  558 + if (width.value > 600) {
  559 + await loadHotProducts();
  560 + } else {
  561 + await loadHotProductsMobile();
  562 + }
  563 + }
  564 +});
  565 +
  566 +const length = computed(() =>
  567 + productStore.total ? Math.ceil(productStore.total / productStore.pageSize) : 0
  568 +);
  569 +const hotLength = computed(() =>
  570 + hotTotalMobile.value ? Math.ceil(hotTotalMobile.value / 4) : 0
  571 +);
314 572 </script>
  573 +<style scoped>
  574 +.title {
  575 + height: 60px;
  576 + overflow: hidden;
  577 + text-overflow: ellipsis;
  578 + display: -webkit-box;
  579 + -webkit-line-clamp: 2;
  580 + -webkit-box-orient: vertical;
  581 +}
  582 +
  583 +@media screen and (min-width: 1537px) {
  584 + .tabs {
  585 + border-bottom: 2px solid #1f88e5;
  586 + margin: 10px auto 20px;
  587 + width: 100%;
  588 + }
  589 +}
  590 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  591 + .tabs {
  592 + border-bottom: 2px solid #1f88e5;
  593 + margin: 10px auto 40px;
  594 + width: 100%;
  595 + }
  596 +}
  597 +@media screen and (max-width: 1280px) {
  598 + .tabs {
  599 + border-bottom: 2px solid #1f88e5;
  600 + margin: 10px auto 40px;
  601 + width: 100%;
  602 + }
  603 +}
  604 +/* .tabs {
  605 + border-bottom: 2px solid #1f88e5;
  606 +} */
  607 +
  608 +.active {
  609 + background-color: #1086e8;
  610 +}
  611 +
  612 +@media screen and (min-width: 1537px) {
  613 + #image-container {
  614 + display: flex;
  615 + align-items: center;
  616 + justify-content: center;
  617 + height: 320px;
  618 + margin: 10px auto 50px;
  619 + width: 100%;
  620 + }
  621 +}
  622 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  623 + #image-container {
  624 + display: flex;
  625 + align-items: center;
  626 + justify-content: center;
  627 + height: 260px;
  628 + margin: 10px auto 0px;
  629 + width: 100%;
  630 + padding: 0;
  631 + }
  632 +}
  633 +@media screen and (max-width: 1280px) {
  634 + #image-container {
  635 + display: flex;
  636 + align-items: center;
  637 + justify-content: center;
  638 + height: 260px;
  639 + margin: 10px auto 0px;
  640 + width: 100%;
  641 + padding: 0;
  642 + }
  643 +}
  644 +.image-row {
  645 + display: flex;
  646 + height: 245px;
  647 +}
  648 +@media screen and (min-width: 1537px) {
  649 + .imageTotal {
  650 + display: inline-block;
  651 + margin: 0 5px;
  652 + text-align: center;
  653 + width: 300px;
  654 + }
  655 +}
  656 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  657 + .imageTotal {
  658 + display: inline-block;
  659 + margin: 0 5px;
  660 + text-align: center;
  661 + width: 200px;
  662 + }
  663 +}
  664 +@media screen and (max-width: 1280px) {
  665 + .imageTotal {
  666 + display: inline-block;
  667 + margin: 0 5px;
  668 + text-align: center;
  669 + width: 200px;
  670 + }
  671 +}
  672 +@media screen and (min-width: 1537px) {
  673 + .image-row img {
  674 + width: 240px;
  675 + height: 240px;
  676 + }
  677 +}
  678 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  679 + .image-row img {
  680 + width: 140px;
  681 + height: 140px;
  682 + }
  683 +}
  684 +@media screen and (max-width: 1280px) {
  685 + .image-row img {
  686 + width: 120px;
  687 + height: 120px;
  688 + }
  689 +}
  690 +@media screen and (min-width: 1537px) {
  691 + .image-name {
  692 + display: -webkit-box; /* Enables multi-line text handling */
  693 + -webkit-box-orient: vertical; /* Defines the vertical orientation of the box */
  694 + -webkit-line-clamp: 3; /* Limits the text to 3 lines */
  695 + overflow: hidden; /* Hides the overflowed text */
  696 + text-overflow: ellipsis; /* Adds an ellipsis when the text overflows */
  697 + margin-top: 5px;
  698 + font-size: 16px;
  699 + width: 180px;
  700 + color: #555;
  701 + text-align: center; /* Centers the text horizontally */
  702 + margin-left: 50px;
  703 + }
  704 +}
  705 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  706 + .image-name {
  707 + display: -webkit-box; /* Enables multi-line text handling */
  708 + -webkit-box-orient: vertical; /* Defines the vertical orientation of the box */
  709 + -webkit-line-clamp: 3; /* Limits the text to 3 lines */
  710 + overflow: hidden; /* Hides the overflowed text */
  711 + text-overflow: ellipsis; /* Adds an ellipsis when the text overflows */
  712 + margin-top: 5px;
  713 + font-size: 16px;
  714 + width: 180px;
  715 + color: #555;
  716 + text-align: center; /* Centers the text horizontally */
  717 + margin-left: 10px;
  718 + }
  719 +}
  720 +@media screen and (max-width: 1280px) {
  721 + .image-name {
  722 + display: -webkit-box; /* Enables multi-line text handling */
  723 + -webkit-box-orient: vertical; /* Defines the vertical orientation of the box */
  724 + -webkit-line-clamp: 3; /* Limits the text to 3 lines */
  725 + overflow: hidden; /* Hides the overflowed text */
  726 + text-overflow: ellipsis; /* Adds an ellipsis when the text overflows */
  727 + margin-top: 5px;
  728 + font-size: 16px;
  729 + width: 180px;
  730 + color: #555;
  731 + text-align: center; /* Centers the text horizontally */
  732 + margin-left: 10px;
  733 + }
  734 +}
  735 +
  736 +button .recommendButton {
  737 + margin: 0 0px;
  738 + cursor: pointer;
  739 +}
  740 +
  741 +.recommend-left-box {
  742 +}
  743 +
  744 +@media screen and (max-width: 1280px) {
  745 + .recommend-img-left {
  746 + width: 26px;
  747 + height: 27px;
  748 + margin-bottom: 60px;
  749 + }
  750 +}
  751 +.recommend-img-left {
  752 + width: 26px;
  753 + height: 27px;
  754 + margin-right: 30px;
  755 + margin-bottom: 60px;
  756 +}
  757 +
  758 +.recommend-img-left:hover {
  759 + cursor: pointer;
  760 +}
  761 +.recommend-right-box {
  762 +}
  763 +
  764 +.recommend-img-right {
  765 + width: 26px;
  766 + height: 27px;
  767 + margin-left: 30px;
  768 + margin-bottom: 60px;
  769 +}
  770 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  771 + .recommend-img-left {
  772 + width: 26px;
  773 + height: 27px;
  774 + margin-right: 30px;
  775 + margin-bottom: 60px;
  776 + }
  777 +}
  778 +@media screen and (max-width: 1536px) and (min-width: 1281px) {
  779 + .recommend-img-right {
  780 + width: 26px;
  781 + height: 27px;
  782 + margin-left: 30px;
  783 + margin-bottom: 60px;
  784 + }
  785 +}
  786 +@media screen and (min-width: 1600px) {
  787 + .recommend-img-left {
  788 + width: 26px;
  789 + height: 27px;
  790 + margin-right: 70px;
  791 + margin-bottom: 60px;
  792 + }
  793 +}
  794 +@media screen and (min-width: 1600px) {
  795 + .recommend-img-right {
  796 + width: 26px;
  797 + height: 27px;
  798 + margin-left: 70px;
  799 + margin-bottom: 60px;
  800 + }
  801 +}
  802 +
  803 +.recommend-img-right:hover {
  804 + cursor: pointer;
  805 +}
  806 +
  807 +.v-card {
  808 + transition: all 0.3s ease-in-out;
  809 +}
  810 +
  811 +.v-card-text {
  812 + max-width: 100%; /* 确保文字宽度受限 */
  813 +}
  814 +.item-name {
  815 + display: -webkit-box !important;
  816 + -webkit-box-orient: vertical !important;
  817 + -webkit-line-clamp: 3 !important;
  818 + overflow: hidden !important;
  819 + text-overflow: ellipsis !important;
  820 + white-space: normal !important;
  821 + text-align: left;
  822 + line-height: 1.5em;
  823 + min-height: calc(3 * 1.5em); /* 强制未满三行时高度一致 */
  824 +}
  825 +
  826 +#product-card .v-responsive.v-img {
  827 + width: 274px !important; /* 设置宽度 */
  828 + height: 274px !important; /* 设置高度 */
  829 +}
  830 +
  831 +.clamp-text {
  832 + display: -webkit-box; /* 使用弹性盒子 */
  833 + -webkit-box-orient: vertical; /* 设置为垂直方向 */
  834 + -webkit-line-clamp: 3; /* 限制最多显示3行 */
  835 + overflow: hidden; /* 隐藏多余内容 */
  836 + text-overflow: ellipsis; /* 添加省略号 */
  837 + white-space: normal; /* 允许换行 */
  838 + line-height: 1.5em; /* 设置每行的高度 */
  839 + min-height: calc(3 * 1.5em); /* 确保最小高度为3行 */
  840 +}
  841 +</style>
... ...
deploy/prod2.sh
1 1 #!/bin/bash
2 2 # 变量定义
3   -LAST_TAG="1.0.46"
4   -TAG="1.0.47"
  3 +LAST_TAG="1.0.47"
  4 +TAG="1.0.48"
5 5 TARGET_PATH="/root/web/canrud-outside-nuxt-front"
6 6 DOCKERFILE_PATH="/root/web/canrud-outside-nuxt-front/canrud-nuxt-front"
7 7 IMAGE_NAME="canrud-outside-front"
... ...
pages/products/index.vue
... ... @@ -2,7 +2,7 @@
2 2 <div class="tw-m-auto tw-pb-[64px]" style="padding-bottom: 0px">
3 3 <CategoryList v-if="categoryStore.categoryVisible && !isMobile()" />
4 4 <MobileCategoryList v-if="categoryStore.categoryVisible && isMobile()" />
5   - <v-tabs
  5 + <!-- <v-tabs
6 6 class="tabs"
7 7 v-model="tabRecom"
8 8 style="margin-top: 25px"
... ... @@ -13,7 +13,6 @@
13 13 v-if="recommendImages[0] !== null && !isMobile()"
14 14 >
15 15 <v-tab :value="1">Best Sellers</v-tab>
16   - <!-- <v-tab :value="3">商品百科</v-tab> -->
17 16 </v-tabs>
18 17 <div id="image-container" v-if="recommendImages[0] !== null && !isMobile()">
19 18 <div class="recommend-left-box">
... ... @@ -25,13 +24,6 @@
25 24 />
26 25 </div>
27 26 <div class="image-row" id="row1">
28   - <!-- <img
29   - v-for="(imageObj, index) in recommendImages.slice(0, 5)"
30   - :key="'row1-' + index"
31   - :src="imageObj[0]?.url"
32   - :alt="'Image ' + (index + 1)"
33   - style="margin: 0 5px; width: 200px; height: 200px"
34   - /> -->
35 27 <div
36 28 v-for="(imageObj, index) in recommendImages"
37 29 :key="'row1-' + index"
... ... @@ -58,7 +50,7 @@
58 50 @click="toggleRowRight"
59 51 />
60 52 </div>
61   - </div>
  53 + </div> -->
62 54 <v-container class="">
63 55 <div class="tw-text-center tw-mt-[32px]" v-if="loading">
64 56 <v-progress-circular
... ... @@ -87,23 +79,13 @@
87 79 v-bind="props"
88 80 :to="`/products/detail/${item.id}`"
89 81 >
90   - <v-img :src="item.imgList[0].url" :alt="item.name">
91   - <!-- <v-expand-transition>
92   - <div
93   - v-if="isHovering"
94   - class="d-flex transition-fast-in-fast-out bg-orange-darken-2 v-card--reveal tw-p-[12px] tw-text-justify"
95   - style="height: 100%"
96   - >
97   - 产品描述描述描述描述描述描述描述描述
98   - </div>
99   - </v-expand-transition> -->
100   - </v-img>
  82 + <v-img :src="item.imgList[0].url" :alt="item.name"> </v-img>
101 83 <v-card-text
102 84 class="tw-text-left font-weight-medium title"
103 85 style="height: auto"
104 86 >
105 87 <h3 style="color: red" v-if="item.price">
106   - ${{ item.price }} - ${{ item.maxPrice }}
  88 + ${{ item.price }} - ${{ item.maxPrice }}
107 89 </h3>
108 90 <h4 class="item-name">{{ item.name }}</h4>
109 91 </v-card-text>
... ...