From 1d368884885d4d3441054208e24e7762b3d37216 Mon Sep 17 00:00:00 2001 From: coder Date: Tue, 14 Apr 2026 18:42:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A5=97=E9=A4=90=E6=9D=83=E7=9B=8A?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E4=BB=8E=E5=90=8E=E5=8F=B0UserTypeConfig?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 权益列表从数据库配置读取 - 支持按用户类型显示✅/❌状态 - 更新各等级用户权益配置 --- app.py | 84 +++++++++++++++++++++++++++++------------- templates/pricing.html | 16 ++++---- 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/app.py b/app.py index 89d50d0..3f219ae 100644 --- a/app.py +++ b/app.py @@ -209,37 +209,71 @@ def pricing(): """会员定价页""" user = get_current_user() + # 权益名称映射 + feature_names = { + 'basic_translate': '基础翻译功能', + 'history': '翻译历史记录', + 'retranslate': '不满意重新翻译', + 'export_pdf': '导出PDF格式', + 'compare_view': '原文译文对比查看', + 'batch_translate': '批量翻译', + 'custom_terms': '自定义术语库', + 'priority_queue': '优先处理队列', + 'custom_instruction': '自定义翻译要求', + 'api_access': 'API接口调用', + } + # 从数据库读取动态配置的会员套餐 db_plans = MembershipPlanConfig.query.filter_by(is_active=True)\ .order_by(MembershipPlanConfig.sort_order).all() - # 如果数据库没有配置,使用默认配置 - if not db_plans: - plans = MEMBERSHIP_PLANS - else: - # 转换为字典格式供模板使用 - plans = {} - for plan in db_plans: - plans[plan.plan_key] = { - 'name': plan.display_name, - 'price': plan.price, - 'original_price': plan.original_price, - 'period': plan.period, - 'period_days': plan.period_days, - 'description': plan.description, - 'is_recommended': plan.is_recommended, - 'user_type_key': plan.user_type_key, - } + # 读取用户类型配置获取权益 + user_types = UserTypeConfig.query.filter_by(is_active=True).all() + user_type_map = {ut.type_key: ut for ut in user_types} - # 添加免费用户套餐(固定) - plans['free'] = { - 'name': '免费用户', - 'price': 0, - 'period': 'forever', - 'description': '基础翻译功能', - } + # 为每个套餐添加权益列表 + plan_features = {} + for plan in db_plans: + ut = user_type_map.get(plan.user_type_key) + if ut: + features = ut.get_features() + plan_features[plan.plan_key] = [ + {'key': f, 'name': feature_names.get(f, f), 'has': True} + for f in features + ] + # 添加限制信息 + plan_features[plan.plan_key].insert(0, { + 'key': 'daily_translations', + 'name': f"每日翻译{ut.daily_translations if ut.daily_translations > 0 else '无限'}次", + 'has': True + }) + plan_features[plan.plan_key].insert(1, { + 'key': 'max_pages', + 'name': f"单文件最大{ut.max_pages if ut.max_pages > 0 else '无限'}页", + 'has': True + }) - return render_template('pricing.html', plans=plans, user=user, db_plans=db_plans) + # 免费用户权益 + free_ut = user_type_map.get('free') + free_features = [] + if free_ut: + free_features = [ + {'key': 'daily_translations', 'name': f"每日翻译{free_ut.daily_translations}次", 'has': True}, + {'key': 'max_pages', 'name': f"单文件最大{free_ut.max_pages}页", 'has': True}, + ] + for f in free_ut.get_features(): + free_features.append({'key': f, 'name': feature_names.get(f, f), 'has': True}) + # 添加没有的功能 + all_features = ['compare_view', 'batch_translate', 'custom_terms'] + for f in all_features: + if f not in free_ut.get_features(): + free_features.append({'key': f, 'name': feature_names.get(f, f), 'has': False}) + + return render_template('pricing.html', + plans=db_plans, + plan_features=plan_features, + free_features=free_features, + user=user) @app.route('/profile') diff --git a/templates/pricing.html b/templates/pricing.html index c74b2c9..57bac2a 100644 --- a/templates/pricing.html +++ b/templates/pricing.html @@ -49,13 +49,9 @@
¥0/永久
{% if user and user.user_type in ['free', 'vip_basic', 'vip_pro', 'vip_enterprise', 'admin'] %} @@ -89,6 +85,12 @@

{{ plan.description }}

+ + {% if user and user.user_type == plan.user_type_key %} 当前套餐 {% elif user and user.user_type in ['vip_enterprise', 'admin'] %}