9c8d5f2cad
订单佣金只认关联用户;合伙人备注写入独立表;H5 增加用户管理与首页统计。 Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
4.2 KiB
TypeScript
141 lines
4.2 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
||
import { Image, Text, View } from '@tarojs/components';
|
||
import Taro from '@tarojs/taro';
|
||
import { JIUZU_SPLASH_GIF_URL, JIUZU_SPLASH_MARK_URL } from '@dukang/shared-types';
|
||
import { markJiuzuSplashPlayed } from '../lib/jiuzu-splash';
|
||
|
||
const CHARS = ['酒', '祖', '杜', '康'] as const;
|
||
|
||
const SPLASH_NAV_BG = '#140808';
|
||
const HOME_NAV_BG = '#FAF9F7';
|
||
/** GIF 21 帧 × 80ms,略提前淡出避免循环 */
|
||
const GIF_MS = 1650;
|
||
const GIF_FADE_MS = 350;
|
||
/** 四字显现并升到偏上位置 */
|
||
const TITLE_MS = 2400;
|
||
/** 副标题在四字到位后再升起 */
|
||
const SUB_DELAY_MS = 2300;
|
||
const SUB_MS = 1400;
|
||
const HOLD_MS = 900;
|
||
const FADE_MS = 800;
|
||
const FADE_AT_MS = GIF_MS + SUB_DELAY_MS + SUB_MS + HOLD_MS;
|
||
|
||
type JiuzuSplashProps = {
|
||
onDone: () => void;
|
||
};
|
||
|
||
function applySplashChrome() {
|
||
try {
|
||
void Taro.hideTabBar({ animation: false });
|
||
} catch {
|
||
/* H5 无原生 TabBar */
|
||
}
|
||
void Taro.setNavigationBarColor({
|
||
frontColor: '#ffffff',
|
||
backgroundColor: SPLASH_NAV_BG,
|
||
animation: { duration: 200, timingFunc: 'easeIn' },
|
||
}).catch(() => {});
|
||
}
|
||
|
||
function restoreChrome() {
|
||
try {
|
||
void Taro.showTabBar({ animation: false });
|
||
} catch {
|
||
/* H5 无原生 TabBar */
|
||
}
|
||
void Taro.setNavigationBarColor({
|
||
frontColor: '#000000',
|
||
backgroundColor: HOME_NAV_BG,
|
||
animation: { duration: 200, timingFunc: 'easeOut' },
|
||
}).catch(() => {});
|
||
}
|
||
|
||
export default function JiuzuSplash({ onDone }: JiuzuSplashProps) {
|
||
const finishedRef = useRef(false);
|
||
const fadingRef = useRef(false);
|
||
const onDoneRef = useRef(onDone);
|
||
onDoneRef.current = onDone;
|
||
const [leaving, setLeaving] = useState(false);
|
||
const [gifDone, setGifDone] = useState(false);
|
||
const [gifGone, setGifGone] = useState(false);
|
||
|
||
const finish = useCallback(() => {
|
||
if (finishedRef.current) return;
|
||
finishedRef.current = true;
|
||
restoreChrome();
|
||
onDoneRef.current();
|
||
}, []);
|
||
|
||
const beginExit = useCallback(() => {
|
||
if (fadingRef.current || finishedRef.current) return;
|
||
fadingRef.current = true;
|
||
setLeaving(true);
|
||
setTimeout(finish, FADE_MS);
|
||
}, [finish]);
|
||
|
||
useEffect(() => {
|
||
markJiuzuSplashPlayed();
|
||
applySplashChrome();
|
||
const gifTimer = setTimeout(() => setGifDone(true), GIF_MS);
|
||
const gifGoneTimer = setTimeout(() => setGifGone(true), GIF_MS + GIF_FADE_MS);
|
||
const exitTimer = setTimeout(beginExit, FADE_AT_MS);
|
||
return () => {
|
||
clearTimeout(gifTimer);
|
||
clearTimeout(gifGoneTimer);
|
||
clearTimeout(exitTimer);
|
||
if (!finishedRef.current) restoreChrome();
|
||
};
|
||
}, [beginExit]);
|
||
|
||
return (
|
||
<View
|
||
className={`jiuzu-splash${gifDone ? ' jiuzu-splash--after-gif' : ''}${leaving ? ' jiuzu-splash--out' : ''}`}
|
||
catchMove
|
||
onTouchMove={(e) => {
|
||
e.stopPropagation?.();
|
||
}}
|
||
>
|
||
<View className="jiuzu-splash-mist jiuzu-splash-mist--a" />
|
||
<View className="jiuzu-splash-mist jiuzu-splash-mist--b" />
|
||
|
||
{gifGone ? null : (
|
||
<Image
|
||
className={`jiuzu-splash-gif${gifDone ? ' jiuzu-splash-gif--out' : ''}`}
|
||
src={JIUZU_SPLASH_GIF_URL}
|
||
mode="aspectFill"
|
||
style={{ width: '100%', height: '100%' }}
|
||
/>
|
||
)}
|
||
|
||
<View className="jiuzu-splash-copy">
|
||
<View className="jiuzu-splash-lockup">
|
||
<Image
|
||
className="jiuzu-splash-mark"
|
||
src={JIUZU_SPLASH_MARK_URL}
|
||
mode="aspectFit"
|
||
style={{ width: '320px', height: '180px' }}
|
||
/>
|
||
<View className="jiuzu-splash-title">
|
||
<View className="jiuzu-splash-chars">
|
||
<View className="jiuzu-splash-shimmer" />
|
||
{CHARS.map((ch) => (
|
||
<View key={ch} className="jiuzu-splash-char">
|
||
<Text className="jiuzu-splash-char-text">{ch}</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="jiuzu-splash-sub">
|
||
<Text className="jiuzu-splash-sub-text">千年酒祖 · 杜康好客</Text>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="jiuzu-splash-skip" onClick={finish}>
|
||
<Text className="jiuzu-splash-skip-text">跳过</Text>
|
||
</View>
|
||
</View>
|
||
);
|
||
}
|