Commit c9fecebbb4f5b1a82f11ac43f66d5b35740b0f0a
1 parent
a4b10b4c
feat: 开发热销商品
Showing
6 changed files
with
912 additions
and
280 deletions
components/Footer.vue
... | ... | @@ -5,7 +5,9 @@ |
5 | 5 | <v-col cols="12" lg="3" sm="12" md="6"> |
6 | 6 | <b>Solution</b> |
7 | 7 | <p><router-link to="/equipment">Lab Device</router-link></p> |
8 | - <p><router-link to="/customize">Customized BatterTesting</router-link></p> | |
8 | + <p> | |
9 | + <router-link to="/customize">Customized BatterTesting</router-link> | |
10 | + </p> | |
9 | 11 | <p><router-link to="/pack">Pack</router-link></p> |
10 | 12 | </v-col> |
11 | 13 | <v-col cols="12" lg="3" sm="12" md="6"> |
... | ... | @@ -16,6 +18,18 @@ |
16 | 18 | <v-col cols="12" lg="3" sm="12" md="6"> |
17 | 19 | <b>About</b> |
18 | 20 | <p><router-link to="/about">About us</router-link></p> |
21 | + <p> | |
22 | + <a | |
23 | + href="https://www.linkedin.com/company/canrd/" | |
24 | + rel="noopener noreferrer" | |
25 | + >LinkedIn</a | |
26 | + > | |
27 | + </p> | |
28 | + <p> | |
29 | + <a href="https://x.com/canrdenerge?s=11" rel="noopener noreferrer" | |
30 | + >Twitter</a | |
31 | + > | |
32 | + </p> | |
19 | 33 | </v-col> |
20 | 34 | <v-col cols="12" lg="3" sm="12" md="6"> |
21 | 35 | <div class="tw-w-[250px] tw-float-left tw-mr-[8px]"> |
... | ... | @@ -24,7 +38,12 @@ |
24 | 38 | <p>Phone: +86 19867737979</p> |
25 | 39 | <p>Wechat: contactcanrd</p> |
26 | 40 | </div> |
27 | - <img class="tw-float-left" src="/wechat.jpg" alt="canrud-wechat" width="80" /> | |
41 | + <img | |
42 | + class="tw-float-left" | |
43 | + src="/wechat.jpg" | |
44 | + alt="canrud-wechat" | |
45 | + width="80" | |
46 | + /> | |
28 | 47 | </v-col> |
29 | 48 | </v-row> |
30 | 49 | </v-container> | ... | ... |
components/MobileCategoryList.vue
... | ... | @@ -200,7 +200,7 @@ watchEffect(async () => { |
200 | 200 | const foundFuncCategory = funcCategoryList.value.find( |
201 | 201 | (func) => func.name === functionName |
202 | 202 | ); |
203 | - console.log(foundFuncCategory, "5656functionName"); | |
203 | + console.log(foundFuncCategory, "functionName"); | |
204 | 204 | |
205 | 205 | if (foundFuncCategory) { |
206 | 206 | const funcCategoryId = foundFuncCategory.id; | ... | ... |
components/ProductDetail.vue
... | ... | @@ -208,30 +208,15 @@ |
208 | 208 | <div |
209 | 209 | v-for="(imageObj, index) in recommendImages.slice(0, 5)" |
210 | 210 | :key="'row1-' + index" |
211 | - style=" | |
212 | - display: inline-block; | |
213 | - margin: 0 5px; | |
214 | - text-align: center; | |
215 | - width: 200px; | |
216 | - " | |
211 | + class="imageTotal" | |
217 | 212 | > |
218 | 213 | <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank"> |
219 | 214 | <img |
220 | 215 | :src="imageObj[0]?.url" |
221 | 216 | :alt="'Image ' + (index + 1)" |
222 | - style="width: 200px; height: 200px; margin-right: 10px" | |
217 | + class="item-imgHot" | |
223 | 218 | /> |
224 | - <span | |
225 | - style=" | |
226 | - display: block; | |
227 | - margin-top: 5px; | |
228 | - font-size: 16px; | |
229 | - width: 180px; | |
230 | - color: #555; | |
231 | - text-align: left; | |
232 | - margin-left: 10px; | |
233 | - " | |
234 | - > | |
219 | + <span class="image-name"> | |
235 | 220 | {{ imageObj[0]?.name }} |
236 | 221 | </span> |
237 | 222 | </a> |
... | ... | @@ -249,30 +234,15 @@ |
249 | 234 | <div |
250 | 235 | v-for="(imageObj, index) in recommendImages.slice(5, 10)" |
251 | 236 | :key="'row2-' + index" |
252 | - style=" | |
253 | - display: inline-block; | |
254 | - margin: 0 5px; | |
255 | - text-align: center; | |
256 | - width: 200px; | |
257 | - " | |
237 | + class="imageTotal" | |
258 | 238 | > |
259 | 239 | <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank"> |
260 | 240 | <img |
261 | 241 | :src="imageObj[0]?.url" |
262 | 242 | :alt="'Image ' + (index + 6)" |
263 | - style="width: 200px; height: 200px; margin-right: 10px" | |
243 | + class="item-imgHot" | |
264 | 244 | /> |
265 | - <span | |
266 | - style=" | |
267 | - display: block; | |
268 | - margin-top: 5px; | |
269 | - font-size: 16px; | |
270 | - color: #555; | |
271 | - text-align: left; | |
272 | - width: 180px; | |
273 | - margin-left: 10px; | |
274 | - " | |
275 | - > | |
245 | + <span class="image-name"> | |
276 | 246 | {{ imageObj[0]?.name }} |
277 | 247 | </span> |
278 | 248 | </a> |
... | ... | @@ -291,63 +261,6 @@ |
291 | 261 | /> |
292 | 262 | </div> |
293 | 263 | </div> |
294 | - | |
295 | - <!-- <div class="tw-pb-[64px]"> | |
296 | - <v-tabs | |
297 | - class="tabs" | |
298 | - v-model="tab" | |
299 | - color="white" | |
300 | - bg-color="#eeeeee" | |
301 | - slider-color="blue-lighten-1" | |
302 | - selected-class="active" | |
303 | - > | |
304 | - <v-tab :value="1">Product Details</v-tab> | |
305 | - <v-tab :value="2">Specification</v-tab> | |
306 | - </v-tabs> | |
307 | - <v-window v-model="tab" class="tw-p-[24px]"> | |
308 | - <v-window-item key="1" :value="1"> | |
309 | - <div v-if="info.advantage" class="tw-mb-[24px]"> | |
310 | - <div class="text-h6">Advantage</div> | |
311 | - <v-divider class="tw-mb-[12px]"></v-divider> | |
312 | - <div v-html="info.advantage"></div> | |
313 | - </div> | |
314 | - <div v-if="info.physicalproperty" class="tw-mb-[24px]"> | |
315 | - <div class="text-h6">Physical Property</div> | |
316 | - <v-divider class="tw-mb-[12px]"></v-divider> | |
317 | - <div v-html="info.physicalproperty"></div> | |
318 | - </div> | |
319 | - <div v-if="info.storage" class="tw-mb-[24px]"> | |
320 | - <div class="text-h6">Storage</div> | |
321 | - <v-divider class="tw-mb-[12px]"></v-divider> | |
322 | - <div v-html="info.storage"></div> | |
323 | - </div> | |
324 | - <div v-if="info.introduction" class="tw-mb-[24px]"> | |
325 | - <div class="text-h6">Introduction</div> | |
326 | - <v-divider class="tw-mb-[12px]"></v-divider> | |
327 | - <div v-html="info.introduction"></div> | |
328 | - </div> | |
329 | - <div v-if="info.description" class="tw-mb-[24px]"> | |
330 | - <div class="text-h6">Description</div> | |
331 | - <v-divider class="tw-mb-[12px]"></v-divider> | |
332 | - <div v-html="info.description"></div> | |
333 | - </div> | |
334 | - </v-window-item> | |
335 | - <v-window-item key="2" :value="2"> | |
336 | - <v-table density="compact" class="table2"> | |
337 | - <tbody> | |
338 | - <tr | |
339 | - class="tr" | |
340 | - v-for="item in info.productAttributeList || []" | |
341 | - :key="item.name" | |
342 | - > | |
343 | - <td class="td tw-w-[400px]">{{ item.name }}</td> | |
344 | - <td class="td">{{ item.value }}</td> | |
345 | - </tr> | |
346 | - </tbody> | |
347 | - </v-table> | |
348 | - </v-window-item> | |
349 | - </v-window> | |
350 | - </div> --> | |
351 | 264 | <div style="display: flex"> |
352 | 265 | <div class="tw-pb-[64px]" style="width: 70%; margin-right: 10px"> |
353 | 266 | <v-tabs |
... | ... | @@ -416,81 +329,82 @@ |
416 | 329 | selected-class="active" |
417 | 330 | grow |
418 | 331 | > |
419 | - <v-tab value="one">Blog recommendation</v-tab> | |
332 | + <v-tab value="one">Journal Recommendation</v-tab> | |
420 | 333 | </v-tabs> |
421 | -<!-- <v-list lines="three">--> | |
422 | -<!-- <v-list-item--> | |
423 | -<!-- v-for="item in info.journals"--> | |
424 | -<!-- :key="item.id"--> | |
425 | -<!-- :subtitle="item.title"--> | |
426 | -<!-- @click="navigateToUrl(item.link)"--> | |
427 | -<!-- lines="three"--> | |
428 | -<!-- style="font-size: 24px"--> | |
429 | -<!-- ></v-list-item>--> | |
430 | -<!-- </v-list>--> | |
431 | 334 | <v-list> |
432 | 335 | <v-list-item |
433 | - v-for="item in info.journals" | |
434 | - :key="item.id" | |
435 | - @click="navigateToUrl(item.link)" | |
436 | - @mouseenter="hoveredItem = item.id" | |
437 | - @mouseleave="hoveredItem = null" | |
336 | + v-for="item in info.journals" | |
337 | + :key="item.id" | |
338 | + @click="navigateToUrl(item.link)" | |
339 | + @mouseenter="hoveredItem = item.id" | |
340 | + @mouseleave="hoveredItem = null" | |
438 | 341 | > |
439 | 342 | <v-list-item-title> |
440 | - <span | |
441 | - :class="['title', { 'full-title': hoveredItem === item.id }]" | |
442 | - > | |
443 | - {{ item.title }} | |
444 | - </span> | |
343 | + <span | |
344 | + :class="['title', { 'full-title': hoveredItem === item.id }]" | |
345 | + > | |
346 | + {{ item.title }} | |
347 | + </span> | |
445 | 348 | </v-list-item-title> |
446 | 349 | </v-list-item> |
447 | 350 | </v-list> |
448 | - <!-- <v-list rounded> | |
449 | - <v-list-item-group v-model="selectedItem" color="primary"> | |
450 | - <v-list-item | |
451 | - v-for="item in info.journals" | |
452 | - :key="item.id" | |
453 | - @click="navigateToUrl(item.link)" | |
454 | - > | |
455 | - <v-list-item-content> | |
456 | - <v-list-item-title v-text="item.title"></v-list-item-title> | |
457 | - </v-list-item-content> | |
458 | - </v-list-item> | |
459 | - </v-list-item-group> | |
460 | - </v-list> --> | |
461 | -<!-- <v-list rounded>--> | |
462 | -<!-- <v-list-item-group v-model="selectedItem" color="primary">--> | |
463 | -<!-- <v-list-item--> | |
464 | -<!-- v-for="item in info.journals"--> | |
465 | -<!-- :key="item.id"--> | |
466 | -<!-- @click="navigateToUrl(item.link)"--> | |
467 | -<!-- >--> | |
468 | -<!-- <v-list-item-content>--> | |
469 | -<!-- <v-hover v-slot:default="{ isHovering, props }">--> | |
470 | -<!-- <div v-bind="props">--> | |
471 | -<!-- <v-list-item-title--> | |
472 | -<!-- v-text="item.title"--> | |
473 | -<!-- style="--> | |
474 | -<!-- overflow: hidden;--> | |
475 | -<!-- text-overflow: ellipsis;--> | |
476 | -<!-- white-space: nowrap;--> | |
477 | -<!-- "--> | |
478 | -<!-- ></v-list-item-title>--> | |
479 | -<!-- <span v-if="isHovering" bottom style="color: #1e88e5">{{--> | |
480 | -<!-- item.title--> | |
481 | -<!-- }}</span>--> | |
482 | -<!-- <v-tooltip v-if="isHovering" bottom>--> | |
483 | -<!-- <template v-slot:activator="{ props: tooltipProps }">--> | |
484 | -<!-- <span v-bind="tooltipProps">{{ item.title }}</span>--> | |
485 | -<!-- </template>--> | |
486 | -<!-- <span>{{ item.title }}</span>--> | |
487 | -<!-- </v-tooltip>--> | |
488 | -<!-- </div>--> | |
489 | -<!-- </v-hover>--> | |
490 | -<!-- </v-list-item-content>--> | |
491 | -<!-- </v-list-item>--> | |
492 | -<!-- </v-list-item-group>--> | |
493 | -<!-- </v-list>--> | |
351 | + </div> | |
352 | + </div> | |
353 | + <v-tabs | |
354 | + class="tabs" | |
355 | + v-model="tabRecomHot" | |
356 | + style="margin-top: 25px" | |
357 | + color="white" | |
358 | + bg-color="#eeeeee" | |
359 | + slider-color="blue-lighten-1" | |
360 | + selected-class="active" | |
361 | + v-if="recommendImagesHot[0] !== null" | |
362 | + > | |
363 | + <v-tab :value="1">Best Sellers</v-tab> | |
364 | + <!-- <v-tab :value="3">商品百科</v-tab> --> | |
365 | + </v-tabs> | |
366 | + <div id="image-container" v-if="recommendImagesHot[0] !== null"> | |
367 | + <div class="recommend-left-box"> | |
368 | + <v-img | |
369 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/76c987e13a334be481a346c19c2284f3qy4tjnxps7.png" | |
370 | + alt="往左移" | |
371 | + class="recommend-img-left" | |
372 | + @click="toggleRowLeft" | |
373 | + /> | |
374 | + </div> | |
375 | + <div class="image-row" id="row1"> | |
376 | + <!-- <img | |
377 | + v-for="(imageObj, index) in recommendImages.slice(0, 5)" | |
378 | + :key="'row1-' + index" | |
379 | + :src="imageObj[0]?.url" | |
380 | + :alt="'Image ' + (index + 1)" | |
381 | + style="margin: 0 5px; width: 200px; height: 200px" | |
382 | + /> --> | |
383 | + <div | |
384 | + v-for="(imageObj, index) in recommendImagesHot" | |
385 | + :key="'row1-' + index" | |
386 | + class="imageTotal" | |
387 | + > | |
388 | + <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank"> | |
389 | + <img | |
390 | + :src="imageObj[0]?.url" | |
391 | + :alt="'Image ' + (index + 1)" | |
392 | + class="item-imgHot" | |
393 | + /> | |
394 | + <span class="image-name"> | |
395 | + {{ imageObj[0]?.name }} | |
396 | + </span> | |
397 | + </a> | |
398 | + <div v-else style="width: 200px; height: 200px"></div> | |
399 | + </div> | |
400 | + </div> | |
401 | + <div class="recommend-right-box"> | |
402 | + <v-img | |
403 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/b5daa0a8f2f140f5b406e984c730a453iznzlekysg.png" | |
404 | + alt="往右移" | |
405 | + class="recommend-img-right" | |
406 | + @click="toggleRowRight" | |
407 | + /> | |
494 | 408 | </div> |
495 | 409 | </div> |
496 | 410 | <div class="social-share-container"> |
... | ... | @@ -545,21 +459,12 @@ const href1 = ref("/products"); |
545 | 459 | const href2 = ref("/products"); |
546 | 460 | const idHref = ref("/products"); |
547 | 461 | const hoveredItem = ref(null); |
548 | -const itemsss = [ | |
549 | - { | |
550 | - name: "Item #1", | |
551 | - id: 1, | |
552 | - }, | |
553 | - { | |
554 | - name: "Item #2", | |
555 | - id: 2, | |
556 | - }, | |
557 | - { | |
558 | - name: "Item #3", | |
559 | - id: 3, | |
560 | - }, | |
561 | -]; | |
562 | 462 | const productStore = useProductListStore(); |
463 | +const maxPage = ref(1); | |
464 | +const tabRecomHot = ref(); | |
465 | +const recommendListHot = ref(); | |
466 | +const recommendImagesHot = ref(); | |
467 | +const currentIndexHot = ref(1); | |
563 | 468 | const currentUrl = ref("https://www.canrud.com/products"); |
564 | 469 | // 定义单个 item 的接口 |
565 | 470 | interface BreadcrumbItem { |
... | ... | @@ -610,6 +515,70 @@ let { data: resData } = await useAsyncData( |
610 | 515 | server: true, // 仅在服务器端获取数据 |
611 | 516 | } |
612 | 517 | ); |
518 | +const loadHotProducts = async () => { | |
519 | + let { data: hotProducts } = await useAsyncData( | |
520 | + "hotProducts", | |
521 | + () => | |
522 | + $fetch("/shop/product/hotProducts", { | |
523 | + method: "GET", | |
524 | + params: { | |
525 | + pageNo: currentIndexHot.value, | |
526 | + pageSize: 5, | |
527 | + }, | |
528 | + }), | |
529 | + { | |
530 | + server: true, // 仅在服务器端获取数据 | |
531 | + } | |
532 | + ); | |
533 | + recommendListHot.value = hotProducts.value.data.records; | |
534 | + maxPage.value = hotProducts.value.data.pages; | |
535 | + // recommendImages.value = recommendList.value.slice(0, 10).map((item) => { | |
536 | + recommendImagesHot.value = Array.from({ length: 5 }).map((_, index) => { | |
537 | + const item = recommendListHot.value[index]; | |
538 | + if (!item) { | |
539 | + return null; | |
540 | + } | |
541 | + // 检查 productimageliststore 是否为字符串格式,如果是,则尝试解析 | |
542 | + if (typeof item.productimageliststore === "string") { | |
543 | + try { | |
544 | + item.productimageliststore = JSON.parse(item.productimageliststore); | |
545 | + } catch (error) { | |
546 | + item.productimageliststore = []; // 解析失败时,设置为空数组 | |
547 | + } | |
548 | + } | |
549 | + const ree = (item.productimageliststore = item?.productimageliststore.map( | |
550 | + (productItem: ProductImage) => ({ | |
551 | + ...productItem, | |
552 | + // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`, | |
553 | + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`, | |
554 | + name: item.name, | |
555 | + productUrl: `https://www.canrud.com/products/detail/${item.id}`, | |
556 | + }) | |
557 | + )); | |
558 | + return ree; | |
559 | + }); | |
560 | +}; | |
561 | +const toggleRowLeft = () => { | |
562 | + if (currentIndex.value !== 1) { | |
563 | + currentIndex.value--; | |
564 | + } else if (currentIndex.value == 1) { | |
565 | + currentIndex.value = maxPage.value; | |
566 | + } | |
567 | +}; | |
568 | +const toggleRowRight = () => { | |
569 | + if (currentIndex.value < maxPage.value) { | |
570 | + currentIndex.value++; | |
571 | + } else if (currentIndex.value == maxPage.value) { | |
572 | + currentIndex.value = 1; | |
573 | + } | |
574 | +}; | |
575 | +watch(currentIndexHot, (newIndex) => { | |
576 | + loadHotProducts(); // Call loadHotProducts when currentIndex changes | |
577 | +}); | |
578 | + | |
579 | +// Initial load of hot products | |
580 | +await loadHotProducts(); // Load hot products the first time | |
581 | + | |
613 | 582 | watchEffect(() => { |
614 | 583 | currentUrl.value = "https://www.canrud.com/products/detail/" + info.id; |
615 | 584 | if (info?.productCrumbsVO?.category1 && productStore.keyword) { |
... | ... | @@ -712,9 +681,9 @@ watchEffect(() => { |
712 | 681 | (productItem: ProductImage) => ({ |
713 | 682 | ...productItem, |
714 | 683 | // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`, |
715 | - url: `/api/show/image?fileKey=${productItem.fileKey}&psize=p512`, | |
684 | + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`, | |
716 | 685 | name: item.name, |
717 | - productUrl: `http://www.canrud.com/products/detail/${item.id}`, | |
686 | + productUrl: `https://www.canrud.com/products/detail/${item.id}`, | |
718 | 687 | }) |
719 | 688 | )); |
720 | 689 | return ree; |
... | ... | @@ -804,23 +773,80 @@ th { |
804 | 773 | color: #1e88e5; |
805 | 774 | } |
806 | 775 | |
807 | -#image-container { | |
808 | - display: flex; | |
809 | - align-items: center; | |
810 | - justify-content: center; | |
811 | - height: 320px; | |
812 | - margin-top: 10px; | |
813 | - margin-bottom: 10px; | |
776 | +@media screen and (min-width: 1537px) { | |
777 | + #image-container { | |
778 | + display: flex; | |
779 | + align-items: center; | |
780 | + justify-content: center; | |
781 | + height: 320px; | |
782 | + margin: 10px auto 100px; | |
783 | + width: 80%; | |
784 | + } | |
785 | +} | |
786 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
787 | + #image-container { | |
788 | + display: flex; | |
789 | + align-items: center; | |
790 | + justify-content: center; | |
791 | + height: 320px; | |
792 | + margin: 10px auto 0px; | |
793 | + width: 80%; | |
794 | + padding: 0; | |
795 | + } | |
814 | 796 | } |
815 | - | |
816 | 797 | .image-row { |
817 | 798 | display: flex; |
818 | 799 | height: 245px; |
819 | 800 | } |
820 | - | |
821 | -.image-row img { | |
822 | - width: 120px; | |
823 | - height: 120px; | |
801 | +@media screen and (min-width: 1537px) { | |
802 | + .imageTotal { | |
803 | + display: inline-block; | |
804 | + margin: 0 5px; | |
805 | + text-align: center; | |
806 | + width: 315px; | |
807 | + } | |
808 | +} | |
809 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
810 | + .imageTotal { | |
811 | + display: inline-block; | |
812 | + margin: 0 5px; | |
813 | + text-align: center; | |
814 | + width: 200px; | |
815 | + } | |
816 | +} | |
817 | +@media screen and (min-width: 1537px) { | |
818 | + .image-row img { | |
819 | + width: 240px; | |
820 | + height: 240px; | |
821 | + } | |
822 | +} | |
823 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
824 | + .image-row img { | |
825 | + width: 140px; | |
826 | + height: 140px; | |
827 | + } | |
828 | +} | |
829 | +@media screen and (min-width: 1537px) { | |
830 | + .image-name { | |
831 | + display: block; | |
832 | + margin-top: 5px; | |
833 | + font-size: 16px; | |
834 | + width: 180px; | |
835 | + color: #555; | |
836 | + text-align: left; | |
837 | + margin-left: 60px; | |
838 | + } | |
839 | +} | |
840 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
841 | + .image-name { | |
842 | + display: block; | |
843 | + margin-top: 5px; | |
844 | + font-size: 16px; | |
845 | + width: 180px; | |
846 | + color: #555; | |
847 | + text-align: left; | |
848 | + margin-left: 10px; | |
849 | + } | |
824 | 850 | } |
825 | 851 | |
826 | 852 | button .recommendButton { |
... | ... | @@ -857,6 +883,7 @@ button .recommendButton { |
857 | 883 | display: flex; |
858 | 884 | flex-direction: row; /* 父容器横向排列 */ |
859 | 885 | gap: 1rem; /* 设置每个分享项之间的间距 */ |
886 | + margin-top: 40px; | |
860 | 887 | } |
861 | 888 | |
862 | 889 | .social-share-item { |
... | ... | @@ -873,11 +900,11 @@ button .recommendButton { |
873 | 900 | |
874 | 901 | .title { |
875 | 902 | font-size: 15px; /* 设置字体大小为24px */ |
876 | - color: black; /* 设置字体颜色为黑色 */ | |
903 | + color: black; /* 设置字体颜色为黑色 */ | |
877 | 904 | display: -webkit-box; /* 使用盒模型显示多行文本 */ |
878 | 905 | -webkit-line-clamp: 2; /* 限制为两行 */ |
879 | 906 | -webkit-box-orient: vertical; /* 盒子方向为垂直 */ |
880 | - overflow: hidden; /* 超过部分隐藏 */ | |
907 | + overflow: hidden; /* 超过部分隐藏 */ | |
881 | 908 | transition: max-height 0.3s ease; /* 过渡效果 */ |
882 | 909 | } |
883 | 910 | |
... | ... | @@ -885,6 +912,6 @@ button .recommendButton { |
885 | 912 | display: block; /* 当悬浮时显示为块级元素 */ |
886 | 913 | color: #1e88e5; |
887 | 914 | white-space: normal; /* 允许换行 */ |
888 | - overflow: visible; /* 显示全部内容 */ | |
915 | + overflow: visible; /* 显示全部内容 */ | |
889 | 916 | } |
890 | 917 | </style> | ... | ... |
nuxt.config.ts
... | ... | @@ -41,8 +41,8 @@ export default defineNuxtConfig({ |
41 | 41 | nitro: { |
42 | 42 | devProxy: { |
43 | 43 | "/shop": { |
44 | - target: "http://47.89.254.121:8002/shop", // 线上代理地址 | |
45 | - // target: "http://127.0.0.1:8002/shop", | |
44 | + // target: "http://47.89.254.121:8002/shop", // 线上代理地址 | |
45 | + target: "http://127.0.0.1:8002/shop", | |
46 | 46 | // target: process.env.BASE_URL || 'http://39.108.227.113:8002/shop', // 目标接口域名 |
47 | 47 | changeOrigin: true, // 表示是否跨域 |
48 | 48 | }, |
... | ... | @@ -50,8 +50,8 @@ export default defineNuxtConfig({ |
50 | 50 | // 该配置用于服务端请求转发 |
51 | 51 | routeRules: { |
52 | 52 | "/shop/**": { |
53 | - proxy: "http://47.89.254.121:8002/shop/**", | |
54 | - // proxy: "http://127.0.0.1:8002/shop/**", | |
53 | + // proxy: "http://47.89.254.121:8002/shop/**", | |
54 | + proxy: "http://127.0.0.1:8002/shop/**", | |
55 | 55 | // proxy: process.env.BASE_URL || 'http://39.108.227.113:8002/shop/**' |
56 | 56 | }, |
57 | 57 | }, | ... | ... |
pages/index.vue
1 | 1 | <template> |
2 | 2 | <v-rows class="tw-w-full"> |
3 | - <v-carousel hide-delimiter-background show-arrows="hover" height="auto" v-if="!isMobile()"> | |
4 | - <v-carousel-item v-for="banner in banners" :src="banner" cover alt="canrud" :key="banner"> | |
3 | + <v-carousel | |
4 | + hide-delimiter-background | |
5 | + show-arrows="hover" | |
6 | + height="auto" | |
7 | + v-if="!isMobile()" | |
8 | + > | |
9 | + <v-carousel-item | |
10 | + v-for="banner in banners" | |
11 | + :src="banner" | |
12 | + cover | |
13 | + alt="canrud" | |
14 | + :key="banner" | |
15 | + > | |
5 | 16 | </v-carousel-item> |
6 | 17 | </v-carousel> |
7 | - <v-carousel hide-delimiter-background show-arrows="hover" height="auto" v-if="isMobile()"> | |
8 | - <v-carousel-item v-for="banner in mobileBanners" :src="banner" cover alt="canrud" :key="banner"> | |
18 | + <v-carousel | |
19 | + hide-delimiter-background | |
20 | + show-arrows="hover" | |
21 | + height="auto" | |
22 | + v-if="isMobile()" | |
23 | + > | |
24 | + <v-carousel-item | |
25 | + v-for="banner in mobileBanners" | |
26 | + :src="banner" | |
27 | + cover | |
28 | + alt="canrud" | |
29 | + :key="banner" | |
30 | + > | |
9 | 31 | </v-carousel-item> |
10 | 32 | </v-carousel> |
11 | 33 | </v-rows> |
12 | 34 | <!-- 能源材料 --> |
13 | 35 | <div class="tw-py-8 py-sm-16"> |
14 | 36 | <v-container> |
15 | - <MainTitleListOdd title="Material Reagents" :list="materials" | |
16 | - desc="Leading global provider of energy storage research materials and providing other professional/universal experimental materials. " /> | |
37 | + <MainTitleListOdd | |
38 | + title="Material Reagents" | |
39 | + :list="materials" | |
40 | + desc="Leading global provider of energy storage research materials and providing other professional/universal experimental materials. " | |
41 | + /> | |
17 | 42 | </v-container> |
18 | 43 | </div> |
19 | 44 | |
20 | 45 | <!-- 设备 --> |
21 | 46 | <div class="bg-grey-lighten-5 tw-py-8 py-sm-16"> |
22 | 47 | <v-container> |
23 | - <MainTitleList title="Lab Device" listType="equipment" | |
48 | + <MainTitleList | |
49 | + title="Lab Device" | |
50 | + listType="equipment" | |
24 | 51 | :list="lab.list.map((item) => ({ ...item, href: '/products' }))" |
25 | 52 | desc="Self-built High-precision Machining Center with Powerful Design and Manufacturing Capabilities. " |
26 | - href="/equipment" /> | |
53 | + href="/equipment" | |
54 | + /> | |
27 | 55 | </v-container> |
28 | 56 | </div> |
29 | 57 | |
30 | 58 | <!-- Customized Battery --> |
31 | 59 | <div class="tw-py-8 py-sm-16"> |
32 | 60 | <v-container> |
33 | - <MainTitleList :title="('Customized Battery')" :list="batteries" href="/customize" | |
34 | - desc="200mAh~10Ah, Winding/Stacking, Unfilled/Filled Electrolyte Cells, Three-Electrode, and More. " /> | |
61 | + <MainTitleList | |
62 | + :title="'Customized Battery'" | |
63 | + :list="batteries" | |
64 | + href="/customize" | |
65 | + desc="200mAh~10Ah, Winding/Stacking, Unfilled/Filled Electrolyte Cells, Three-Electrode, and More. " | |
66 | + /> | |
35 | 67 | </v-container> |
36 | 68 | </div> |
37 | 69 | <!-- Testing --> |
38 | 70 | <div class="bg-grey-lighten-5 tw-py-8 py-sm-16"> |
39 | 71 | <v-container> |
40 | - <MainTitleList title="Testing" :list="tests" href="/test" | |
41 | - desc="Self built testing center and signed strategic cooperation with ATL, Tsinghua and other units. " /> | |
72 | + <MainTitleList | |
73 | + title="Testing" | |
74 | + :list="tests" | |
75 | + href="/test" | |
76 | + desc="Self built testing center and signed strategic cooperation with ATL, Tsinghua and other units. " | |
77 | + /> | |
42 | 78 | </v-container> |
43 | 79 | </div> |
44 | 80 | <!-- Pack --> |
45 | 81 | <div class="pt-8 pb-8 pt pt-sm-16 pb-sm-32"> |
46 | 82 | <v-container> |
47 | - <MainTitleList title="Pack" href="/pack" :list="packs" | |
48 | - desc="Focusing on energy materials/new energy storage systems/modules and other fields, mastering advanced technologies to provide high-quality services. " /> | |
83 | + <MainTitleList | |
84 | + title="Pack" | |
85 | + href="/pack" | |
86 | + :list="packs" | |
87 | + desc="Focusing on energy materials/new energy storage systems/modules and other fields, mastering advanced technologies to provide high-quality services. " | |
88 | + /> | |
49 | 89 | </v-container> |
50 | 90 | </div> |
91 | + <v-tabs | |
92 | + class="tabs" | |
93 | + v-model="tabRecom" | |
94 | + color="white" | |
95 | + bg-color="#eeeeee" | |
96 | + slider-color="blue-lighten-1" | |
97 | + selected-class="active" | |
98 | + v-if="recommendImages[0] !== null && !isMobile()" | |
99 | + > | |
100 | + <v-tab :value="1">Best Sellers</v-tab> | |
101 | + <!-- <v-tab :value="3">商品百科</v-tab> --> | |
102 | + </v-tabs> | |
103 | + <div id="image-container" v-if="recommendImages[0] !== null && !isMobile()"> | |
104 | + <div class="recommend-left-box"> | |
105 | + <v-img | |
106 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/76c987e13a334be481a346c19c2284f3qy4tjnxps7.png" | |
107 | + alt="往左移" | |
108 | + class="recommend-img-left" | |
109 | + @click="toggleRowLeft" | |
110 | + /> | |
111 | + </div> | |
112 | + <div class="image-row" id="row1"> | |
113 | + <!-- <img | |
114 | + v-for="(imageObj, index) in recommendImages.slice(0, 5)" | |
115 | + :key="'row1-' + index" | |
116 | + :src="imageObj[0]?.url" | |
117 | + :alt="'Image ' + (index + 1)" | |
118 | + style="margin: 0 5px; width: 200px; height: 200px" | |
119 | + /> --> | |
120 | + <div | |
121 | + v-for="(imageObj, index) in recommendImages" | |
122 | + :key="'row1-' + index" | |
123 | + class="imageTotal" | |
124 | + > | |
125 | + <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank"> | |
126 | + <img | |
127 | + :src="imageObj[0]?.url" | |
128 | + :alt="'Image ' + (index + 1)" | |
129 | + class="item-imgHot" | |
130 | + /> | |
131 | + <span class="image-name"> | |
132 | + {{ imageObj[0]?.name }} | |
133 | + </span> | |
134 | + </a> | |
135 | + <div v-else style="width: 200px; height: 200px"></div> | |
136 | + </div> | |
137 | + </div> | |
138 | + <div class="recommend-right-box"> | |
139 | + <v-img | |
140 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/b5daa0a8f2f140f5b406e984c730a453iznzlekysg.png" | |
141 | + alt="往右移" | |
142 | + class="recommend-img-right" | |
143 | + @click="toggleRowRight" | |
144 | + /> | |
145 | + </div> | |
146 | + </div> | |
51 | 147 | </template> |
52 | 148 | |
53 | 149 | <script setup lang="ts"> |
54 | -import MainTitleList from '../components/MainTitleList.vue' | |
55 | -import MainTitleListOdd from '../components/MainTitleListOdd.vue' | |
56 | -import { useCategoryStore } from '../stores/category' | |
57 | -import { computed } from 'vue' | |
58 | -import { isMobile } from '../utils' | |
150 | +import MainTitleList from "../components/MainTitleList.vue"; | |
151 | +import MainTitleListOdd from "../components/MainTitleListOdd.vue"; | |
152 | +import { useCategoryStore } from "../stores/category"; | |
153 | +import { computed, onMounted, reactive, ref } from "vue"; | |
154 | +import { isMobile } from "../utils"; | |
155 | + | |
156 | +const maxPage = ref(1); | |
157 | +const tabRecom = ref(); | |
158 | +const recommendList = ref(); | |
159 | +const recommendImages = ref(); | |
160 | +const currentIndex = ref(1); | |
161 | +const flag = ref(false); | |
162 | +const loadHotProducts = async () => { | |
163 | + let { data: hotProducts } = await useAsyncData( | |
164 | + "hotProducts", | |
165 | + () => | |
166 | + $fetch("/shop/product/hotProducts", { | |
167 | + method: "GET", | |
168 | + params: { | |
169 | + pageNo: currentIndex.value, | |
170 | + pageSize: 5, | |
171 | + }, | |
172 | + }), | |
173 | + { | |
174 | + server: true, // 仅在服务器端获取数据 | |
175 | + } | |
176 | + ); | |
177 | + recommendList.value = hotProducts.value.data.records; | |
178 | + maxPage.value = hotProducts.value.data.pages; | |
179 | + // recommendImages.value = recommendList.value.slice(0, 10).map((item) => { | |
180 | + recommendImages.value = Array.from({ length: 5 }).map((_, index) => { | |
181 | + const item = recommendList.value[index]; | |
182 | + if (!item) { | |
183 | + return null; | |
184 | + } | |
185 | + // 检查 productimageliststore 是否为字符串格式,如果是,则尝试解析 | |
186 | + if (typeof item.productimageliststore === "string") { | |
187 | + try { | |
188 | + item.productimageliststore = JSON.parse(item.productimageliststore); | |
189 | + } catch (error) { | |
190 | + item.productimageliststore = []; // 解析失败时,设置为空数组 | |
191 | + } | |
192 | + } | |
193 | + const ree = (item.productimageliststore = item?.productimageliststore.map( | |
194 | + (productItem: ProductImage) => ({ | |
195 | + ...productItem, | |
196 | + // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`, | |
197 | + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`, | |
198 | + name: item.name, | |
199 | + productUrl: `https://www.canrud.com/products/detail/${item.id}`, | |
200 | + }) | |
201 | + )); | |
202 | + return ree; | |
203 | + }); | |
204 | +}; | |
205 | +const toggleRowLeft = () => { | |
206 | + if (currentIndex.value !== 1) { | |
207 | + currentIndex.value--; | |
208 | + } else if (currentIndex.value == 1) { | |
209 | + currentIndex.value = maxPage.value; | |
210 | + } | |
211 | +}; | |
212 | +const toggleRowRight = () => { | |
213 | + if (currentIndex.value < maxPage.value) { | |
214 | + currentIndex.value++; | |
215 | + } else if (currentIndex.value == maxPage.value) { | |
216 | + currentIndex.value = 1; | |
217 | + } | |
218 | +}; | |
219 | +watch(currentIndex, (newIndex) => { | |
220 | + loadHotProducts(); // Call loadHotProducts when currentIndex changes | |
221 | +}); | |
222 | + | |
223 | +// Initial load of hot products | |
224 | +await loadHotProducts(); // Load hot products the first time | |
225 | + | |
59 | 226 | onMounted(() => { |
60 | - console.log('%c [ onMounted ]-10', 'font-size:13px; background:pink; color:#bf2c9f;', 111) | |
61 | -}) | |
227 | + console.log( | |
228 | + "%c [ onMounted ]-10", | |
229 | + "font-size:13px; background:pink; color:#bf2c9f;", | |
230 | + 111 | |
231 | + ); | |
232 | +}); | |
62 | 233 | useHead({ |
63 | - title: 'canrud', | |
234 | + title: "canrud", | |
64 | 235 | meta: [ |
65 | 236 | { |
66 | - name: 'title', | |
67 | - content: "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at contact@canrd.com or call +86 19867737979 to explore our innovative offerings. Together, let's shape a greener, brighter world!" | |
68 | - }, { | |
69 | - name: 'keywords', | |
237 | + name: "title", | |
70 | 238 | content: |
71 | - '科路得,canrd,canrud,Energy Storage Research,Lithium Batteries Research,Material Reagents,Lab Device,Customized Battery,Testing,Pack', | |
72 | - }, { | |
239 | + "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at contact@canrd.com or call +86 19867737979 to explore our innovative offerings. Together, let's shape a greener, brighter world!", | |
240 | + }, | |
241 | + { | |
242 | + name: "keywords", | |
243 | + content: | |
244 | + "科路得,canrd,canrud,Energy Storage Research,Lithium Batteries Research,Material Reagents,Lab Device,Customized Battery,Testing,Pack", | |
245 | + }, | |
246 | + { | |
73 | 247 | name: "description", |
74 | 248 | content: |
75 | - "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at contact@canrd.com or call +86 19867737979 to explore our innovative offerings. Together, let's shape a greener, brighter world!" | |
76 | - }], | |
77 | - link: [ | |
78 | - { rel: 'preload', href: '/banner/banner1.jpg', as: 'image' } | |
79 | - ] | |
80 | -}) | |
249 | + "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at contact@canrd.com or call +86 19867737979 to explore our innovative offerings. Together, let's shape a greener, brighter world!", | |
250 | + }, | |
251 | + ], | |
252 | + link: [{ rel: "preload", href: "/banner/banner1.jpg", as: "image" }], | |
253 | +}); | |
81 | 254 | |
82 | 255 | // useAsyncData(async ({ app }) => { |
83 | 256 | // console.log('%c [ app ]-70', 'font-size:13px; background:pink; color:#bf2c9f;', app) |
... | ... | @@ -85,76 +258,245 @@ useHead({ |
85 | 258 | // app.head.meta = [ |
86 | 259 | // { |
87 | 260 | // name: 'description', |
88 | -// content: "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at | |
261 | +// content: "科路得,助您科研之路势在必得。Canrd aims to be the world's leading one-stop service provider in new energy research. With a dedication to excellence, we offer Material Reagents, Lab Devices, Customized Batteries, Testing, and Advanced Packaging for energy materials and storage systems. We master advanced technologies to provide high-quality solutions. Our team's quick responses ensure tailored and professional services to meet your unique needs. Contact us at | |
89 | 262 | // }] |
90 | 263 | // }) |
91 | -console.log(11) | |
264 | +console.log(11); | |
92 | 265 | |
93 | -const store = useCategoryStore() | |
266 | +const store = useCategoryStore(); | |
94 | 267 | |
95 | 268 | const lab = computed( |
96 | 269 | () => |
97 | 270 | store?.list?.[3] || { |
98 | - categoryDisplayName: '', | |
99 | - list: [] | |
271 | + categoryDisplayName: "", | |
272 | + list: [], | |
100 | 273 | } |
101 | -) | |
274 | +); | |
102 | 275 | |
103 | 276 | const banners = [ |
104 | - '/banner/banner1.jpg', | |
105 | - '/banner/banner2.jpg', | |
106 | - '/banner/banner3.jpg', | |
107 | - '/banner/banner5.jpg' | |
108 | -] | |
277 | + "/banner/banner1.jpg", | |
278 | + "/banner/banner2.jpg", | |
279 | + "/banner/banner3.jpg", | |
280 | + "/banner/banner5.jpg", | |
281 | +]; | |
109 | 282 | |
110 | 283 | const mobileBanners = [ |
111 | - '/mobile/banner-index1.png', | |
112 | - '/mobile/banner-index2.png', | |
113 | - '/mobile/banner-index3.png' | |
114 | -] | |
284 | + "/mobile/banner-index1.png", | |
285 | + "/mobile/banner-index2.png", | |
286 | + "/mobile/banner-index3.png", | |
287 | +]; | |
115 | 288 | |
116 | 289 | const materials = [ |
117 | - { name: 'Energy materials', imageUrl: '/home/1.jpg', href: '/products' }, | |
290 | + { name: "Energy materials", imageUrl: "/home/1.jpg", href: "/products" }, | |
118 | 291 | { |
119 | - name: 'Laboratory consumables', | |
120 | - imageUrl: '/home/2-Universal-consumables.png', | |
121 | - href: '/products' | |
292 | + name: "Laboratory consumables", | |
293 | + imageUrl: "/home/2-Universal-consumables.png", | |
294 | + href: "/products", | |
122 | 295 | }, |
123 | 296 | { |
124 | - name: 'Low-dimensional materials', | |
125 | - imageUrl: '/home/3-Low-dimensional-materials.png', | |
126 | - href: '/products' | |
127 | - } | |
128 | -] | |
297 | + name: "Low-dimensional materials", | |
298 | + imageUrl: "/home/3-Low-dimensional-materials.png", | |
299 | + href: "/products", | |
300 | + }, | |
301 | +]; | |
129 | 302 | |
130 | 303 | const tests = [ |
131 | 304 | { |
132 | - name: 'Electrochemical performance', | |
133 | - imageUrl: '/home/8_Electrochemical_performance.svg', | |
134 | - href: '/test' | |
305 | + name: "Electrochemical performance", | |
306 | + imageUrl: "/home/8_Electrochemical_performance.svg", | |
307 | + href: "/test", | |
308 | + }, | |
309 | + { | |
310 | + name: "Reliability testing", | |
311 | + imageUrl: "/home/9 Reliability testing.svg", | |
312 | + href: "/test", | |
135 | 313 | }, |
136 | - { name: 'Reliability testing', imageUrl: '/home/9 Reliability testing.svg', href: '/test' }, | |
137 | - { name: 'Material testing', imageUrl: '/home/10 Material testing.svg', href: '/test' }, | |
138 | - { name: 'Calibration', imageUrl: '/home/11 Calibration.svg', href: '/test' } | |
139 | -] | |
314 | + { | |
315 | + name: "Material testing", | |
316 | + imageUrl: "/home/10 Material testing.svg", | |
317 | + href: "/test", | |
318 | + }, | |
319 | + { name: "Calibration", imageUrl: "/home/11 Calibration.svg", href: "/test" }, | |
320 | +]; | |
140 | 321 | const batteries = [ |
141 | - { name: 'Material evaluation', imageUrl: '/home/4-Material-evaluation.png', href: '/customize' }, | |
142 | - { name: 'R&D foundry', imageUrl: '/home/5-R&D-foundry.png', href: '/customize' }, | |
143 | - { name: 'Chemical system', imageUrl: '/home/6-Chemical-system.png', href: '/customize' }, | |
144 | 322 | { |
145 | - name: 'Semi product customization', | |
146 | - imageUrl: '/home/7-Semi-product-customization.png', | |
147 | - href: '/customize' | |
148 | - } | |
149 | -] | |
323 | + name: "Material evaluation", | |
324 | + imageUrl: "/home/4-Material-evaluation.png", | |
325 | + href: "/customize", | |
326 | + }, | |
327 | + { | |
328 | + name: "R&D foundry", | |
329 | + imageUrl: "/home/5-R&D-foundry.png", | |
330 | + href: "/customize", | |
331 | + }, | |
332 | + { | |
333 | + name: "Chemical system", | |
334 | + imageUrl: "/home/6-Chemical-system.png", | |
335 | + href: "/customize", | |
336 | + }, | |
337 | + { | |
338 | + name: "Semi product customization", | |
339 | + imageUrl: "/home/7-Semi-product-customization.png", | |
340 | + href: "/customize", | |
341 | + }, | |
342 | +]; | |
150 | 343 | const packs = [ |
151 | - { name: 'Power bank', imageUrl: '/home/12-power-bank.png', href: '/pack' }, | |
152 | - { name: 'Energy storage', imageUrl: '/home/13-Energy-storage.png', href: '/pack' }, | |
153 | - { name: 'power tool', imageUrl: '/home/3-powertool.png', href: '/pack' }, | |
344 | + { name: "Power bank", imageUrl: "/home/12-power-bank.png", href: "/pack" }, | |
154 | 345 | { |
155 | - name: 'portable energy storage', | |
156 | - imageUrl: '/home/4-portableenergystorage.png', | |
157 | - href: '/pack' | |
158 | - } | |
159 | -] | |
346 | + name: "Energy storage", | |
347 | + imageUrl: "/home/13-Energy-storage.png", | |
348 | + href: "/pack", | |
349 | + }, | |
350 | + { name: "power tool", imageUrl: "/home/3-powertool.png", href: "/pack" }, | |
351 | + { | |
352 | + name: "portable energy storage", | |
353 | + imageUrl: "/home/4-portableenergystorage.png", | |
354 | + href: "/pack", | |
355 | + }, | |
356 | +]; | |
160 | 357 | </script> |
358 | +<style scoped> | |
359 | +@media screen and (min-width: 1537px) { | |
360 | + .tabs { | |
361 | + border-bottom: 2px solid #1f88e5; | |
362 | + margin: 10px auto 100px; | |
363 | + width: 85%; | |
364 | + } | |
365 | +} | |
366 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
367 | + .tabs { | |
368 | + border-bottom: 2px solid #1f88e5; | |
369 | + margin: 10px auto 20px; | |
370 | + width: 80%; | |
371 | + } | |
372 | +} | |
373 | + | |
374 | +.active { | |
375 | + background-color: #1086e8; | |
376 | +} | |
377 | + | |
378 | +/* #image-container { | |
379 | + display: flex; | |
380 | + align-items: center; | |
381 | + justify-content: center; | |
382 | + height: 320px; | |
383 | + margin: 10px auto 50px; | |
384 | + width: 80%; | |
385 | +} */ | |
386 | + | |
387 | +@media screen and (min-width: 1537px) { | |
388 | + #image-container { | |
389 | + display: flex; | |
390 | + align-items: center; | |
391 | + justify-content: center; | |
392 | + height: 320px; | |
393 | + margin: 10px auto 100px; | |
394 | + width: 80%; | |
395 | + } | |
396 | +} | |
397 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
398 | + #image-container { | |
399 | + display: flex; | |
400 | + align-items: center; | |
401 | + justify-content: center; | |
402 | + height: 320px; | |
403 | + margin: 10px auto 0px; | |
404 | + width: 80%; | |
405 | + } | |
406 | +} | |
407 | +.image-row { | |
408 | + display: flex; | |
409 | + height: 305px; | |
410 | +} | |
411 | +@media screen and (min-width: 1537px) { | |
412 | + .image-row { | |
413 | + display: flex; | |
414 | + height: 305px; | |
415 | + } | |
416 | +} | |
417 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
418 | + .image-row { | |
419 | + display: flex; | |
420 | + height: 245px; | |
421 | + } | |
422 | +} | |
423 | +@media screen and (min-width: 1537px) { | |
424 | + .imageTotal { | |
425 | + display: inline-block; | |
426 | + margin: 0 5px; | |
427 | + text-align: center; | |
428 | + width: 290px; | |
429 | + } | |
430 | +} | |
431 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
432 | + .imageTotal { | |
433 | + display: inline-block; | |
434 | + margin: 0 5px; | |
435 | + text-align: center; | |
436 | + width: 210px; | |
437 | + } | |
438 | +} | |
439 | +@media screen and (min-width: 1537px) { | |
440 | + .image-row img { | |
441 | + width: 240px; | |
442 | + height: 240px; | |
443 | + } | |
444 | +} | |
445 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
446 | + .image-row img { | |
447 | + width: 140px; | |
448 | + height: 140px; | |
449 | + } | |
450 | +} | |
451 | +@media screen and (min-width: 1537px) { | |
452 | + .image-name { | |
453 | + display: block; | |
454 | + margin-top: 5px; | |
455 | + font-size: 16px; | |
456 | + width: 180px; | |
457 | + color: #555; | |
458 | + text-align: left; | |
459 | + margin-left: 50px; | |
460 | + } | |
461 | +} | |
462 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
463 | + .image-name { | |
464 | + display: block; | |
465 | + margin-top: 5px; | |
466 | + font-size: 16px; | |
467 | + width: 180px; | |
468 | + color: #555; | |
469 | + text-align: left; | |
470 | + margin-left: 10px; | |
471 | + } | |
472 | +} | |
473 | +button .recommendButton { | |
474 | + margin: 0 0px; | |
475 | + cursor: pointer; | |
476 | +} | |
477 | + | |
478 | +.recommend-left-box { | |
479 | +} | |
480 | + | |
481 | +.recommend-img-left { | |
482 | + width: 26px; | |
483 | + height: 27px; | |
484 | + margin-right: 30px; | |
485 | +} | |
486 | + | |
487 | +.recommend-img-left:hover { | |
488 | + cursor: pointer; | |
489 | +} | |
490 | +.recommend-right-box { | |
491 | +} | |
492 | + | |
493 | +.recommend-img-right { | |
494 | + width: 26px; | |
495 | + height: 27px; | |
496 | + margin-left: 30px; | |
497 | +} | |
498 | + | |
499 | +.recommend-img-right:hover { | |
500 | + cursor: pointer; | |
501 | +} | |
502 | +</style> | ... | ... |
pages/products/index.vue
1 | 1 | <template> |
2 | - <div class="tw-m-auto tw-pb-[64px]"> | |
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 | 5 | <v-container class=""> |
... | ... | @@ -70,11 +70,72 @@ |
70 | 70 | total-visible="5" |
71 | 71 | ></v-pagination></v-col |
72 | 72 | ></v-row> |
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 | |
87 | + id="image-container" | |
88 | + v-if="recommendImages[0] !== null && !isMobile()" | |
89 | + > | |
90 | + <div class="recommend-left-box"> | |
91 | + <v-img | |
92 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/76c987e13a334be481a346c19c2284f3qy4tjnxps7.png" | |
93 | + alt="往左移" | |
94 | + class="recommend-img-left" | |
95 | + @click="toggleRowLeft" | |
96 | + /> | |
97 | + </div> | |
98 | + <div class="image-row" id="row1"> | |
99 | + <!-- <img | |
100 | + v-for="(imageObj, index) in recommendImages.slice(0, 5)" | |
101 | + :key="'row1-' + index" | |
102 | + :src="imageObj[0]?.url" | |
103 | + :alt="'Image ' + (index + 1)" | |
104 | + style="margin: 0 5px; width: 200px; height: 200px" | |
105 | + /> --> | |
106 | + <div | |
107 | + v-for="(imageObj, index) in recommendImages" | |
108 | + :key="'row1-' + index" | |
109 | + class="imageTotal" | |
110 | + > | |
111 | + <a v-if="imageObj" :href="imageObj[0]?.productUrl" target="_blank"> | |
112 | + <img | |
113 | + :src="imageObj[0]?.url" | |
114 | + :alt="'Image ' + (index + 1)" | |
115 | + class="item-imgHot" | |
116 | + /> | |
117 | + <span class="image-name"> | |
118 | + {{ imageObj[0]?.name }} | |
119 | + </span> | |
120 | + </a> | |
121 | + <div v-else style="width: 200px; height: 200px"></div> | |
122 | + </div> | |
123 | + </div> | |
124 | + <div class="recommend-right-box"> | |
125 | + <v-img | |
126 | + src="https://m-canrd.oss-cn-shenzhen.aliyuncs.com/crmebimage/public/maintain/2024/09/14/b5daa0a8f2f140f5b406e984c730a453iznzlekysg.png" | |
127 | + alt="往右移" | |
128 | + class="recommend-img-right" | |
129 | + @click="toggleRowRight" | |
130 | + /> | |
131 | + </div> | |
132 | + </div> | |
73 | 133 | </v-container> |
74 | 134 | </div> |
75 | 135 | </template> |
76 | 136 | |
77 | 137 | <script setup lang="ts"> |
138 | +import type { ProductImage } from "~/type"; | |
78 | 139 | import { isMobile, isEqual } from "~/utils"; |
79 | 140 | import { useProductListStore } from "~/stores/product_list"; |
80 | 141 | import { useCategoryStore } from "~/stores/category"; |
... | ... | @@ -89,7 +150,76 @@ const route = useRoute(); // 获取路由信息 |
89 | 150 | const router = useRouter(); // 获取路由信息 |
90 | 151 | const title = ref(""); |
91 | 152 | const keywordTitle = ref(""); |
153 | +const maxPage = ref(1); | |
154 | +const tabRecom = ref(); | |
155 | +const recommendList = ref(); | |
156 | +const recommendImages = ref(); | |
157 | +const currentIndex = ref(1); | |
92 | 158 | const isOrNotMobile = isMobile(); |
159 | +const loadHotProducts = async () => { | |
160 | + let { data: hotProducts } = await useAsyncData( | |
161 | + "hotProducts", | |
162 | + () => | |
163 | + $fetch("/shop/product/hotProducts", { | |
164 | + method: "GET", | |
165 | + params: { | |
166 | + pageNo: currentIndex.value, | |
167 | + pageSize: 5, | |
168 | + }, | |
169 | + }), | |
170 | + { | |
171 | + server: true, // 仅在服务器端获取数据 | |
172 | + } | |
173 | + ); | |
174 | + recommendList.value = hotProducts.value.data.records; | |
175 | + maxPage.value = hotProducts.value.data.pages; | |
176 | + // recommendImages.value = recommendList.value.slice(0, 10).map((item) => { | |
177 | + recommendImages.value = Array.from({ length: 5 }).map((_, index) => { | |
178 | + const item = recommendList.value[index]; | |
179 | + if (!item) { | |
180 | + return null; | |
181 | + } | |
182 | + // 检查 productimageliststore 是否为字符串格式,如果是,则尝试解析 | |
183 | + if (typeof item.productimageliststore === "string") { | |
184 | + try { | |
185 | + item.productimageliststore = JSON.parse(item.productimageliststore); | |
186 | + } catch (error) { | |
187 | + item.productimageliststore = []; // 解析失败时,设置为空数组 | |
188 | + } | |
189 | + } | |
190 | + const ree = (item.productimageliststore = item?.productimageliststore.map( | |
191 | + (productItem: ProductImage) => ({ | |
192 | + ...productItem, | |
193 | + // url: `http://112.74.45.244:8100/api/show/image?fileKey=${item.fileKey}`, | |
194 | + url: `https://www.canrud.com/api/show/image?fileKey=${productItem.fileKey}&psize=p256`, | |
195 | + name: item.name, | |
196 | + productUrl: `https://www.canrud.com/products/detail/${item.id}`, | |
197 | + }) | |
198 | + )); | |
199 | + return ree; | |
200 | + }); | |
201 | +}; | |
202 | +const toggleRowLeft = () => { | |
203 | + if (currentIndex.value !== 1) { | |
204 | + currentIndex.value--; | |
205 | + } else if (currentIndex.value == 1) { | |
206 | + currentIndex.value = maxPage.value; | |
207 | + } | |
208 | +}; | |
209 | +const toggleRowRight = () => { | |
210 | + if (currentIndex.value < maxPage.value) { | |
211 | + currentIndex.value++; | |
212 | + } else if (currentIndex.value == maxPage.value) { | |
213 | + currentIndex.value = 1; | |
214 | + } | |
215 | +}; | |
216 | +watch(currentIndex, (newIndex) => { | |
217 | + loadHotProducts(); // Call loadHotProducts when currentIndex changes | |
218 | +}); | |
219 | + | |
220 | +// Initial load of hot products | |
221 | +await loadHotProducts(); // Load hot products the first time | |
222 | + | |
93 | 223 | watchEffect(() => { |
94 | 224 | // 遍历数组 |
95 | 225 | if (router.currentRoute.value.query.categories) { |
... | ... | @@ -285,4 +415,118 @@ const length = computed(() => |
285 | 415 | -webkit-line-clamp: 2; |
286 | 416 | -webkit-box-orient: vertical; |
287 | 417 | } |
418 | + | |
419 | +.tabs { | |
420 | + border-bottom: 2px solid #1f88e5; | |
421 | +} | |
422 | + | |
423 | +.active { | |
424 | + background-color: #1086e8; | |
425 | +} | |
426 | + | |
427 | +@media screen and (min-width: 1537px) { | |
428 | + #image-container { | |
429 | + display: flex; | |
430 | + align-items: center; | |
431 | + justify-content: center; | |
432 | + height: 320px; | |
433 | + margin: 10px auto 100px; | |
434 | + width: 80%; | |
435 | + } | |
436 | +} | |
437 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
438 | + #image-container { | |
439 | + display: flex; | |
440 | + align-items: center; | |
441 | + justify-content: center; | |
442 | + height: 320px; | |
443 | + margin: 10px auto 0px; | |
444 | + width: 80%; | |
445 | + padding: 0; | |
446 | + } | |
447 | +} | |
448 | +.image-row { | |
449 | + display: flex; | |
450 | + height: 245px; | |
451 | +} | |
452 | +@media screen and (min-width: 1537px) { | |
453 | + .imageTotal { | |
454 | + display: inline-block; | |
455 | + margin: 0 5px; | |
456 | + text-align: center; | |
457 | + width: 300px; | |
458 | + } | |
459 | +} | |
460 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
461 | + .imageTotal { | |
462 | + display: inline-block; | |
463 | + margin: 0 5px; | |
464 | + text-align: center; | |
465 | + width: 200px; | |
466 | + } | |
467 | +} | |
468 | +@media screen and (min-width: 1537px) { | |
469 | + .image-row img { | |
470 | + width: 240px; | |
471 | + height: 240px; | |
472 | + } | |
473 | +} | |
474 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
475 | + .image-row img { | |
476 | + width: 140px; | |
477 | + height: 140px; | |
478 | + } | |
479 | +} | |
480 | +@media screen and (min-width: 1537px) { | |
481 | + .image-name { | |
482 | + display: block; | |
483 | + margin-top: 5px; | |
484 | + font-size: 16px; | |
485 | + width: 180px; | |
486 | + color: #555; | |
487 | + text-align: left; | |
488 | + margin-left: 50px; | |
489 | + } | |
490 | +} | |
491 | +@media screen and (max-width: 1536px) and (min-width: 1281px) { | |
492 | + .image-name { | |
493 | + display: block; | |
494 | + margin-top: 5px; | |
495 | + font-size: 16px; | |
496 | + width: 180px; | |
497 | + color: #555; | |
498 | + text-align: left; | |
499 | + margin-left: 10px; | |
500 | + } | |
501 | +} | |
502 | + | |
503 | +button .recommendButton { | |
504 | + margin: 0 0px; | |
505 | + cursor: pointer; | |
506 | +} | |
507 | + | |
508 | +.recommend-left-box { | |
509 | +} | |
510 | + | |
511 | +.recommend-img-left { | |
512 | + width: 26px; | |
513 | + height: 27px; | |
514 | + margin-right: 30px; | |
515 | +} | |
516 | + | |
517 | +.recommend-img-left:hover { | |
518 | + cursor: pointer; | |
519 | +} | |
520 | +.recommend-right-box { | |
521 | +} | |
522 | + | |
523 | +.recommend-img-right { | |
524 | + width: 26px; | |
525 | + height: 27px; | |
526 | + margin-left: 30px; | |
527 | +} | |
528 | + | |
529 | +.recommend-img-right:hover { | |
530 | + cursor: pointer; | |
531 | +} | |
288 | 532 | </style> | ... | ... |