mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
feat(channels): gate available channels behind feature switch (frontend)
Wire the new available_channels_enabled setting end-to-end on the frontend — hide the user sidebar entry by default and surface the toggle under Admin Settings > Features. - types/PublicSettings + api/admin/settings SystemSettings + UpdateSettingsRequest: add available_channels_enabled - stores/app cached fallback: available_channels_enabled: false - AppSidebar: add flagAvailableChannels getter (strict === true: default hide), apply to /available-channels nav entry - SettingsView: Features tab — new Toggle card, form default/payload - i18n (zh/en): admin.settings.features.availableChannels.*
This commit is contained in:
@@ -148,6 +148,9 @@ export interface SystemSettings {
|
||||
// Channel Monitor feature switch
|
||||
channel_monitor_enabled: boolean
|
||||
channel_monitor_default_interval_seconds: number
|
||||
|
||||
// Available Channels feature switch
|
||||
available_channels_enabled: boolean
|
||||
}
|
||||
|
||||
export interface UpdateSettingsRequest {
|
||||
@@ -259,6 +262,9 @@ export interface UpdateSettingsRequest {
|
||||
// Channel Monitor feature switch
|
||||
channel_monitor_enabled?: boolean
|
||||
channel_monitor_default_interval_seconds?: number
|
||||
|
||||
// Available Channels feature switch
|
||||
available_channels_enabled?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -631,6 +631,9 @@ const ChevronDownIcon = {
|
||||
// getter 返回 false = 隐藏;undefined/true = 显示(宽容策略,避免 public settings 未加载闪烁)。
|
||||
const flagChannelMonitor = () => appStore.cachedPublicSettings?.channel_monitor_enabled
|
||||
const flagPayment = () => appStore.cachedPublicSettings?.payment_enabled
|
||||
// Opt-in feature:默认关闭,未加载 settings 时也视为关闭(严格 === true 判定)
|
||||
const flagAvailableChannels = () =>
|
||||
appStore.cachedPublicSettings?.available_channels_enabled === true
|
||||
const flagOpsMonitoring = () => adminSettingsStore.opsMonitoringEnabled
|
||||
const flagAdminPayment = () => adminSettingsStore.paymentEnabled
|
||||
|
||||
@@ -648,7 +651,7 @@ function buildSelfNavItems(withDashboard: boolean): NavItem[] {
|
||||
{ path: '/subscriptions', label: t('nav.mySubscriptions'), icon: CreditCardIcon, hideInSimpleMode: true },
|
||||
{ path: '/purchase', label: t('nav.buySubscription'), icon: RechargeSubscriptionIcon, hideInSimpleMode: true, featureFlag: flagPayment },
|
||||
{ path: '/orders', label: t('nav.myOrders'), icon: OrderListIcon, hideInSimpleMode: true, featureFlag: flagPayment },
|
||||
{ path: '/available-channels', label: t('nav.availableChannels'), icon: ChannelIcon, hideInSimpleMode: true },
|
||||
{ path: '/available-channels', label: t('nav.availableChannels'), icon: ChannelIcon, hideInSimpleMode: true, featureFlag: flagAvailableChannels },
|
||||
{ path: '/redeem', label: t('nav.redeem'), icon: GiftIcon, hideInSimpleMode: true },
|
||||
{ path: '/profile', label: t('nav.profile'), icon: UserIcon },
|
||||
...customMenuItemsForUser.value.map((item): NavItem => ({
|
||||
|
||||
@@ -4541,6 +4541,12 @@ export default {
|
||||
defaultInterval: 'Default check interval (seconds)',
|
||||
defaultIntervalHint: 'Pre-fills the interval when creating a new monitor; each monitor can override it. Range 15 – 3600.',
|
||||
},
|
||||
availableChannels: {
|
||||
title: 'Available Channels',
|
||||
description: 'Show logged-in users an aggregate view of the channels, models and pricing they can access. Disabled by default.',
|
||||
enabled: 'Enable Available Channels',
|
||||
enabledHint: 'When off, the sidebar entry is hidden and the endpoint returns an empty list.',
|
||||
},
|
||||
},
|
||||
emailTabDisabledTitle: 'Email Verification Not Enabled',
|
||||
emailTabDisabledHint: 'Enable email verification in the Security tab to configure SMTP settings.',
|
||||
|
||||
@@ -4714,6 +4714,12 @@ export default {
|
||||
defaultInterval: '默认检测间隔(秒)',
|
||||
defaultIntervalHint: '新建渠道监控时表单的默认值,可被单个渠道覆盖。范围 15 – 3600 秒。',
|
||||
},
|
||||
availableChannels: {
|
||||
title: '可用渠道',
|
||||
description: '向已登录用户展示他们能访问的渠道、模型和定价聚合视图。默认关闭。',
|
||||
enabled: '启用可用渠道',
|
||||
enabledHint: '关闭后用户端侧边栏入口隐藏,接口返回空数组。',
|
||||
},
|
||||
},
|
||||
emailTabDisabledTitle: '邮箱验证未启用',
|
||||
emailTabDisabledHint: '请在「安全与认证」选项卡中启用邮箱验证后,再配置 SMTP 设置。',
|
||||
|
||||
@@ -345,6 +345,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
balance_low_notify_threshold: 0,
|
||||
channel_monitor_enabled: true,
|
||||
channel_monitor_default_interval_seconds: 60,
|
||||
available_channels_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ export interface PublicSettings {
|
||||
balance_low_notify_threshold: number
|
||||
channel_monitor_enabled: boolean
|
||||
channel_monitor_default_interval_seconds: number
|
||||
available_channels_enabled: boolean
|
||||
}
|
||||
|
||||
export interface AuthResponse {
|
||||
|
||||
@@ -2416,6 +2416,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="border-b border-gray-100 px-6 py-4 dark:border-dark-700">
|
||||
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
{{ t('admin.settings.features.availableChannels.title') }}
|
||||
</h2>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
{{ t('admin.settings.features.availableChannels.description') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="space-y-5 p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('admin.settings.features.availableChannels.enabled') }}
|
||||
</label>
|
||||
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t('admin.settings.features.availableChannels.enabledHint') }}
|
||||
</p>
|
||||
</div>
|
||||
<Toggle v-model="form.available_channels_enabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /Tab: Features -->
|
||||
|
||||
<!-- Tab: Email -->
|
||||
@@ -3145,7 +3169,9 @@ const form = reactive<SettingsForm>({
|
||||
account_quota_notify_emails: [] as NotifyEmailEntry[],
|
||||
// Channel Monitor feature switch
|
||||
channel_monitor_enabled: true,
|
||||
channel_monitor_default_interval_seconds: 60
|
||||
channel_monitor_default_interval_seconds: 60,
|
||||
// Available Channels feature switch
|
||||
available_channels_enabled: false
|
||||
})
|
||||
|
||||
// Proxies for web search emulation ProxySelector
|
||||
@@ -3749,6 +3775,8 @@ async function saveSettings() {
|
||||
// Channel Monitor feature switch
|
||||
channel_monitor_enabled: form.channel_monitor_enabled,
|
||||
channel_monitor_default_interval_seconds: Number(form.channel_monitor_default_interval_seconds) || 60,
|
||||
// Available Channels feature switch
|
||||
available_channels_enabled: form.available_channels_enabled,
|
||||
}
|
||||
|
||||
const updated = await adminAPI.settings.updateSettings(payload)
|
||||
|
||||
Reference in New Issue
Block a user