Files
vf_react/src/hooks/useSubscription.js

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())
};
};