微信小程序上传

This commit is contained in:
2026-07-12 14:45:57 +08:00
parent d271ac5b13
commit becf91da52
45 changed files with 1815 additions and 23 deletions
@@ -0,0 +1,4 @@
export default definePageConfig({
navigationStyle: 'custom',
navigationBarTitleText: '杜康好客',
});
+123
View File
@@ -0,0 +1,123 @@
import { useEffect, useState } from 'react';
import { View, Text, Image } from '@tarojs/components';
import { useDidShow } from '@tarojs/taro';
import TabMainHeader from '../../components/TabMainHeader';
import CouponBadge from '../../components/CouponBadge';
import UserTabBar, { shouldRenderPageTabBar, syncTabBarSelected } from '../../components/UserTabBar';
import { request, toast } from '../../lib/api';
import { FALLBACK_CITY_CODE, getProductMainImage } from '../../lib/product-images';
type Product = {
id: string;
name: string;
subtitle?: string;
price: number;
benefitDisplay?: number;
mainImageUrl?: string | null;
carouselUrls?: string[] | null;
aromaType: string;
};
const AROMA_TABS = [
{ key: 'QINGXIANG', label: '清香型', open: true },
{ key: 'JIANGXIANG', label: '酱香型', open: false },
{ key: 'NONGXIANG', label: '浓香型', open: false },
] as const;
export default function HomePage() {
const [tab, setTab] = useState('QINGXIANG');
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(true);
const cityCode = FALLBACK_CITY_CODE;
useDidShow(() => {
syncTabBarSelected(0);
});
useEffect(() => {
setLoading(true);
request<Product[]>(`/catalog/products?cityCode=${encodeURIComponent(cityCode)}`)
.then((list) => setProducts(Array.isArray(list) ? list : []))
.catch((e) => toast(e instanceof Error ? e.message : '加载失败'))
.finally(() => setLoading(false));
}, [cityCode]);
function onAromaTabClick(key: string, open: boolean) {
if (!open) {
toast('暂未开放');
return;
}
setTab(key);
}
const filtered = products.filter((p) => p.aromaType === tab);
const onSale = tab === 'QINGXIANG';
return (
<View className="u-page u-page--tab home-page">
<TabMainHeader
title="杜康好客"
extra={(
<View style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
<View className="tab-main-city-pin" />
<Text className="tab-main-city-label"></Text>
</View>
)}
/>
<View className="home-aroma-nav">
{AROMA_TABS.map((t) => (
<Text
key={t.key}
className={`home-aroma-tab${tab === t.key ? ' home-aroma-tab--active' : ''}${!t.open ? ' home-aroma-tab--muted' : ''}`}
onClick={() => onAromaTabClick(t.key, t.open)}
>
{t.label}
</Text>
))}
</View>
<View className="home-product-list">
{loading ? <View className="home-empty"></View> : null}
{!loading && !onSale ? <View className="home-empty">线</View> : null}
{!loading && onSale && filtered.length === 0 ? (
<View className="home-empty"></View>
) : null}
{!loading &&
onSale &&
filtered.map((p) => {
const cover = getProductMainImage(p);
return (
<View key={p.id} className="home-product-card">
{cover ? (
<Image className="home-product-cover" src={cover} mode="aspectFill" />
) : (
<View className="home-product-cover--empty" />
)}
<View className="home-product-body">
<View className="home-product-row">
<Text className="home-product-name">{p.name}</Text>
<Text className="home-product-price">¥{Number(p.price).toFixed(2)}</Text>
</View>
{p.subtitle ? <Text className="home-product-sub">{p.subtitle}</Text> : null}
<View className="home-product-footer">
<CouponBadge amount={p.benefitDisplay ?? p.price} label="好客权益" />
</View>
</View>
<View className="home-product-actions">
<Text
className="home-buy-btn"
onClick={() => toast('详情页开发中')}
>
</Text>
</View>
</View>
);
})}
</View>
{shouldRenderPageTabBar() ? <UserTabBar selected={0} /> : null}
</View>
);
}