404 lines
10 KiB
Markdown
404 lines
10 KiB
Markdown
# Genex 小程序 + H5 开发指南
|
||
|
||
> 基于 Taro 3.x 的跨端轻量级应用
|
||
|
||
---
|
||
|
||
## 1. 产品定位
|
||
|
||
小程序/H5作为**轻量获客入口**,主要通过社交分享引流,提供核心消费者功能的精简版。完整功能引导下载原生App。
|
||
|
||
**覆盖平台**:
|
||
- 微信小程序(主要)
|
||
- 支付宝小程序
|
||
- H5(移动浏览器、App内嵌WebView)
|
||
|
||
---
|
||
|
||
## 2. 技术栈
|
||
|
||
| 技术 | 版本 | 用途 |
|
||
|------|------|------|
|
||
| **Taro** | 3.x | 跨端框架(React语法) |
|
||
| **React** | 18.x | UI框架 |
|
||
| **TypeScript** | 5.x | 类型安全 |
|
||
| **Zustand** | 4.x | 状态管理 |
|
||
| **Taro UI / NutUI** | 最新 | 跨端UI组件库 |
|
||
|
||
---
|
||
|
||
## 3. 项目结构
|
||
|
||
```
|
||
genex-mini/
|
||
├── src/
|
||
│ ├── app.ts # 应用入口
|
||
│ ├── app.config.ts # 全局配置
|
||
│ ├── pages/
|
||
│ │ ├── index/ # 首页(券推荐)
|
||
│ │ ├── coupon-detail/ # 券详情
|
||
│ │ ├── purchase/ # 购买页
|
||
│ │ ├── my-coupons/ # 我的券
|
||
│ │ ├── redeem/ # 券使用(出示券码)
|
||
│ │ ├── login/ # 登录/注册
|
||
│ │ └── profile/ # 个人中心
|
||
│ ├── components/
|
||
│ │ ├── coupon-card/ # 券卡片组件
|
||
│ │ ├── ai-guide/ # AI引导气泡
|
||
│ │ └── share-card/ # 分享卡片
|
||
│ ├── services/
|
||
│ │ ├── api.ts # API请求封装
|
||
│ │ └── auth.ts # 认证服务
|
||
│ ├── stores/
|
||
│ │ ├── user-store.ts # 用户状态
|
||
│ │ └── coupon-store.ts # 券状态
|
||
│ ├── utils/
|
||
│ │ ├── share.ts # 分享工具
|
||
│ │ └── platform.ts # 平台判断
|
||
│ └── assets/
|
||
├── config/
|
||
│ ├── index.ts # Taro编译配置
|
||
│ ├── dev.ts
|
||
│ └── prod.ts
|
||
└── package.json
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 核心功能(精简版)
|
||
|
||
### 4.1 功能矩阵
|
||
|
||
| 功能 | 小程序/H5 | 原生App |
|
||
|------|----------|---------|
|
||
| 浏览券市场 | ✅ | ✅ |
|
||
| 购买券 | ✅ | ✅ |
|
||
| 我的券 | ✅ | ✅ |
|
||
| 出示券码使用 | ✅ | ✅ |
|
||
| 二级市场交易 | ❌(引导下载App) | ✅ |
|
||
| P2P转赠 | ❌(引导下载App) | ✅ |
|
||
| AI Agent完整对话 | ❌(精简版) | ✅ |
|
||
| KYC认证 | L0/L1 | L0/L1/L2/L3 |
|
||
|
||
### 4.2 首页
|
||
|
||
```tsx
|
||
// src/pages/index/index.tsx
|
||
import { View, ScrollView } from '@tarojs/components';
|
||
import { useEffect } from 'react';
|
||
import { useCouponStore } from '@/stores/coupon-store';
|
||
import CouponCard from '@/components/coupon-card';
|
||
import AiGuide from '@/components/ai-guide';
|
||
|
||
export default function IndexPage() {
|
||
const { hotCoupons, fetchHotCoupons } = useCouponStore();
|
||
|
||
useEffect(() => {
|
||
fetchHotCoupons();
|
||
}, []);
|
||
|
||
return (
|
||
<View className="index-page">
|
||
{/* AI轻量推荐条 */}
|
||
<AiGuide type="recommendation" />
|
||
|
||
{/* 搜索栏 */}
|
||
<SearchBar placeholder="搜索券..." />
|
||
|
||
{/* 分类标签 */}
|
||
<CategoryTabs />
|
||
|
||
{/* 券列表 */}
|
||
<ScrollView scrollY>
|
||
{hotCoupons.map((coupon) => (
|
||
<CouponCard key={coupon.id} coupon={coupon} />
|
||
))}
|
||
</ScrollView>
|
||
</View>
|
||
);
|
||
}
|
||
```
|
||
|
||
### 4.3 购买流程
|
||
|
||
```tsx
|
||
// src/pages/purchase/index.tsx
|
||
export default function PurchasePage() {
|
||
const { id } = useRouter().params;
|
||
const coupon = useCouponDetail(id!);
|
||
|
||
const handlePurchase = async () => {
|
||
// 微信小程序:调用微信支付
|
||
// H5:调用支付宝/银联等H5支付
|
||
const paymentResult = await Taro.requestPayment({
|
||
...paymentParams,
|
||
});
|
||
|
||
if (paymentResult.errMsg === 'requestPayment:ok') {
|
||
// 后端自动完成:法币→稳定币→链上原子交换
|
||
await api.confirmPurchase(orderId);
|
||
Taro.navigateTo({ url: '/pages/purchase-success/index' });
|
||
}
|
||
};
|
||
|
||
return (
|
||
<View>
|
||
<CouponDetailCard coupon={coupon} />
|
||
<PriceSection price={coupon.currentPrice} faceValue={coupon.faceValue} />
|
||
<Button onClick={handlePurchase}>立即购买</Button>
|
||
</View>
|
||
);
|
||
}
|
||
```
|
||
|
||
### 4.4 出示券码
|
||
|
||
```tsx
|
||
// src/pages/redeem/index.tsx
|
||
export default function RedeemPage() {
|
||
const { couponId } = useRouter().params;
|
||
const qrCode = useRedeemCode(couponId!);
|
||
|
||
return (
|
||
<View className="redeem-page">
|
||
<Text>出示给商户扫码</Text>
|
||
<QRCode value={qrCode.data} size={200} />
|
||
<Text className="coupon-code">{qrCode.numericCode}</Text>
|
||
<BrightnessMaxWidget /> {/* 自动调高亮度 */}
|
||
<CountdownTimer expiry={qrCode.expiresAt} />
|
||
</View>
|
||
);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 社交分享
|
||
|
||
```typescript
|
||
// src/utils/share.ts
|
||
export function configShare(coupon: Coupon) {
|
||
return {
|
||
title: `${coupon.issuerName} ${coupon.faceValue}元券 仅${coupon.currentPrice}元`,
|
||
path: `/pages/coupon-detail/index?id=${coupon.id}&from=share`,
|
||
imageUrl: coupon.shareImage || coupon.imageUrl,
|
||
};
|
||
}
|
||
|
||
// 小程序页面配置
|
||
export default {
|
||
onShareAppMessage() {
|
||
return configShare(currentCoupon);
|
||
},
|
||
onShareTimeline() {
|
||
return {
|
||
title: `限时折扣券`,
|
||
query: `id=${currentCoupon.id}`,
|
||
};
|
||
},
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## 6. AI Agent(精简版)
|
||
|
||
小程序/H5中AI Agent以轻量形式集成:
|
||
|
||
| 组件 | 说明 |
|
||
|------|------|
|
||
| 推荐条 | 首页顶部横向滚动AI推荐标签 |
|
||
| 购买引导 | 新用户首次进入时的对话气泡引导 |
|
||
|
||
```tsx
|
||
// src/components/ai-guide/index.tsx
|
||
export default function AiGuide({ type }: { type: 'recommendation' | 'purchase' }) {
|
||
const suggestions = useAiSuggestions(type);
|
||
|
||
if (type === 'recommendation') {
|
||
return (
|
||
<ScrollView scrollX className="ai-suggest-bar">
|
||
{suggestions.map((s) => (
|
||
<Tag key={s.id} onClick={() => navigateToCoupon(s.couponId)}>
|
||
{s.text}
|
||
</Tag>
|
||
))}
|
||
</ScrollView>
|
||
);
|
||
}
|
||
|
||
return <ChatBubble message={suggestions[0]?.text} />;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 平台适配
|
||
|
||
```typescript
|
||
// src/utils/platform.ts
|
||
import Taro from '@tarojs/taro';
|
||
|
||
export function getPlatform(): 'weapp' | 'alipay' | 'h5' {
|
||
return Taro.getEnv() as any;
|
||
}
|
||
|
||
export function getPaymentMethod() {
|
||
switch (getPlatform()) {
|
||
case 'weapp': return 'wechat_pay';
|
||
case 'alipay': return 'alipay';
|
||
case 'h5': return 'h5_pay';
|
||
}
|
||
}
|
||
```
|
||
|
||
### 条件编译
|
||
|
||
```typescript
|
||
// Taro支持条件编译
|
||
// #ifdef WEAPP
|
||
// 微信小程序专用代码
|
||
wx.login({ success: (res) => { /* ... */ } });
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
// H5专用代码
|
||
window.location.href = authUrl;
|
||
// #endif
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 性能优化
|
||
|
||
| 策略 | 实现 |
|
||
|------|------|
|
||
| 分包加载 | 主包只含首页+登录,其余分包 |
|
||
| 图片优化 | WebP格式 + CDN + 懒加载 |
|
||
| 数据预拉取 | `onPrefetch` 预加载详情页数据 |
|
||
| 骨架屏 | 关键页面skeleton loading |
|
||
| 缓存策略 | 券列表本地缓存,增量更新 |
|
||
|
||
### 分包配置
|
||
|
||
```typescript
|
||
// src/app.config.ts
|
||
export default defineAppConfig({
|
||
pages: [
|
||
'pages/index/index',
|
||
'pages/login/index',
|
||
],
|
||
subPackages: [
|
||
{
|
||
root: 'pages/coupon-detail',
|
||
pages: ['index'],
|
||
},
|
||
{
|
||
root: 'pages/purchase',
|
||
pages: ['index'],
|
||
},
|
||
{
|
||
root: 'pages/my-coupons',
|
||
pages: ['index'],
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 测试与发布
|
||
|
||
| 平台 | 发布流程 |
|
||
|------|---------|
|
||
| 微信小程序 | 开发版 → 体验版 → 审核 → 正式版 |
|
||
| 支付宝小程序 | 开发版 → 灰度 → 审核 → 正式版 |
|
||
| H5 | CI/CD自动部署至CDN |
|
||
|
||
---
|
||
|
||
## 10. 多语言与国际化
|
||
|
||
### 10.1 i18n配置
|
||
|
||
```typescript
|
||
// src/utils/i18n.ts
|
||
import Taro from '@tarojs/taro';
|
||
|
||
// 支持语言:中文(默认)、英文、日文
|
||
type Locale = 'zh-CN' | 'en-US' | 'ja-JP';
|
||
|
||
const messages: Record<Locale, Record<string, string>> = {
|
||
'zh-CN': {
|
||
'home.title': '发现好券',
|
||
'coupon.buy': '立即购买',
|
||
'coupon.faceValue': '面值',
|
||
'coupon.discount': '折扣',
|
||
'coupon.expiry': '有效期至',
|
||
'my.coupons': '我的券',
|
||
'my.orders': '我的订单',
|
||
'redeem.show': '出示给商户扫码',
|
||
// ...
|
||
},
|
||
'en-US': {
|
||
'home.title': 'Discover Deals',
|
||
'coupon.buy': 'Buy Now',
|
||
'coupon.faceValue': 'Face Value',
|
||
'coupon.discount': 'Discount',
|
||
'coupon.expiry': 'Valid Until',
|
||
'my.coupons': 'My Coupons',
|
||
'my.orders': 'My Orders',
|
||
'redeem.show': 'Show to Merchant',
|
||
// ...
|
||
},
|
||
'ja-JP': {
|
||
'home.title': 'クーポンを探す',
|
||
'coupon.buy': '今すぐ購入',
|
||
'coupon.faceValue': '額面',
|
||
'coupon.discount': '割引',
|
||
'coupon.expiry': '有効期限',
|
||
'my.coupons': 'マイクーポン',
|
||
'my.orders': '注文履歴',
|
||
'redeem.show': '店舗に提示',
|
||
// ...
|
||
},
|
||
};
|
||
|
||
export function useI18n() {
|
||
const locale = useLocaleStore((s) => s.locale);
|
||
const t = (key: string) => messages[locale]?.[key] || messages['zh-CN'][key] || key;
|
||
return { t, locale };
|
||
}
|
||
|
||
// 自动检测系统语言
|
||
export function detectLocale(): Locale {
|
||
const systemInfo = Taro.getSystemInfoSync();
|
||
const lang = systemInfo.language || 'zh-CN';
|
||
if (lang.startsWith('en')) return 'en-US';
|
||
if (lang.startsWith('ja')) return 'ja-JP';
|
||
return 'zh-CN';
|
||
}
|
||
```
|
||
|
||
### 10.2 多币种展示
|
||
|
||
```typescript
|
||
// src/utils/currency.ts
|
||
export function formatPrice(amount: number, currency: string = 'USD'): string {
|
||
const formatters: Record<string, Intl.NumberFormat> = {
|
||
USD: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }),
|
||
CNY: new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }),
|
||
JPY: new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }),
|
||
SGD: new Intl.NumberFormat('en-SG', { style: 'currency', currency: 'SGD' }),
|
||
};
|
||
return formatters[currency]?.format(amount) || `$${amount.toFixed(2)}`;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
*文档版本: v2.0*
|
||
*基于: Genex 券交易平台 - 软件需求规格说明书 v4.1*
|
||
*技术栈: Taro 3.x + React 18 + TypeScript*
|
||
*更新: 补充多语言国际化(i18n)、多币种展示*
|