187 lines
5.7 KiB
JavaScript
187 lines
5.7 KiB
JavaScript
// src/hooks/useSubscription.js
|
|
// 订阅信息自定义 Hook - 使用 Redux 状态管理
|
|
|
|
import { useEffect } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
import { logger } from '../utils/logger';
|
|
import {
|
|
fetchSubscriptionInfo,
|
|
openModal,
|
|
closeModal,
|
|
resetToFree,
|
|
selectSubscriptionInfo,
|
|
selectSubscriptionLoading,
|
|
selectSubscriptionLoaded,
|
|
selectSubscriptionError,
|
|
selectSubscriptionModalOpen
|
|
} from '../store/slices/subscriptionSlice';
|
|
|
|
// 订阅级别映射
|
|
const SUBSCRIPTION_LEVELS = {
|
|
free: 0,
|
|
pro: 1,
|
|
max: 2
|
|
};
|
|
|
|
// 功能权限映射
|
|
const FEATURE_REQUIREMENTS = {
|
|
'related_stocks': 'pro', // 相关标的
|
|
'related_concepts': 'pro', // 相关概念
|
|
'transmission_chain': 'max', // 事件传导链分析
|
|
'historical_events_full': 'pro', // 历史事件对比(完整版)
|
|
'concept_html_detail': 'pro', // 概念HTML具体内容
|
|
'concept_stats_panel': 'pro', // 概念统计中心
|
|
'concept_related_stocks': 'pro', // 概念相关股票
|
|
'concept_timeline': 'max', // 概念历史时间轴
|
|
'hot_stocks': 'pro' // 热门个股
|
|
};
|
|
|
|
/**
|
|
* 订阅信息自定义 Hook (Redux 版本)
|
|
*
|
|
* 功能:
|
|
* - 自动根据登录状态加载订阅信息 (从 Redux)
|
|
* - 提供权限检查方法
|
|
* - 提供订阅 Modal 控制方法
|
|
*
|
|
* @returns {{
|
|
* subscriptionInfo: Object,
|
|
* loading: boolean,
|
|
* error: string|null,
|
|
* isSubscriptionModalOpen: boolean,
|
|
* openSubscriptionModal: Function,
|
|
* closeSubscriptionModal: Function,
|
|
* refreshSubscription: Function,
|
|
* hasFeatureAccess: Function,
|
|
* hasSubscriptionLevel: Function,
|
|
* getRequiredLevel: Function,
|
|
* getSubscriptionStatusText: Function,
|
|
* getUpgradeRecommendation: Function
|
|
* }}
|
|
*/
|
|
export const useSubscription = () => {
|
|
const dispatch = useDispatch();
|
|
const { user, isAuthenticated } = useAuth();
|
|
|
|
// Redux 状态
|
|
const subscriptionInfo = useSelector(selectSubscriptionInfo);
|
|
const loading = useSelector(selectSubscriptionLoading);
|
|
const loaded = useSelector(selectSubscriptionLoaded);
|
|
const error = useSelector(selectSubscriptionError);
|
|
const isSubscriptionModalOpen = useSelector(selectSubscriptionModalOpen);
|
|
|
|
// 自动加载订阅信息(带防重复逻辑)
|
|
useEffect(() => {
|
|
if (isAuthenticated && user) {
|
|
// 只在未加载且未在加载中时才请求,避免多个组件重复调用
|
|
if (!loaded && !loading) {
|
|
dispatch(fetchSubscriptionInfo());
|
|
logger.debug('useSubscription', '加载订阅信息', { userId: user.id });
|
|
}
|
|
} else {
|
|
// 用户未登录,重置为免费版
|
|
dispatch(resetToFree());
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [isAuthenticated, user?.id, dispatch, loaded, loading]);
|
|
|
|
// 获取订阅级别数值
|
|
const getSubscriptionLevel = (type = null) => {
|
|
const subType = (type || subscriptionInfo.type || 'free').toLowerCase();
|
|
return SUBSCRIPTION_LEVELS[subType] || 0;
|
|
};
|
|
|
|
// 检查是否有指定功能的权限
|
|
const hasFeatureAccess = (featureName) => {
|
|
// Max 用户解锁所有功能
|
|
if (user?.subscription_type === 'max' || subscriptionInfo.type === 'max') {
|
|
return true;
|
|
}
|
|
|
|
if (!subscriptionInfo.is_active) {
|
|
return false;
|
|
}
|
|
|
|
const requiredLevel = FEATURE_REQUIREMENTS[featureName];
|
|
if (!requiredLevel) {
|
|
return true; // 如果功能不需要特定权限,默认允许
|
|
}
|
|
|
|
const currentLevel = getSubscriptionLevel();
|
|
const requiredLevelNum = getSubscriptionLevel(requiredLevel);
|
|
|
|
return currentLevel >= requiredLevelNum;
|
|
};
|
|
|
|
// 检查是否达到指定订阅级别
|
|
const hasSubscriptionLevel = (requiredLevel) => {
|
|
if (!subscriptionInfo.is_active) {
|
|
return false;
|
|
}
|
|
|
|
const currentLevel = getSubscriptionLevel();
|
|
const requiredLevelNum = getSubscriptionLevel(requiredLevel);
|
|
|
|
return currentLevel >= requiredLevelNum;
|
|
};
|
|
|
|
// 获取功能所需的订阅级别
|
|
const getRequiredLevel = (featureName) => {
|
|
return FEATURE_REQUIREMENTS[featureName] || 'free';
|
|
};
|
|
|
|
// 获取订阅状态文本
|
|
const getSubscriptionStatusText = () => {
|
|
const type = subscriptionInfo.type || 'free';
|
|
switch (type.toLowerCase()) {
|
|
case 'free':
|
|
return '免费版';
|
|
case 'pro':
|
|
return 'Pro版';
|
|
case 'max':
|
|
return 'Max版';
|
|
default:
|
|
return '未知';
|
|
}
|
|
};
|
|
|
|
// 获取升级建议
|
|
const getUpgradeRecommendation = (featureName) => {
|
|
const requiredLevel = getRequiredLevel(featureName);
|
|
const currentType = subscriptionInfo.type || 'free';
|
|
|
|
if (hasFeatureAccess(featureName)) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
current: currentType,
|
|
required: requiredLevel,
|
|
message: `此功能需要${requiredLevel === 'pro' ? 'Pro版' : 'Max版'}订阅`
|
|
};
|
|
};
|
|
|
|
return {
|
|
// 订阅信息 (来自 Redux)
|
|
subscriptionInfo,
|
|
loading,
|
|
error,
|
|
|
|
// Modal 控制
|
|
isSubscriptionModalOpen,
|
|
openSubscriptionModal: () => dispatch(openModal()),
|
|
closeSubscriptionModal: () => dispatch(closeModal()),
|
|
|
|
// 权限检查方法
|
|
hasFeatureAccess,
|
|
hasSubscriptionLevel,
|
|
getRequiredLevel,
|
|
getSubscriptionStatusText,
|
|
getUpgradeRecommendation,
|
|
|
|
// 手动刷新
|
|
refreshSubscription: () => dispatch(fetchSubscriptionInfo())
|
|
};
|
|
};
|