feat: multiple improvements and bug fixes

- Add gift card redemption feature
- Resolve custom range selection issue in overview
- Allow log page size to be modified
- Add subscription path change notification
- Improve dynamic node rate feature
- Support markdown documentation display for plugins
- Reduce power reset service logging
- Fix backend version number not updating after update
This commit is contained in:
xboard
2025-07-14 00:33:04 +08:00
parent a01b94f131
commit a838a43ae5
38 changed files with 3056 additions and 325 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
<link rel="icon" type="image/png" href="/images/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Shadcn Admin</title>
<meta
name="description"
content="Admin Dashboard UI built with Shadcn and Vite."
/>
<script>
window.settings = {
base_url: 'http://127.0.0.1:8000',
title: 'Xboard',
version: '1.0.0',
logo: 'https://xboard.io/i6mages/logo.png',
secure_path: '/afbced4e',
}
</script>
<script src="./locales/en-US.js"></script>
<script src="./locales/zh-CN.js"></script>
<script src="./locales/ko-KR.js"></script>
<script type="module" crossorigin src="./assets/index.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index.css">
<link rel="stylesheet" crossorigin href="./assets/vendor.css">
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@@ -161,6 +161,7 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"planManagement": "Plan Management",
"orderManagement": "Order Management",
"couponManagement": "Coupon Management",
"giftCardManagement": "Gift Card Management",
"userManagement": "User Management",
"trafficResetLogs": "Traffic Reset Logs",
"ticketManagement": "Ticket Management"
@@ -555,7 +556,8 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"subscribe_path": {
"title": "Subscription Path",
"description": "Subscription path, modifying will change the original subscribe path",
"current_format": "Current subscription path format: {path}/xxxxxxxxxx"
"current_format": "Current subscription path format: {path}/xxxxxxxxxx",
"restart_tip": "You may need to restart the service for the new subscribe path to take effect."
},
"show_info_to_server": {
"title": "Show Subscription Info in Nodes",
@@ -932,6 +934,8 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"error": "Copy failed",
"errorLog": "Error copying to clipboard"
},
"submit": "Submit",
"saving": "Saving...",
"table": {
"noData": "No data available",
"pagination": {
@@ -955,6 +959,15 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"updating": "Updating...",
"updateSuccess": "Update successful, system will restart shortly",
"updateFailed": "Update failed, please try again later"
},
"time": {
"day": "day",
"hour": " hour(s)"
},
"reset": "Reset",
"export": "Export",
"currency": {
"yuan": "Yuan"
}
},
"dashboard": {
@@ -1164,6 +1177,241 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"loading": "Searching..."
}
},
"giftCard": {
"types": {
"1": "General Gift Card",
"2": "Plan-Specific Gift Card",
"3": "Mystery Box Reward",
"4": "Task Gift Card"
},
"status": {
"0": "Unused",
"1": "Used",
"2": "Disabled",
"3": "Expired"
},
"template": {
"title": "Gift Card Templates",
"add": "Add Template",
"search": "Search template name...",
"form": {
"name": {
"label": "Name",
"placeholder": "Enter template name"
},
"sort": {
"label": "Sort",
"placeholder": "Smaller numbers come first"
},
"type": {
"label": "Type",
"placeholder": "Select gift card type"
},
"description": {
"label": "Description",
"placeholder": "Enter gift card description"
},
"status": {
"label": "Status",
"description": "If disabled, this template cannot be used to generate or redeem new gift cards."
},
"display": {
"title": "Display Settings"
},
"theme_color": {
"label": "Theme Color"
},
"icon": {
"label": "Icon",
"placeholder": "Enter the URL of the icon"
},
"background_image": {
"label": "Background Image",
"placeholder": "Enter the URL of the background image"
},
"conditions": {
"title": "Usage Conditions",
"new_user_max_days": {
"label": "New User Registration Day Limit",
"placeholder": "e.g., 7 (only for users registered within 7 days)"
},
"new_user_only": {
"label": "New Users Only"
},
"paid_user_only": {
"label": "Paid Users Only"
},
"require_invite": {
"label": "Requires Invitation"
},
"allowed_plans": {
"label": "Allowed Plans",
"placeholder": "Select allowed plans (leave empty for no restriction)"
},
"disallowed_plans": {
"label": "Disallowed Plans",
"placeholder": "Select disallowed plans (leave empty for no restriction)"
}
},
"limits": {
"title": "Usage Limits",
"max_use_per_user": {
"label": "Max Uses Per User",
"placeholder": "Leave empty for no limit"
},
"cooldown_hours": {
"label": "Cooldown for Same Type (Hours)",
"placeholder": "Leave empty for no limit"
},
"invite_reward_rate": {
"label": "Inviter Reward Rate",
"placeholder": "e.g., 0.2 (for 20%)",
"description": "If the user has an inviter, the inviter's reward = balance reward * this rate"
}
},
"rewards": {
"title": "Reward Content",
"balance": {
"label": "Reward Amount (in Yuan)",
"short_label": "Balance",
"placeholder": "Enter the reward amount in Yuan"
},
"transfer_enable": {
"label": "Reward Traffic (in bytes)",
"short_label": "Traffic",
"placeholder": "Enter the reward traffic in bytes"
},
"expire_days": {
"label": "Extend Validity (in days)",
"short_label": "Validity",
"placeholder": "Enter the number of days to extend"
},
"transfer": {
"label": "Reward Traffic (in bytes)",
"placeholder": "Enter the reward traffic in bytes"
},
"days": {
"label": "Extend Validity (in days)",
"placeholder": "Enter the number of days to extend"
},
"device_limit": {
"label": "Increase Device Limit",
"short_label": "Devices",
"placeholder": "Enter the number of devices to increase"
},
"reset_package": {
"label": "Reset Monthly Traffic",
"description": "If enabled, the user's current plan traffic usage will be reset to zero upon redemption."
},
"reset_count": {
"description": "This type of card will reset the user's traffic usage for the current month."
},
"task_card": {
"description": "The specific rewards for task gift cards will be configured in the task system."
},
"plan_id": {
"label": "Specify Plan",
"short_label": "Plan",
"placeholder": "Select a plan"
},
"plan_validity_days": {
"label": "Plan Validity (in days)",
"short_label": "Plan Validity",
"placeholder": "Leave empty to use the plan's default validity"
},
"random_rewards": {
"label": "Random Reward Pool",
"add": "Add Random Reward Item",
"weight": "Weight"
}
},
"special_config": {
"title": "Special Configuration",
"start_time": {
"label": "Event Start Time",
"placeholder": "Pick a start date"
},
"end_time": {
"label": "Event End Time",
"placeholder": "Pick an end date"
},
"festival_bonus": {
"label": "Festival Reward Multiplier",
"placeholder": "e.g., 1.5 (for 1.5x)"
}
}
}
},
"code": {
"title": "Code Management",
"add": "Generate Codes",
"search": "Search codes...",
"form": {
"template_id": {
"label": "Gift Card Template",
"placeholder": "Select a template"
},
"count": {
"label": "Quantity to Generate",
"placeholder": "Enter the quantity to generate"
},
"prefix": {
"label": "Code Prefix",
"placeholder": "Leave empty for default prefix GC"
},
"expires_hours": {
"label": "Validity (Hours)",
"placeholder": "From generation time, leave empty for no expiration"
},
"max_usage": {
"label": "Max Usage Count",
"placeholder": "Total times each code can be used"
},
"download_csv": "Export as CSV"
},
"table": {
"code": "Code",
"template": "Template",
"status": "Status",
"expires_at": "Expires At",
"used_at": "Used At",
"used_by": "Used By",
"max_usage": "Max Uses",
"usage_count": "Usage Count"
},
"messages": {
"generateSuccess": "Codes generated successfully",
"generateFailed": "Failed to generate codes",
"deleteConfirm": "Are you sure you want to delete this code? This action cannot be undone.",
"deleteSuccess": "Code deleted successfully",
"deleteFailed": "Failed to delete code"
}
},
"messages": {
"formInvalid": "Form validation failed, please check your input.",
"templateCreated": "Template created successfully",
"templateUpdated": "Template updated successfully",
"createTemplateFailed": "Failed to create template",
"updateTemplateFailed": "Failed to update template",
"deleteConfirm": "Are you sure you want to delete this template? All codes under it will also be deleted.",
"deleteSuccess": "Template deleted successfully",
"deleteFailed": "Failed to delete template",
"codesGenerated": "Codes generated successfully"
},
"table": {
"columns": {
"no_rewards": "No Rewards"
}
},
"common": {
"currency": {
"yuan": "Yuan"
},
"time": {
"day": "day"
}
}
},
"route": {
"title": "Route Management",
"description": "Manage all route groups, including adding, deleting, and editing operations.",
@@ -1705,6 +1953,7 @@ window.XBOARD_TRANSLATIONS['en-US'] = {
"error_gte_zero": "Base rate must be greater than or equal to 0"
},
"dynamic_rate": {
"section_title": "Dynamic Rate Configuration",
"enable_label": "Enable Dynamic Rate",
"enable_description": "Set different rate multipliers based on time periods",
"rules_label": "Time Period Rules",

View File

@@ -161,6 +161,7 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"planManagement": "套餐管理",
"orderManagement": "订单管理",
"couponManagement": "优惠券管理",
"giftCardManagement": "礼品卡管理",
"userManagement": "用户管理",
"ticketManagement": "工单管理",
"trafficResetLogs": "流量重置日志"
@@ -475,7 +476,8 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"subscribe_path": {
"title": "订阅路径",
"description": "订阅路径修改后将会改变原有的subscribe路径",
"current_format": "当前订阅路径格式:{path}/xxxxxxxxxx"
"current_format": "当前订阅路径格式:{path}/xxxxxxxxxx",
"restart_tip": "修改订阅路径后,可能需要重启服务才能生效。"
},
"show_info_to_server": {
"title": "在订阅中展示订阅信息",
@@ -937,6 +939,8 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"error": "复制失败",
"errorLog": "复制到剪贴板时出错"
},
"submit": "提交",
"saving": "保存中...",
"table": {
"noData": "暂无数据",
"pagination": {
@@ -960,6 +964,15 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"updating": "更新中...",
"updateSuccess": "更新成功,系统将在稍后自动重启",
"updateFailed": "更新失败,请稍后重试"
},
"time": {
"day": "天",
"hour": "小时"
},
"reset": "重置",
"export": "导出",
"currency": {
"yuan": "元"
}
},
"dashboard": {
@@ -1156,6 +1169,348 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"pagination": "第 {{current}}/{{total}} 页,共 {{count}} 条"
}
},
"giftCard": {
"title": "礼品卡管理",
"description": "在这里可以管理礼品卡模板、兑换码和使用记录等功能。",
"tabs": {
"templates": "模板管理",
"codes": "兑换码管理",
"usages": "使用记录",
"statistics": "统计数据"
},
"template": {
"title": "模板管理",
"description": "管理礼品卡模板,包括创建、编辑和删除模板。",
"table": {
"title": "模板列表",
"columns": {
"id": "ID",
"name": "名称",
"type": "类型",
"status": "状态",
"sort": "排序",
"rewards": "奖励内容",
"created_at": "创建时间",
"actions": "操作",
"no_rewards": "无奖励"
}
},
"form": {
"add": "添加模板",
"edit": "编辑模板",
"name": {
"label": "模板名称",
"placeholder": "请输入模板名称",
"required": "请输入模板名称"
},
"sort": {
"label": "排序",
"placeholder": "数字越小越靠前"
},
"type": {
"label": "类型",
"placeholder": "请选择礼品卡类型"
},
"description": {
"label": "描述",
"placeholder": "请输入礼品卡描述"
},
"status": {
"label": "状态",
"description": "禁用后,此模板将无法生成或兑换新的礼品卡。"
},
"display": {
"title": "显示效果"
},
"theme_color": {
"label": "主题颜色"
},
"icon": {
"label": "图标",
"placeholder": "请输入图标的URL"
},
"background_image": {
"label": "背景图片",
"placeholder": "请输入背景图片的URL"
},
"conditions": {
"title": "使用条件",
"new_user_max_days": {
"label": "新用户注册天数限制",
"placeholder": "例如: 7 (仅限注册7天内的用户)"
},
"new_user_only": {
"label": "仅限新用户"
},
"paid_user_only": {
"label": "仅限付费用户"
},
"require_invite": {
"label": "需要邀请关系"
},
"allowed_plans": {
"label": "允许的套餐",
"placeholder": "选择允许兑换的套餐 (留空则不限制)"
},
"disallowed_plans": {
"label": "禁止的套餐",
"placeholder": "选择禁止兑换的套餐 (留空则不限制)"
}
},
"limits": {
"title": "使用限制",
"max_use_per_user": {
"label": "单用户最大使用次数",
"placeholder": "留空则不限制"
},
"cooldown_hours": {
"label": "同类卡冷却时间(小时)",
"placeholder": "留空则不限制"
},
"invite_reward_rate": {
"label": "邀请人奖励比例",
"placeholder": "例如: 0.2 (代表20%)",
"description": "使用者有邀请人时,给邀请人的奖励 = 余额奖励 * 此比例"
}
},
"rewards": {
"title": "奖励内容",
"balance": {
"label": "奖励余额 (元)",
"short_label": "余额",
"placeholder": "请输入奖励的金额(元)"
},
"transfer_enable": {
"label": "奖励流量 (字节)",
"short_label": "流量",
"placeholder": "请输入奖励的流量(字节)"
},
"expire_days": {
"label": "延长有效期 (天)",
"short_label": "有效期",
"placeholder": "请输入延长的天数"
},
"transfer": {
"label": "奖励流量 (字节)",
"placeholder": "请输入奖励的流量(字节)"
},
"days": {
"label": "延长有效期 (天)",
"placeholder": "请输入延长的天数"
},
"device_limit": {
"label": "增加设备数",
"short_label": "设备数",
"placeholder": "请输入增加的设备数量"
},
"reset_package": {
"label": "重置当月流量",
"description": "开启后,兑换时会将用户当前套餐的已用流量清零。"
},
"reset_count": {
"description": "该类型卡将重置用户当月的流量使用。"
},
"task_card": {
"description": "任务礼品卡的具体奖励将在任务系统中配置。"
},
"plan_id": {
"label": "指定套餐",
"short_label": "套餐",
"placeholder": "请选择一个套餐"
},
"plan_validity_days": {
"label": "套餐有效期 (天)",
"short_label": "套餐有效期",
"placeholder": "留空则使用套餐默认有效期"
},
"random_rewards": {
"label": "随机奖励池",
"add": "添加随机奖励项",
"weight": "权重"
}
},
"special_config": {
"title": "特殊配置",
"start_time": {
"label": "活动开始时间",
"placeholder": "请选择开始日期"
},
"end_time": {
"label": "活动结束时间",
"placeholder": "请选择结束日期"
},
"festival_bonus": {
"label": "节日奖励乘数",
"placeholder": "例如: 1.5 (代表1.5倍)"
}
},
"submit": {
"saving": "保存中...",
"save": "保存"
}
},
"actions": {
"edit": "编辑",
"delete": "删除",
"deleteConfirm": {
"title": "确认删除",
"description": "此操作将永久删除该模板,确定要继续吗?",
"confirmText": "删除"
}
}
},
"code": {
"title": "兑换码管理",
"form": {
"generate": "生成兑换码",
"template_id": {
"label": "选择模板",
"placeholder": "请选择一个模板来生成兑换码"
},
"count": {
"label": "生成数量"
},
"prefix": {
"label": "自定义前缀 (可选)"
},
"expires_hours": {
"label": "有效期 (小时)"
},
"max_usage": {
"label": "最大使用次数"
},
"download_csv": "导出CSV",
"submit": {
"generating": "生成中...",
"generate": "立即生成"
}
},
"description": "管理礼品卡兑换码,包括生成、查看和导出兑换码。",
"generate": {
"title": "生成兑换码",
"template": "选择模板",
"count": "生成数量",
"prefix": "自定义前缀",
"expires_hours": "有效期 (小时)",
"max_usage": "最大使用次数",
"submit": "生成"
},
"table": {
"title": "兑换码列表",
"columns": {
"id": "ID",
"code": "兑换码",
"template_name": "模板名称",
"status": "状态",
"expires_at": "过期时间",
"usage_count": "已用次数",
"max_usage": "可用次数",
"created_at": "创建时间"
}
},
"actions": {
"enable": "启用",
"disable": "禁用",
"export": "导出",
"exportConfirm": {
"title": "确认导出",
"description": "将导出选定批次的所有兑换码为文本文件。确定要继续吗?",
"confirmText": "导出"
}
},
"status": {
"0": "未使用",
"1": "已使用",
"2": "已禁用",
"3": "已过期"
}
},
"usage": {
"title": "使用记录",
"description": "查看礼品卡的使用记录和详细信息。",
"table": {
"columns": {
"id": "ID",
"code": "兑换码",
"template_name": "模板名称",
"user_email": "用户邮箱",
"rewards_given": "获得奖励",
"invite_rewards": "邀请奖励",
"multiplier_applied": "倍数加成",
"ip_address": "IP地址",
"created_at": "使用时间",
"actions": "操作"
}
},
"actions": {
"view": "查看详情"
}
},
"statistics": {
"title": "统计数据",
"description": "查看礼品卡的统计数据和使用情况分析。",
"total": {
"title": "总体统计",
"templates_count": "模板总数",
"active_templates_count": "活跃模板数",
"codes_count": "兑换码总数",
"used_codes_count": "已使用兑换码",
"usages_count": "使用记录数"
},
"daily": {
"title": "每日使用量",
"chart": "使用量趋势图"
},
"type": {
"title": "类型统计",
"chart": "类型分布图"
},
"dateRange": {
"label": "日期范围",
"start": "开始日期",
"end": "结束日期"
}
},
"types": {
"1": "通用礼品卡",
"2": "套餐礼品卡",
"3": "盲盒礼品卡",
"4": "任务礼品卡"
},
"common": {
"search": "搜索礼品卡...",
"reset": "重置",
"filter": "筛选",
"export": "导出",
"refresh": "刷新",
"back": "返回",
"close": "关闭",
"confirm": "确认",
"cancel": "取消",
"enabled": "已启用",
"disabled": "已禁用",
"loading": "加载中...",
"noData": "暂无数据",
"success": "操作成功",
"error": "操作失败"
},
"messages": {
"formInvalid": "请检查表单输入是否正确",
"templateCreated": "模板创建成功",
"templateUpdated": "模板更新成功",
"templateDeleted": "模板删除成功",
"codeGenerated": "兑换码生成成功",
"generateCodeFailed": "兑换码生成失败",
"codeStatusUpdated": "兑换码状态更新成功",
"updateCodeStatusFailed": "兑换码状态更新失败",
"codesExported": "兑换码导出成功",
"createTemplateFailed": "创建模板失败",
"updateTemplateFailed": "更新模板失败",
"deleteTemplateFailed": "删除模板失败",
"loadDataFailed": "加载数据失败",
"codesGenerated": "兑换码生成成功"
}
},
"route": {
"title": "路由管理",
"description": "管理所有路由组,包括添加、删除、编辑等操作。",
@@ -1672,6 +2027,7 @@ window.XBOARD_TRANSLATIONS['zh-CN'] = {
"error_gte_zero": "基础倍率必须大于或等于0"
},
"dynamic_rate": {
"section_title": "动态倍率配置",
"enable_label": "启用动态倍率",
"enable_description": "根据时间段设置不同的倍率乘数",
"rules_label": "时间段规则",