From 20f77ff88620f618ddb843ee0797da35526fca98 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Thu, 14 May 2026 18:18:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A6=96=E9=A1=B5=E7=9A=84?= =?UTF-8?q?=E7=94=BB=E5=86=8C=E4=B8=BAswiper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/brochure/shared.ts | 97 ++++++++++++++++++++ src/pages/brochure/viewer.tsx | 92 ++----------------- src/pages/index/CatalogShowcase.scss | 93 +++++++++++++++++++ src/pages/index/CatalogShowcase.tsx | 131 ++++++++++++++++++++------- 4 files changed, 294 insertions(+), 119 deletions(-) create mode 100644 src/pages/brochure/shared.ts diff --git a/src/pages/brochure/shared.ts b/src/pages/brochure/shared.ts new file mode 100644 index 0000000..a14915e --- /dev/null +++ b/src/pages/brochure/shared.ts @@ -0,0 +1,97 @@ +import Taro from '@tarojs/taro' + +const PREVIEW_TITLE = '品牌画册' +const BROCHURE_API_BASE = 'https://cms-api.websoft.top/api' + +interface BrochureGoods { + goodsId?: number + name?: string + goodsName?: string + files?: string +} + +export interface BrochurePayload { + title: string + images: string[] +} + +const parseFiles = (files?: string): string[] => { + if (!files) { + return [] + } + + try { + const parsed = JSON.parse(files) + + if (Array.isArray(parsed)) { + return parsed.reduce((result, item: any) => { + if (typeof item === 'string') { + result.push(item) + return result + } + + if (item && typeof item.url === 'string') { + result.push(item.url) + } + + return result + }, []) + } + + if (typeof parsed === 'string') { + return [parsed] + } + + if (parsed && typeof parsed.url === 'string') { + return [parsed.url] + } + } catch (error) { + if (/^https?:\/\//.test(files) || files.startsWith('/')) { + return [files] + } + + console.error('解析画册图片失败:', error) + return [] + } + + return [] +} + +export const getBrochurePayload = async (): Promise => { + const response = await Taro.request({ + url: `${BROCHURE_API_BASE}/shop/shop-goods`, + method: 'GET', + header: { + 'Content-Type': 'application/json', + Tenantid: '10582' + } + }) + + const responseData: any = response.data + const goodsList: BrochureGoods[] = Array.isArray(responseData) + ? responseData + : (Array.isArray(responseData?.data) ? responseData.data : []) + + if (!goodsList.length) { + throw new Error('画册加载失败,请稍后重试') + } + + const title = goodsList[0]?.goodsName || goodsList[0]?.name || PREVIEW_TITLE + const images: string[] = [] + + goodsList.forEach((item) => { + const parsedImages = parseFiles(item.files) + if (parsedImages.length) { + images.push(...parsedImages) + } + }) + + if (!images.length) { + throw new Error('当前商品未配置画册图片') + } + + return { + title, + images + } +} diff --git a/src/pages/brochure/viewer.tsx b/src/pages/brochure/viewer.tsx index 1895b0f..19e5689 100644 --- a/src/pages/brochure/viewer.tsx +++ b/src/pages/brochure/viewer.tsx @@ -1,60 +1,10 @@ -import {useEffect, useState} from 'react' +import { useEffect, useState } from 'react' import Taro from '@tarojs/taro' -import {View, Image} from '@tarojs/components' -import {Loading} from '@nutui/nutui-react-taro' +import { View, Image } from '@tarojs/components' +import { Loading } from '@nutui/nutui-react-taro' +import { getBrochurePayload } from './shared' import './viewer.scss' -const PREVIEW_TITLE = '品牌画册' -const BROCHURE_API_BASE = 'https://cms-api.websoft.top/api' - -interface BrochureGoods { - goodsId?: number; - name?: string; - goodsName?: string; - files?: string; -} - -const parseFiles = (files?: string): string[] => { - if (!files) { - return [] - } - - try { - const parsed = JSON.parse(files) - if (Array.isArray(parsed)) { - return parsed.reduce((result, item: any) => { - if (typeof item === 'string') { - result.push(item) - return result - } - - if (item && typeof item.url === 'string') { - result.push(item.url) - } - - return result - }, []) - } - - if (typeof parsed === 'string') { - return [parsed] - } - - if (parsed && typeof parsed.url === 'string') { - return [parsed.url] - } - } catch (error) { - if (/^https?:\/\//.test(files) || files.startsWith('/')) { - return [files] - } - - console.error('解析画册图片失败:', error) - return [] - } - - return [] -} - function BrochureViewer() { const [loading, setLoading] = useState(true) const [images, setImages] = useState([]) @@ -63,40 +13,10 @@ function BrochureViewer() { useEffect(() => { const loadBrochure = async () => { try { - const response = await Taro.request({ - url: `${BROCHURE_API_BASE}/shop/shop-goods`, - method: 'GET', - header: { - 'Content-Type': 'application/json', - 'Tenantid': '10582' - } - }) - - const responseData: any = response.data - const goodsList: BrochureGoods[] = Array.isArray(responseData) - ? responseData - : (Array.isArray(responseData?.data) ? responseData.data : []) - - if (!goodsList.length) { - throw new Error('画册加载失败,请稍后重试') - } - const nextTitle = goodsList[0]?.goodsName || goodsList[0]?.name || PREVIEW_TITLE - const nextImages: string[] = [] - - goodsList.forEach((item) => { - const parsedImages = parseFiles(item.files) - if (parsedImages.length) { - nextImages.push(...parsedImages) - } - }) - - if (!nextImages.length) { - throw new Error('当前商品未配置画册图片') - } - + const { title, images: nextImages } = await getBrochurePayload() setImages(nextImages) Taro.setNavigationBarTitle({ - title: nextTitle + title }) } catch (error: any) { const nextMessage = error?.message || error?.errMsg || '画册加载失败,请稍后重试' diff --git a/src/pages/index/CatalogShowcase.scss b/src/pages/index/CatalogShowcase.scss index 0d3f590..a04b08a 100644 --- a/src/pages/index/CatalogShowcase.scss +++ b/src/pages/index/CatalogShowcase.scss @@ -108,3 +108,96 @@ &:nth-child(3) { height: 32px; } } } + +.catalog-swiper { + margin: 24px 16px 8px; + + &__header { + display: flex; + align-items: flex-end; + justify-content: space-between; + padding: 0 4px 12px; + gap: 12px; + } + + &__title-wrap { + display: flex; + flex-direction: column; + gap: 4px; + } + + &__eyebrow { + font-size: 20px; + line-height: 1; + letter-spacing: 3px; + color: #94a3b8; + } + + &__title { + font-size: 36px; + line-height: 1.2; + font-weight: 700; + color: #0f172a; + } + + &__cta { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 10px 14px; + border-radius: 999px; + background: linear-gradient(135deg, #1e3a5f 0%, #2563eb 100%); + flex-shrink: 0; + } + + &__cta-text { + font-size: 24px; + line-height: 1; + color: #ffffff; + font-weight: 600; + } + + &__body { + border-radius: 20px; + overflow: hidden; + background: linear-gradient(135deg, #1e293b 0%, #2563eb 100%); + box-shadow: 0 12px 32px rgba(37, 99, 235, 0.18); + } + + &__slide { + width: 100%; + //height: 220px; + overflow: hidden; + } + + &__image { + width: 100%; + //height: 220px; + display: block; + } + + &__placeholder { + //height: 220px; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + } + + &__placeholder-text { + font-size: 28px; + color: rgba(255, 255, 255, 0.88); + } + + .nut-swiper { + //height: 220px !important; + } + + .nut-swiper-item { + //height: 220px !important; + } + + .nut-swiper-item__inner { + height: 100%; + } +} diff --git a/src/pages/index/CatalogShowcase.tsx b/src/pages/index/CatalogShowcase.tsx index 339db2f..e22023f 100644 --- a/src/pages/index/CatalogShowcase.tsx +++ b/src/pages/index/CatalogShowcase.tsx @@ -1,50 +1,115 @@ -import { View, Text } from '@tarojs/components' +import { useEffect, useState } from 'react' +import { View, Text, Image } from '@tarojs/components' import Taro from '@tarojs/taro' +import { Swiper } from '@nutui/nutui-react-taro' import { ArrowRight } from '@nutui/icons-react-taro' +import { getBrochurePayload } from '@/pages/brochure/shared' import './CatalogShowcase.scss' -const BROCHURE_GOODS_ID = 333 function CatalogShowcase() { - const handleViewCatalog = () => { - Taro.navigateTo({ - url: `/pages/brochure/viewer?id=${BROCHURE_GOODS_ID}` + const [images, setImages] = useState([]) + const [current, setCurrent] = useState(0) + + useEffect(() => { + getBrochurePayload() + .then(({ images: nextImages }) => { + setImages(nextImages) + }) + .catch(() => undefined) + }, []) + + const handlePreviewCurrent = () => { + if (!images.length) { + Taro.showToast({ + title: '画册加载中', + icon: 'none' + }) + return + } + + Taro.previewImage({ + current: images[current] || images[0], + urls: images }) } return ( - - {/* 装饰性背景元素 */} - - + <> + {/* 旧版品牌画册卡片保留,按需求先注释,不直接删除 + + + - - - BRAND CATALOG - 品牌画册 - - 了解南南佐顿门窗的完整产品线与定制方案 - - - 点击查看画册 - - - - - - - - - - - + + + BRAND CATALOG + 品牌画册 + + 了解南南佐顿门窗的完整产品线与定制方案 + + + 点击查看画册 + + + + + + + + + + + + + 2026 - 2026 - + */} + + + + + BRAND CATALOG + 品牌画册 + + {/**/} + {/* 点击预览当前图片*/} + {/* */} + {/**/} + + + + {images.length ? ( + setCurrent(event.detail.current)} + > + {images.map((item, index) => ( + + + + + + ))} + + ) : ( + + 画册加载中... + + )} + + + ) }