feat: 品牌重命名 Sub2API -> TianShuAPI (基于官方 v0.1.46)
- 基于官方最新代码 upstream/main (93db889)
- 包含所有官方新功能:运维监控、促销码系统、Linux DO OAuth 等
- 仅修改品牌显示名称,保持所有功能完整
- 修改范围:前后端界面文字、i18n、邮件模板、日志输出
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,7 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *showVersion {
|
if *showVersion {
|
||||||
log.Printf("Sub2API %s (commit: %s, built: %s)\n", Version, Commit, Date)
|
log.Printf("TianShuAPI %s (commit: %s, built: %s)\n", Version, Commit, Date)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ func runSetupServer() {
|
|||||||
// This allows users to run setup on a different address if needed
|
// This allows users to run setup on a different address if needed
|
||||||
addr := config.GetServerAddress()
|
addr := config.GetServerAddress()
|
||||||
log.Printf("Setup wizard available at http://%s", addr)
|
log.Printf("Setup wizard available at http://%s", addr)
|
||||||
log.Println("Complete the setup wizard to configure Sub2API")
|
log.Println("Complete the setup wizard to configure TianShuAPI")
|
||||||
|
|
||||||
if err := r.Run(addr); err != nil {
|
if err := r.Run(addr); err != nil {
|
||||||
log.Fatalf("Failed to start setup server: %v", err)
|
log.Fatalf("Failed to start setup server: %v", err)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (c *githubReleaseClient) FetchLatestRelease(ctx context.Context, repo strin
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
||||||
req.Header.Set("User-Agent", "Sub2API-Updater")
|
req.Header.Set("User-Agent", "TianShuAPI-Updater")
|
||||||
|
|
||||||
resp, err := c.httpClient.Do(req)
|
resp, err := c.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ func (s *GitHubReleaseServiceSuite) TestFetchLatestRelease_Success() {
|
|||||||
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s.srv = newLocalTestServer(s.T(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
require.Equal(s.T(), "/repos/test/repo/releases/latest", r.URL.Path)
|
require.Equal(s.T(), "/repos/test/repo/releases/latest", r.URL.Path)
|
||||||
require.Equal(s.T(), "application/vnd.github.v3+json", r.Header.Get("Accept"))
|
require.Equal(s.T(), "application/vnd.github.v3+json", r.Header.Get("Accept"))
|
||||||
require.Equal(s.T(), "Sub2API-Updater", r.Header.Get("User-Agent"))
|
require.Equal(s.T(), "TianShuAPI-Updater", r.Header.Get("User-Agent"))
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
_, _ = w.Write([]byte(releaseJSON))
|
_, _ = w.Write([]byte(releaseJSON))
|
||||||
|
|||||||
@@ -271,14 +271,14 @@ func TestAPIContracts(t *testing.T) {
|
|||||||
service.SettingKeySMTPUsername: "user",
|
service.SettingKeySMTPUsername: "user",
|
||||||
service.SettingKeySMTPPassword: "secret",
|
service.SettingKeySMTPPassword: "secret",
|
||||||
service.SettingKeySMTPFrom: "no-reply@example.com",
|
service.SettingKeySMTPFrom: "no-reply@example.com",
|
||||||
service.SettingKeySMTPFromName: "Sub2API",
|
service.SettingKeySMTPFromName: "TianShuAPI",
|
||||||
service.SettingKeySMTPUseTLS: "true",
|
service.SettingKeySMTPUseTLS: "true",
|
||||||
|
|
||||||
service.SettingKeyTurnstileEnabled: "true",
|
service.SettingKeyTurnstileEnabled: "true",
|
||||||
service.SettingKeyTurnstileSiteKey: "site-key",
|
service.SettingKeyTurnstileSiteKey: "site-key",
|
||||||
service.SettingKeyTurnstileSecretKey: "secret-key",
|
service.SettingKeyTurnstileSecretKey: "secret-key",
|
||||||
|
|
||||||
service.SettingKeySiteName: "Sub2API",
|
service.SettingKeySiteName: "TianShuAPI",
|
||||||
service.SettingKeySiteLogo: "",
|
service.SettingKeySiteLogo: "",
|
||||||
service.SettingKeySiteSubtitle: "Subtitle",
|
service.SettingKeySiteSubtitle: "Subtitle",
|
||||||
service.SettingKeyAPIBaseURL: "https://api.example.com",
|
service.SettingKeyAPIBaseURL: "https://api.example.com",
|
||||||
@@ -308,7 +308,7 @@ func TestAPIContracts(t *testing.T) {
|
|||||||
"smtp_username": "user",
|
"smtp_username": "user",
|
||||||
"smtp_password_configured": true,
|
"smtp_password_configured": true,
|
||||||
"smtp_from_email": "no-reply@example.com",
|
"smtp_from_email": "no-reply@example.com",
|
||||||
"smtp_from_name": "Sub2API",
|
"smtp_from_name": "TianShuAPI",
|
||||||
"smtp_use_tls": true,
|
"smtp_use_tls": true,
|
||||||
"turnstile_enabled": true,
|
"turnstile_enabled": true,
|
||||||
"turnstile_site_key": "site-key",
|
"turnstile_site_key": "site-key",
|
||||||
@@ -321,7 +321,7 @@ func TestAPIContracts(t *testing.T) {
|
|||||||
"ops_realtime_monitoring_enabled": true,
|
"ops_realtime_monitoring_enabled": true,
|
||||||
"ops_query_mode_default": "auto",
|
"ops_query_mode_default": "auto",
|
||||||
"ops_metrics_interval_seconds": 60,
|
"ops_metrics_interval_seconds": 60,
|
||||||
"site_name": "Sub2API",
|
"site_name": "TianShuAPI",
|
||||||
"site_logo": "",
|
"site_logo": "",
|
||||||
"site_subtitle": "Subtitle",
|
"site_subtitle": "Subtitle",
|
||||||
"api_base_url": "https://api.example.com",
|
"api_base_url": "https://api.example.com",
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ func (s *AuthService) SendVerifyCode(ctx context.Context, email string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取网站名称
|
// 获取网站名称
|
||||||
siteName := "Sub2API"
|
siteName := "TianShuAPI"
|
||||||
if s.settingService != nil {
|
if s.settingService != nil {
|
||||||
siteName = s.settingService.GetSiteName(ctx)
|
siteName = s.settingService.GetSiteName(ctx)
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ func (s *AuthService) SendVerifyCodeAsync(ctx context.Context, email string) (*S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取网站名称
|
// 获取网站名称
|
||||||
siteName := "Sub2API"
|
siteName := "TianShuAPI"
|
||||||
if s.settingService != nil {
|
if s.settingService != nil {
|
||||||
siteName = s.settingService.GetSiteName(ctx)
|
siteName = s.settingService.GetSiteName(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
|
|||||||
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
EmailVerifyEnabled: settings[SettingKeyEmailVerifyEnabled] == "true",
|
||||||
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
||||||
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
||||||
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "Sub2API"),
|
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "TianShuAPI"),
|
||||||
SiteLogo: settings[SettingKeySiteLogo],
|
SiteLogo: settings[SettingKeySiteLogo],
|
||||||
SiteSubtitle: s.getStringOrDefault(settings, SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
SiteSubtitle: s.getStringOrDefault(settings, SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
||||||
APIBaseURL: settings[SettingKeyAPIBaseURL],
|
APIBaseURL: settings[SettingKeyAPIBaseURL],
|
||||||
@@ -247,7 +247,7 @@ func (s *SettingService) IsEmailVerifyEnabled(ctx context.Context) bool {
|
|||||||
func (s *SettingService) GetSiteName(ctx context.Context) string {
|
func (s *SettingService) GetSiteName(ctx context.Context) string {
|
||||||
value, err := s.settingRepo.GetValue(ctx, SettingKeySiteName)
|
value, err := s.settingRepo.GetValue(ctx, SettingKeySiteName)
|
||||||
if err != nil || value == "" {
|
if err != nil || value == "" {
|
||||||
return "Sub2API"
|
return "TianShuAPI"
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
|
|||||||
defaults := map[string]string{
|
defaults := map[string]string{
|
||||||
SettingKeyRegistrationEnabled: "true",
|
SettingKeyRegistrationEnabled: "true",
|
||||||
SettingKeyEmailVerifyEnabled: "false",
|
SettingKeyEmailVerifyEnabled: "false",
|
||||||
SettingKeySiteName: "Sub2API",
|
SettingKeySiteName: "TianShuAPI",
|
||||||
SettingKeySiteLogo: "",
|
SettingKeySiteLogo: "",
|
||||||
SettingKeyDefaultConcurrency: strconv.Itoa(s.cfg.Default.UserConcurrency),
|
SettingKeyDefaultConcurrency: strconv.Itoa(s.cfg.Default.UserConcurrency),
|
||||||
SettingKeyDefaultBalance: strconv.FormatFloat(s.cfg.Default.UserBalance, 'f', 8, 64),
|
SettingKeyDefaultBalance: strconv.FormatFloat(s.cfg.Default.UserBalance, 'f', 8, 64),
|
||||||
@@ -332,7 +332,7 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
|
|||||||
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
TurnstileEnabled: settings[SettingKeyTurnstileEnabled] == "true",
|
||||||
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
TurnstileSiteKey: settings[SettingKeyTurnstileSiteKey],
|
||||||
TurnstileSecretKeyConfigured: settings[SettingKeyTurnstileSecretKey] != "",
|
TurnstileSecretKeyConfigured: settings[SettingKeyTurnstileSecretKey] != "",
|
||||||
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "Sub2API"),
|
SiteName: s.getStringOrDefault(settings, SettingKeySiteName, "TianShuAPI"),
|
||||||
SiteLogo: settings[SettingKeySiteLogo],
|
SiteLogo: settings[SettingKeySiteLogo],
|
||||||
SiteSubtitle: s.getStringOrDefault(settings, SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
SiteSubtitle: s.getStringOrDefault(settings, SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
||||||
APIBaseURL: settings[SettingKeyAPIBaseURL],
|
APIBaseURL: settings[SettingKeyAPIBaseURL],
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func RunCLI() error {
|
|||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("╔═══════════════════════════════════════════╗")
|
fmt.Println("╔═══════════════════════════════════════════╗")
|
||||||
fmt.Println("║ Sub2API Installation Wizard ║")
|
fmt.Println("║ TianShuAPI Installation Wizard ║")
|
||||||
fmt.Println("╚═══════════════════════════════════════════╝")
|
fmt.Println("╚═══════════════════════════════════════════╝")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* API Client for Sub2API Backend
|
* API Client for TianShuAPI Backend
|
||||||
* Central export point for all API modules
|
* Central export point for all API modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ import { ref, computed, onMounted } from 'vue'
|
|||||||
import { getPublicSettings } from '@/api/auth'
|
import { getPublicSettings } from '@/api/auth'
|
||||||
import { sanitizeUrl } from '@/utils/url'
|
import { sanitizeUrl } from '@/utils/url'
|
||||||
|
|
||||||
const siteName = ref('Sub2API')
|
const siteName = ref('TianShuAPI')
|
||||||
const siteLogo = ref('')
|
const siteLogo = ref('')
|
||||||
const siteSubtitle = ref('Subscription to API Conversion Platform')
|
const siteSubtitle = ref('Subscription to API Conversion Platform')
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ const currentYear = computed(() => new Date().getFullYear())
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const settings = await getPublicSettings()
|
const settings = await getPublicSettings()
|
||||||
siteName.value = settings.site_name || 'Sub2API'
|
siteName.value = settings.site_name || 'TianShuAPI'
|
||||||
siteLogo.value = sanitizeUrl(settings.site_logo || '', { allowRelative: true })
|
siteLogo.value = sanitizeUrl(settings.site_logo || '', { allowRelative: true })
|
||||||
siteSubtitle.value = settings.site_subtitle || 'Subscription to API Conversion Platform'
|
siteSubtitle.value = settings.site_subtitle || 'Subscription to API Conversion Platform'
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Layout Components
|
# Layout Components
|
||||||
|
|
||||||
Vue 3 layout components for the Sub2API frontend, built with Composition API, TypeScript, and TailwindCSS.
|
Vue 3 layout components for the TianShuAPI frontend, built with Composition API, TypeScript, and TailwindCSS.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ export default {
|
|||||||
|
|
||||||
// Setup Wizard
|
// Setup Wizard
|
||||||
setup: {
|
setup: {
|
||||||
title: 'Sub2API Setup',
|
title: 'TianShuAPI Setup',
|
||||||
description: 'Configure your Sub2API instance',
|
description: 'Configure your TianShuAPI instance',
|
||||||
database: {
|
database: {
|
||||||
title: 'Database Configuration',
|
title: 'Database Configuration',
|
||||||
description: 'Connect to your PostgreSQL database',
|
description: 'Connect to your PostgreSQL database',
|
||||||
@@ -2447,7 +2447,7 @@ export default {
|
|||||||
secretKeyConfiguredHint: 'Secret key configured. Leave empty to keep the current value.' },
|
secretKeyConfiguredHint: 'Secret key configured. Leave empty to keep the current value.' },
|
||||||
linuxdo: {
|
linuxdo: {
|
||||||
title: 'LinuxDo Connect Login',
|
title: 'LinuxDo Connect Login',
|
||||||
description: 'Configure LinuxDo Connect OAuth for Sub2API end-user login',
|
description: 'Configure LinuxDo Connect OAuth for TianShuAPI end-user login',
|
||||||
enable: 'Enable LinuxDo Login',
|
enable: 'Enable LinuxDo Login',
|
||||||
enableHint: 'Show LinuxDo login on the login/register pages',
|
enableHint: 'Show LinuxDo login on the login/register pages',
|
||||||
clientId: 'Client ID',
|
clientId: 'Client ID',
|
||||||
@@ -2477,7 +2477,7 @@ export default {
|
|||||||
title: 'Site Settings',
|
title: 'Site Settings',
|
||||||
description: 'Customize site branding',
|
description: 'Customize site branding',
|
||||||
siteName: 'Site Name',
|
siteName: 'Site Name',
|
||||||
siteNamePlaceholder: 'Sub2API',
|
siteNamePlaceholder: 'TianShuAPI',
|
||||||
siteNameHint: 'Displayed in emails and page titles',
|
siteNameHint: 'Displayed in emails and page titles',
|
||||||
siteSubtitle: 'Site Subtitle',
|
siteSubtitle: 'Site Subtitle',
|
||||||
siteSubtitlePlaceholder: 'Subscription to API Conversion Platform',
|
siteSubtitlePlaceholder: 'Subscription to API Conversion Platform',
|
||||||
@@ -2523,7 +2523,7 @@ export default {
|
|||||||
fromEmail: 'From Email',
|
fromEmail: 'From Email',
|
||||||
fromEmailPlaceholder: "noreply{'@'}example.com",
|
fromEmailPlaceholder: "noreply{'@'}example.com",
|
||||||
fromName: 'From Name',
|
fromName: 'From Name',
|
||||||
fromNamePlaceholder: 'Sub2API',
|
fromNamePlaceholder: 'TianShuAPI',
|
||||||
useTls: 'Use TLS',
|
useTls: 'Use TLS',
|
||||||
useTlsHint: 'Enable TLS encryption for SMTP connection'
|
useTlsHint: 'Enable TLS encryption for SMTP connection'
|
||||||
},
|
},
|
||||||
@@ -2692,14 +2692,14 @@ export default {
|
|||||||
// Admin tour steps
|
// Admin tour steps
|
||||||
admin: {
|
admin: {
|
||||||
welcome: {
|
welcome: {
|
||||||
title: '👋 Welcome to Sub2API',
|
title: '👋 Welcome to TianShuAPI',
|
||||||
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">Sub2API is a powerful AI service gateway platform that helps you easily manage and distribute AI services.</p><p style="margin-bottom: 12px;"><b>🎯 Core Features:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>📦 <b>Group Management</b> - Create service tiers (VIP, Free Trial, etc.)</li><li>🔗 <b>Account Pool</b> - Connect multiple upstream AI service accounts</li><li>🔑 <b>Key Distribution</b> - Generate independent API Keys for users</li><li>💰 <b>Billing Control</b> - Flexible rate and quota management</li></ul><p style="color: #10b981; font-weight: 600;">Let\'s complete the initial setup in 3 minutes →</p></div>',
|
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">TianShuAPI is a powerful AI service gateway platform that helps you easily manage and distribute AI services.</p><p style="margin-bottom: 12px;"><b>🎯 Core Features:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>📦 <b>Group Management</b> - Create service tiers (VIP, Free Trial, etc.)</li><li>🔗 <b>Account Pool</b> - Connect multiple upstream AI service accounts</li><li>🔑 <b>Key Distribution</b> - Generate independent API Keys for users</li><li>💰 <b>Billing Control</b> - Flexible rate and quota management</li></ul><p style="color: #10b981; font-weight: 600;">Let\'s complete the initial setup in 3 minutes →</p></div>',
|
||||||
nextBtn: 'Start Setup 🚀',
|
nextBtn: 'Start Setup 🚀',
|
||||||
prevBtn: 'Skip'
|
prevBtn: 'Skip'
|
||||||
},
|
},
|
||||||
groupManage: {
|
groupManage: {
|
||||||
title: '📦 Step 1: Group Management',
|
title: '📦 Step 1: Group Management',
|
||||||
description: '<div style="line-height: 1.7;"><p style="margin-bottom: 12px;"><b>What is a Group?</b></p><p style="margin-bottom: 12px;">Groups are the core concept of Sub2API, like a "service package":</p><ul style="margin-left: 20px; margin-bottom: 12px; font-size: 13px;"><li>🎯 Each group can contain multiple upstream accounts</li><li>💰 Each group has independent billing multiplier</li><li>👥 Can be set as public or exclusive</li></ul><p style="margin-top: 12px; padding: 8px 12px; background: #f0fdf4; border-left: 3px solid #10b981; border-radius: 4px; font-size: 13px;"><b>💡 Example:</b> You can create "VIP Premium" (high rate) and "Free Trial" (low rate) groups</p><p style="margin-top: 16px; color: #10b981; font-weight: 600;">👉 Click "Group Management" on the left sidebar</p></div>'
|
description: '<div style="line-height: 1.7;"><p style="margin-bottom: 12px;"><b>What is a Group?</b></p><p style="margin-bottom: 12px;">Groups are the core concept of TianShuAPI, like a "service package":</p><ul style="margin-left: 20px; margin-bottom: 12px; font-size: 13px;"><li>🎯 Each group can contain multiple upstream accounts</li><li>💰 Each group has independent billing multiplier</li><li>👥 Can be set as public or exclusive</li></ul><p style="margin-top: 12px; padding: 8px 12px; background: #f0fdf4; border-left: 3px solid #10b981; border-radius: 4px; font-size: 13px;"><b>💡 Example:</b> You can create "VIP Premium" (high rate) and "Free Trial" (low rate) groups</p><p style="margin-top: 16px; color: #10b981; font-weight: 600;">👉 Click "Group Management" on the left sidebar</p></div>'
|
||||||
},
|
},
|
||||||
createGroup: {
|
createGroup: {
|
||||||
title: '➕ Create New Group',
|
title: '➕ Create New Group',
|
||||||
@@ -2792,8 +2792,8 @@ export default {
|
|||||||
// User tour steps
|
// User tour steps
|
||||||
user: {
|
user: {
|
||||||
welcome: {
|
welcome: {
|
||||||
title: '👋 Welcome to Sub2API',
|
title: '👋 Welcome to TianShuAPI',
|
||||||
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">Hello! Welcome to the Sub2API AI service platform.</p><p style="margin-bottom: 12px;"><b>🎯 Quick Start:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>🔑 Create API Key</li><li>📋 Copy key to your application</li><li>🚀 Start using AI services</li></ul><p style="color: #10b981; font-weight: 600;">Just 1 minute, let\'s get started →</p></div>',
|
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">Hello! Welcome to the TianShuAPI AI service platform.</p><p style="margin-bottom: 12px;"><b>🎯 Quick Start:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>🔑 Create API Key</li><li>📋 Copy key to your application</li><li>🚀 Start using AI services</li></ul><p style="color: #10b981; font-weight: 600;">Just 1 minute, let\'s get started →</p></div>',
|
||||||
nextBtn: 'Start 🚀',
|
nextBtn: 'Start 🚀',
|
||||||
prevBtn: 'Skip'
|
prevBtn: 'Skip'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export default {
|
|||||||
|
|
||||||
// Setup Wizard
|
// Setup Wizard
|
||||||
setup: {
|
setup: {
|
||||||
title: 'Sub2API 安装向导',
|
title: 'TianShuAPI 安装向导',
|
||||||
description: '配置您的 Sub2API 实例',
|
description: '配置您的 TianShuAPI 实例',
|
||||||
database: {
|
database: {
|
||||||
title: '数据库配置',
|
title: '数据库配置',
|
||||||
description: '连接到您的 PostgreSQL 数据库',
|
description: '连接到您的 PostgreSQL 数据库',
|
||||||
@@ -2592,7 +2592,7 @@ export default {
|
|||||||
secretKeyConfiguredHint: '密钥已配置,留空以保留当前值。' },
|
secretKeyConfiguredHint: '密钥已配置,留空以保留当前值。' },
|
||||||
linuxdo: {
|
linuxdo: {
|
||||||
title: 'LinuxDo Connect 登录',
|
title: 'LinuxDo Connect 登录',
|
||||||
description: '配置 LinuxDo Connect OAuth,用于 Sub2API 用户登录',
|
description: '配置 LinuxDo Connect OAuth,用于 TianShuAPI 用户登录',
|
||||||
enable: '启用 LinuxDo 登录',
|
enable: '启用 LinuxDo 登录',
|
||||||
enableHint: '在登录/注册页面显示 LinuxDo 登录入口',
|
enableHint: '在登录/注册页面显示 LinuxDo 登录入口',
|
||||||
clientId: 'Client ID',
|
clientId: 'Client ID',
|
||||||
@@ -2622,7 +2622,7 @@ export default {
|
|||||||
description: '自定义站点品牌',
|
description: '自定义站点品牌',
|
||||||
siteName: '站点名称',
|
siteName: '站点名称',
|
||||||
siteNameHint: '显示在邮件和页面标题中',
|
siteNameHint: '显示在邮件和页面标题中',
|
||||||
siteNamePlaceholder: 'Sub2API',
|
siteNamePlaceholder: 'TianShuAPI',
|
||||||
siteSubtitle: '站点副标题',
|
siteSubtitle: '站点副标题',
|
||||||
siteSubtitleHint: '显示在登录和注册页面',
|
siteSubtitleHint: '显示在登录和注册页面',
|
||||||
siteSubtitlePlaceholder: '订阅转 API 转换平台',
|
siteSubtitlePlaceholder: '订阅转 API 转换平台',
|
||||||
@@ -2666,7 +2666,7 @@ export default {
|
|||||||
fromEmail: '发件人邮箱',
|
fromEmail: '发件人邮箱',
|
||||||
fromEmailPlaceholder: "noreply{'@'}example.com",
|
fromEmailPlaceholder: "noreply{'@'}example.com",
|
||||||
fromName: '发件人名称',
|
fromName: '发件人名称',
|
||||||
fromNamePlaceholder: 'Sub2API',
|
fromNamePlaceholder: 'TianShuAPI',
|
||||||
useTls: '使用 TLS',
|
useTls: '使用 TLS',
|
||||||
useTlsHint: '为 SMTP 连接启用 TLS 加密'
|
useTlsHint: '为 SMTP 连接启用 TLS 加密'
|
||||||
},
|
},
|
||||||
@@ -2833,14 +2833,14 @@ export default {
|
|||||||
// Admin tour steps
|
// Admin tour steps
|
||||||
admin: {
|
admin: {
|
||||||
welcome: {
|
welcome: {
|
||||||
title: '👋 欢迎使用 Sub2API',
|
title: '👋 欢迎使用 TianShuAPI',
|
||||||
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">Sub2API 是一个强大的 AI 服务中转平台,让您轻松管理和分发 AI 服务。</p><p style="margin-bottom: 12px;"><b>🎯 核心功能:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>📦 <b>分组管理</b> - 创建不同的服务套餐(VIP、免费试用等)</li><li>🔗 <b>账号池</b> - 连接多个上游 AI 服务商账号</li><li>🔑 <b>密钥分发</b> - 为用户生成独立的 API Key</li><li>💰 <b>计费管理</b> - 灵活的费率和配额控制</li></ul><p style="color: #10b981; font-weight: 600;">接下来,我们将用 3 分钟带您完成首次配置 →</p></div>',
|
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">TianShuAPI 是一个强大的 AI 服务中转平台,让您轻松管理和分发 AI 服务。</p><p style="margin-bottom: 12px;"><b>🎯 核心功能:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>📦 <b>分组管理</b> - 创建不同的服务套餐(VIP、免费试用等)</li><li>🔗 <b>账号池</b> - 连接多个上游 AI 服务商账号</li><li>🔑 <b>密钥分发</b> - 为用户生成独立的 API Key</li><li>💰 <b>计费管理</b> - 灵活的费率和配额控制</li></ul><p style="color: #10b981; font-weight: 600;">接下来,我们将用 3 分钟带您完成首次配置 →</p></div>',
|
||||||
nextBtn: '开始配置 🚀',
|
nextBtn: '开始配置 🚀',
|
||||||
prevBtn: '跳过'
|
prevBtn: '跳过'
|
||||||
},
|
},
|
||||||
groupManage: {
|
groupManage: {
|
||||||
title: '📦 第一步:分组管理',
|
title: '📦 第一步:分组管理',
|
||||||
description: '<div style="line-height: 1.7;"><p style="margin-bottom: 12px;"><b>什么是分组?</b></p><p style="margin-bottom: 12px;">分组是 Sub2API 的核心概念,它就像一个"服务套餐":</p><ul style="margin-left: 20px; margin-bottom: 12px; font-size: 13px;"><li>🎯 每个分组可以包含多个上游账号</li><li>💰 每个分组有独立的计费倍率</li><li>👥 可以设置为公开或专属分组</li></ul><p style="margin-top: 12px; padding: 8px 12px; background: #f0fdf4; border-left: 3px solid #10b981; border-radius: 4px; font-size: 13px;"><b>💡 示例:</b>您可以创建"VIP专线"(高倍率)和"免费试用"(低倍率)两个分组</p><p style="margin-top: 16px; color: #10b981; font-weight: 600;">👉 点击左侧的"分组管理"开始</p></div>'
|
description: '<div style="line-height: 1.7;"><p style="margin-bottom: 12px;"><b>什么是分组?</b></p><p style="margin-bottom: 12px;">分组是 TianShuAPI 的核心概念,它就像一个"服务套餐":</p><ul style="margin-left: 20px; margin-bottom: 12px; font-size: 13px;"><li>🎯 每个分组可以包含多个上游账号</li><li>💰 每个分组有独立的计费倍率</li><li>👥 可以设置为公开或专属分组</li></ul><p style="margin-top: 12px; padding: 8px 12px; background: #f0fdf4; border-left: 3px solid #10b981; border-radius: 4px; font-size: 13px;"><b>💡 示例:</b>您可以创建"VIP专线"(高倍率)和"免费试用"(低倍率)两个分组</p><p style="margin-top: 16px; color: #10b981; font-weight: 600;">👉 点击左侧的"分组管理"开始</p></div>'
|
||||||
},
|
},
|
||||||
createGroup: {
|
createGroup: {
|
||||||
title: '➕ 创建新分组',
|
title: '➕ 创建新分组',
|
||||||
@@ -2933,8 +2933,8 @@ export default {
|
|||||||
// User tour steps
|
// User tour steps
|
||||||
user: {
|
user: {
|
||||||
welcome: {
|
welcome: {
|
||||||
title: '👋 欢迎使用 Sub2API',
|
title: '👋 欢迎使用 TianShuAPI',
|
||||||
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">您好!欢迎来到 Sub2API AI 服务平台。</p><p style="margin-bottom: 12px;"><b>🎯 快速开始:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>🔑 创建 API 密钥</li><li>📋 复制密钥到您的应用</li><li>🚀 开始使用 AI 服务</li></ul><p style="color: #10b981; font-weight: 600;">只需 1 分钟,让我们开始吧 →</p></div>',
|
description: '<div style="line-height: 1.8;"><p style="margin-bottom: 16px;">您好!欢迎来到 TianShuAPI AI 服务平台。</p><p style="margin-bottom: 12px;"><b>🎯 快速开始:</b></p><ul style="margin-left: 20px; margin-bottom: 16px;"><li>🔑 创建 API 密钥</li><li>📋 复制密钥到您的应用</li><li>🚀 开始使用 AI 服务</li></ul><p style="color: #10b981; font-weight: 600;">只需 1 分钟,让我们开始吧 →</p></div>',
|
||||||
nextBtn: '开始 🚀',
|
nextBtn: '开始 🚀',
|
||||||
prevBtn: '跳过'
|
prevBtn: '跳过'
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const appStore = useAppStore()
|
|||||||
appStore.initFromInjectedConfig()
|
appStore.initFromInjectedConfig()
|
||||||
|
|
||||||
// Set document title immediately after config is loaded
|
// Set document title immediately after config is loaded
|
||||||
if (appStore.siteName && appStore.siteName !== 'Sub2API') {
|
if (appStore.siteName && appStore.siteName !== 'TianShuAPI') {
|
||||||
document.title = `${appStore.siteName} - AI API Gateway`
|
document.title = `${appStore.siteName} - AI API Gateway`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This directory contains the Vue Router configuration for the Sub2API frontend application. The router implements a comprehensive navigation system with authentication guards, role-based access control, and lazy loading.
|
This directory contains the Vue Router configuration for the TianShuAPI frontend application. The router implements a comprehensive navigation system with authentication guards, role-based access control, and lazy loading.
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Vue Router configuration for Sub2API frontend
|
* Vue Router configuration for TianShuAPI frontend
|
||||||
* Defines all application routes with lazy loading and navigation guards
|
* Defines all application routes with lazy loading and navigation guards
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ router.beforeEach((to, _from, next) => {
|
|||||||
|
|
||||||
// Set page title
|
// Set page title
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const siteName = appStore.siteName || 'Sub2API'
|
const siteName = appStore.siteName || 'TianShuAPI'
|
||||||
if (to.meta.title) {
|
if (to.meta.title) {
|
||||||
document.title = `${to.meta.title} - ${siteName}`
|
document.title = `${to.meta.title} - ${siteName}`
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Pinia Stores Documentation
|
# Pinia Stores Documentation
|
||||||
|
|
||||||
This directory contains all Pinia stores for the Sub2API frontend application.
|
This directory contains all Pinia stores for the TianShuAPI frontend application.
|
||||||
|
|
||||||
## Stores Overview
|
## Stores Overview
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const useAppStore = defineStore('app', () => {
|
|||||||
// Public settings cache state
|
// Public settings cache state
|
||||||
const publicSettingsLoaded = ref<boolean>(false)
|
const publicSettingsLoaded = ref<boolean>(false)
|
||||||
const publicSettingsLoading = ref<boolean>(false)
|
const publicSettingsLoading = ref<boolean>(false)
|
||||||
const siteName = ref<string>('Sub2API')
|
const siteName = ref<string>('TianShuAPI')
|
||||||
const siteLogo = ref<string>('')
|
const siteLogo = ref<string>('')
|
||||||
const siteVersion = ref<string>('')
|
const siteVersion = ref<string>('')
|
||||||
const contactInfo = ref<string>('')
|
const contactInfo = ref<string>('')
|
||||||
@@ -284,7 +284,7 @@ export const useAppStore = defineStore('app', () => {
|
|||||||
*/
|
*/
|
||||||
function applySettings(config: PublicSettings): void {
|
function applySettings(config: PublicSettings): void {
|
||||||
cachedPublicSettings.value = config
|
cachedPublicSettings.value = config
|
||||||
siteName.value = config.site_name || 'Sub2API'
|
siteName.value = config.site_name || 'TianShuAPI'
|
||||||
siteLogo.value = config.site_logo || ''
|
siteLogo.value = config.site_logo || ''
|
||||||
siteVersion.value = config.version || ''
|
siteVersion.value = config.version || ''
|
||||||
contactInfo.value = config.contact_info || ''
|
contactInfo.value = config.contact_info || ''
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Core Type Definitions for Sub2API Frontend
|
* Core Type Definitions for TianShuAPI Frontend
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ==================== Common Types ====================
|
// ==================== Common Types ====================
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ const authStore = useAuthStore()
|
|||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
// Site settings - directly from appStore (already initialized from injected config)
|
// Site settings - directly from appStore (already initialized from injected config)
|
||||||
const siteName = computed(() => appStore.cachedPublicSettings?.site_name || appStore.siteName || 'Sub2API')
|
const siteName = computed(() => appStore.cachedPublicSettings?.site_name || appStore.siteName || 'TianShuAPI')
|
||||||
const siteLogo = computed(() => appStore.cachedPublicSettings?.site_logo || appStore.siteLogo || '')
|
const siteLogo = computed(() => appStore.cachedPublicSettings?.site_logo || appStore.siteLogo || '')
|
||||||
const siteSubtitle = computed(() => appStore.cachedPublicSettings?.site_subtitle || 'AI API Gateway Platform')
|
const siteSubtitle = computed(() => appStore.cachedPublicSettings?.site_subtitle || 'AI API Gateway Platform')
|
||||||
const docUrl = computed(() => appStore.cachedPublicSettings?.doc_url || appStore.docUrl || '')
|
const docUrl = computed(() => appStore.cachedPublicSettings?.doc_url || appStore.docUrl || '')
|
||||||
|
|||||||
@@ -1000,7 +1000,7 @@ const form = reactive<SettingsForm>({
|
|||||||
email_verify_enabled: false,
|
email_verify_enabled: false,
|
||||||
default_balance: 0,
|
default_balance: 0,
|
||||||
default_concurrency: 1,
|
default_concurrency: 1,
|
||||||
site_name: 'Sub2API',
|
site_name: 'TianShuAPI',
|
||||||
site_logo: '',
|
site_logo: '',
|
||||||
site_subtitle: 'Subscription to API Conversion Platform',
|
site_subtitle: 'Subscription to API Conversion Platform',
|
||||||
api_base_url: '',
|
api_base_url: '',
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ const hasRegisterData = ref<boolean>(false)
|
|||||||
// Public settings
|
// Public settings
|
||||||
const turnstileEnabled = ref<boolean>(false)
|
const turnstileEnabled = ref<boolean>(false)
|
||||||
const turnstileSiteKey = ref<string>('')
|
const turnstileSiteKey = ref<string>('')
|
||||||
const siteName = ref<string>('Sub2API')
|
const siteName = ref<string>('TianShuAPI')
|
||||||
|
|
||||||
// Turnstile for resend
|
// Turnstile for resend
|
||||||
const turnstileRef = ref<InstanceType<typeof TurnstileWidget> | null>(null)
|
const turnstileRef = ref<InstanceType<typeof TurnstileWidget> | null>(null)
|
||||||
@@ -241,7 +241,7 @@ onMounted(async () => {
|
|||||||
const settings = await getPublicSettings()
|
const settings = await getPublicSettings()
|
||||||
turnstileEnabled.value = settings.turnstile_enabled
|
turnstileEnabled.value = settings.turnstile_enabled
|
||||||
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
||||||
siteName.value = settings.site_name || 'Sub2API'
|
siteName.value = settings.site_name || 'TianShuAPI'
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load public settings:', error)
|
console.error('Failed to load public settings:', error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Authentication Views
|
# Authentication Views
|
||||||
|
|
||||||
This directory contains Vue 3 authentication views for the Sub2API frontend application.
|
This directory contains Vue 3 authentication views for the TianShuAPI frontend application.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ const registrationEnabled = ref<boolean>(true)
|
|||||||
const emailVerifyEnabled = ref<boolean>(false)
|
const emailVerifyEnabled = ref<boolean>(false)
|
||||||
const turnstileEnabled = ref<boolean>(false)
|
const turnstileEnabled = ref<boolean>(false)
|
||||||
const turnstileSiteKey = ref<string>('')
|
const turnstileSiteKey = ref<string>('')
|
||||||
const siteName = ref<string>('Sub2API')
|
const siteName = ref<string>('TianShuAPI')
|
||||||
const linuxdoOAuthEnabled = ref<boolean>(false)
|
const linuxdoOAuthEnabled = ref<boolean>(false)
|
||||||
|
|
||||||
// Turnstile
|
// Turnstile
|
||||||
@@ -308,7 +308,7 @@ onMounted(async () => {
|
|||||||
emailVerifyEnabled.value = settings.email_verify_enabled
|
emailVerifyEnabled.value = settings.email_verify_enabled
|
||||||
turnstileEnabled.value = settings.turnstile_enabled
|
turnstileEnabled.value = settings.turnstile_enabled
|
||||||
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
turnstileSiteKey.value = settings.turnstile_site_key || ''
|
||||||
siteName.value = settings.site_name || 'Sub2API'
|
siteName.value = settings.site_name || 'TianShuAPI'
|
||||||
linuxdoOAuthEnabled.value = settings.linuxdo_oauth_enabled
|
linuxdoOAuthEnabled.value = settings.linuxdo_oauth_enabled
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load public settings:', error)
|
console.error('Failed to load public settings:', error)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Authentication Views Usage Examples
|
# Authentication Views Usage Examples
|
||||||
|
|
||||||
This document provides practical examples of how to use the authentication views in the Sub2API frontend.
|
This document provides practical examples of how to use the authentication views in the TianShuAPI frontend.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ This document provides practical examples of how to use the authentication views
|
|||||||
// - On success:
|
// - On success:
|
||||||
// - Token stored in localStorage
|
// - Token stored in localStorage
|
||||||
// - User data stored in state
|
// - User data stored in state
|
||||||
// - Success toast: "Account created successfully! Welcome to Sub2API."
|
// - Success toast: "Account created successfully! Welcome to TianShuAPI."
|
||||||
// - Redirect to /dashboard
|
// - Redirect to /dashboard
|
||||||
// - On error:
|
// - On error:
|
||||||
// - Error message displayed inline
|
// - Error message displayed inline
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Both LoginView and RegisterView use the AuthLayout component, which provides:
|
|||||||
│ │
|
│ │
|
||||||
│ ┌─────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────┐ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ Sub2API Logo │ │
|
│ │ TianShuAPI Logo │ │
|
||||||
│ │ "Subscription to API Conversion" │ │
|
│ │ "Subscription to API Conversion" │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ └─────────────────────────────────────┘ │
|
│ └─────────────────────────────────────┘ │
|
||||||
@@ -39,7 +39,7 @@ Centered: Both horizontally and vertically
|
|||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
│ 🔷 Sub2API │
|
│ 🔷 TianShuAPI │
|
||||||
│ Subscription to API Conversion Platform │
|
│ Subscription to API Conversion Platform │
|
||||||
│ │
|
│ │
|
||||||
│ ┌─────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────┐ │
|
||||||
@@ -133,13 +133,13 @@ Centered: Both horizontally and vertically
|
|||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
│ 🔷 Sub2API │
|
│ 🔷 TianShuAPI │
|
||||||
│ Subscription to API Conversion Platform │
|
│ Subscription to API Conversion Platform │
|
||||||
│ │
|
│ │
|
||||||
│ ┌─────────────────────────────────────┐ │
|
│ ┌─────────────────────────────────────┐ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ Create Account │ │
|
│ │ Create Account │ │
|
||||||
│ │ Sign up to start using Sub2API │ │
|
│ │ Sign up to start using TianShuAPI │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ Username │ │
|
│ │ Username │ │
|
||||||
│ │ ┌────────────────────────────────┐ │ │
|
│ │ ┌────────────────────────────────┐ │ │
|
||||||
|
|||||||
Reference in New Issue
Block a user