feat(settings): 添加文档链接配置功能
- 后台系统设置新增文档链接(doc_url)配置项 - 首页顶部导航栏显示文档链接图标(条件渲染) - Footer区域添加文档链接和GitHub链接 - 支持中英文国际化
This commit is contained in:
@@ -60,6 +60,7 @@ type UpdateSettingsRequest struct {
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
ApiBaseUrl string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocUrl string `json:"doc_url"`
|
||||
|
||||
// 默认配置
|
||||
DefaultConcurrency int `json:"default_concurrency"`
|
||||
@@ -104,6 +105,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
SiteSubtitle: req.SiteSubtitle,
|
||||
ApiBaseUrl: req.ApiBaseUrl,
|
||||
ContactInfo: req.ContactInfo,
|
||||
DocUrl: req.DocUrl,
|
||||
DefaultConcurrency: req.DefaultConcurrency,
|
||||
DefaultBalance: req.DefaultBalance,
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ const (
|
||||
SettingKeySiteSubtitle = "site_subtitle" // 网站副标题
|
||||
SettingKeyApiBaseUrl = "api_base_url" // API端点地址(用于客户端配置和导入)
|
||||
SettingKeyContactInfo = "contact_info" // 客服联系方式
|
||||
SettingKeyDocUrl = "doc_url" // 文档链接
|
||||
|
||||
// 默认配置
|
||||
SettingKeyDefaultConcurrency = "default_concurrency" // 新用户默认并发量
|
||||
@@ -80,6 +81,7 @@ type SystemSettings struct {
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
ApiBaseUrl string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocUrl string `json:"doc_url"`
|
||||
|
||||
// 默认配置
|
||||
DefaultConcurrency int `json:"default_concurrency"`
|
||||
@@ -97,5 +99,6 @@ type PublicSettings struct {
|
||||
SiteSubtitle string `json:"site_subtitle"`
|
||||
ApiBaseUrl string `json:"api_base_url"`
|
||||
ContactInfo string `json:"contact_info"`
|
||||
DocUrl string `json:"doc_url"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*model.PublicSe
|
||||
model.SettingKeySiteSubtitle,
|
||||
model.SettingKeyApiBaseUrl,
|
||||
model.SettingKeyContactInfo,
|
||||
model.SettingKeyDocUrl,
|
||||
}
|
||||
|
||||
settings, err := s.settingRepo.GetMultiple(ctx, keys)
|
||||
@@ -71,6 +72,7 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*model.PublicSe
|
||||
SiteSubtitle: s.getStringOrDefault(settings, model.SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
||||
ApiBaseUrl: settings[model.SettingKeyApiBaseUrl],
|
||||
ContactInfo: settings[model.SettingKeyContactInfo],
|
||||
DocUrl: settings[model.SettingKeyDocUrl],
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -106,6 +108,7 @@ func (s *SettingService) UpdateSettings(ctx context.Context, settings *model.Sys
|
||||
updates[model.SettingKeySiteSubtitle] = settings.SiteSubtitle
|
||||
updates[model.SettingKeyApiBaseUrl] = settings.ApiBaseUrl
|
||||
updates[model.SettingKeyContactInfo] = settings.ContactInfo
|
||||
updates[model.SettingKeyDocUrl] = settings.DocUrl
|
||||
|
||||
// 默认配置
|
||||
updates[model.SettingKeyDefaultConcurrency] = strconv.Itoa(settings.DefaultConcurrency)
|
||||
@@ -210,6 +213,7 @@ func (s *SettingService) parseSettings(settings map[string]string) *model.System
|
||||
SiteSubtitle: s.getStringOrDefault(settings, model.SettingKeySiteSubtitle, "Subscription to API Conversion Platform"),
|
||||
ApiBaseUrl: settings[model.SettingKeyApiBaseUrl],
|
||||
ContactInfo: settings[model.SettingKeyContactInfo],
|
||||
DocUrl: settings[model.SettingKeyDocUrl],
|
||||
}
|
||||
|
||||
// 解析整数类型
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface SystemSettings {
|
||||
site_subtitle: string;
|
||||
api_base_url: string;
|
||||
contact_info: string;
|
||||
doc_url: string;
|
||||
// SMTP settings
|
||||
smtp_host: string;
|
||||
smtp_port: number;
|
||||
|
||||
@@ -2,6 +2,8 @@ export default {
|
||||
// Home Page
|
||||
home: {
|
||||
viewOnGithub: 'View on GitHub',
|
||||
viewDocs: 'View Documentation',
|
||||
docs: 'Docs',
|
||||
switchToLight: 'Switch to Light Mode',
|
||||
switchToDark: 'Switch to Dark Mode',
|
||||
dashboard: 'Dashboard',
|
||||
@@ -1077,6 +1079,8 @@ export default {
|
||||
contactInfo: 'Contact Info',
|
||||
contactInfoPlaceholder: 'e.g., QQ: 123456789',
|
||||
contactInfoHint: 'Customer support contact info, displayed on redeem page, profile, etc.',
|
||||
docUrl: 'Documentation URL',
|
||||
docUrlHint: 'Link to your documentation site. Leave empty to hide the documentation link.',
|
||||
siteLogo: 'Site Logo',
|
||||
uploadImage: 'Upload Image',
|
||||
remove: 'Remove',
|
||||
|
||||
@@ -2,6 +2,8 @@ export default {
|
||||
// Home Page
|
||||
home: {
|
||||
viewOnGithub: '在 GitHub 上查看',
|
||||
viewDocs: '查看文档',
|
||||
docs: '文档',
|
||||
switchToLight: '切换到浅色模式',
|
||||
switchToDark: '切换到深色模式',
|
||||
dashboard: '控制台',
|
||||
@@ -1301,6 +1303,8 @@ export default {
|
||||
contactInfo: '客服联系方式',
|
||||
contactInfoPlaceholder: '例如:QQ: 123456789',
|
||||
contactInfoHint: '填写客服联系方式,将展示在兑换页面、个人资料等位置',
|
||||
docUrl: '文档链接',
|
||||
docUrlHint: '文档网站的链接。留空则隐藏文档链接。',
|
||||
siteLogo: '站点Logo',
|
||||
uploadImage: '上传图片',
|
||||
remove: '移除',
|
||||
|
||||
@@ -25,6 +25,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
const siteVersion = ref<string>('');
|
||||
const contactInfo = ref<string>('');
|
||||
const apiBaseUrl = ref<string>('');
|
||||
const docUrl = ref<string>('');
|
||||
|
||||
// Version cache state
|
||||
const versionLoaded = ref<boolean>(false);
|
||||
@@ -297,6 +298,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
site_subtitle: '',
|
||||
api_base_url: apiBaseUrl.value,
|
||||
contact_info: contactInfo.value,
|
||||
doc_url: docUrl.value,
|
||||
version: siteVersion.value,
|
||||
};
|
||||
}
|
||||
@@ -314,6 +316,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
siteVersion.value = data.version || '';
|
||||
contactInfo.value = data.contact_info || '';
|
||||
apiBaseUrl.value = data.api_base_url || '';
|
||||
docUrl.value = data.doc_url || '';
|
||||
publicSettingsLoaded.value = true;
|
||||
return data;
|
||||
} catch (error) {
|
||||
@@ -347,6 +350,7 @@ export const useAppStore = defineStore('app', () => {
|
||||
siteVersion,
|
||||
contactInfo,
|
||||
apiBaseUrl,
|
||||
docUrl,
|
||||
|
||||
// Version state
|
||||
versionLoaded,
|
||||
|
||||
@@ -53,6 +53,7 @@ export interface PublicSettings {
|
||||
site_subtitle: string;
|
||||
api_base_url: string;
|
||||
contact_info: string;
|
||||
doc_url: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,17 @@
|
||||
<!-- Language Switcher -->
|
||||
<LocaleSwitcher />
|
||||
|
||||
<!-- GitHub Link -->
|
||||
<!-- Doc Link -->
|
||||
<a
|
||||
:href="githubUrl"
|
||||
v-if="docUrl"
|
||||
:href="docUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="p-2 rounded-lg text-gray-500 hover:text-gray-700 dark:text-dark-400 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-dark-800 transition-colors"
|
||||
:title="t('home.viewOnGithub')"
|
||||
:title="t('home.viewDocs')"
|
||||
>
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.604-3.369-1.34-3.369-1.34-.454-1.156-1.11-1.464-1.11-1.464-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.831.092-.646.35-1.086.636-1.336-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.025A9.578 9.578 0 0112 6.836c.85.004 1.705.114 2.504.336 1.909-1.294 2.747-1.025 2.747-1.025.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z" />
|
||||
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
@@ -253,10 +254,29 @@
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="relative z-10 px-6 py-8 border-t border-gray-200/50 dark:border-dark-800/50">
|
||||
<div class="max-w-6xl mx-auto text-center">
|
||||
<div class="max-w-6xl mx-auto flex flex-col sm:flex-row items-center justify-center gap-4 text-center sm:text-left">
|
||||
<p class="text-sm text-gray-500 dark:text-dark-400">
|
||||
© {{ currentYear }} {{ siteName }}. {{ t('home.footer.allRightsReserved') }}
|
||||
</p>
|
||||
<div class="flex items-center gap-4">
|
||||
<a
|
||||
v-if="docUrl"
|
||||
:href="docUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-sm text-gray-500 hover:text-gray-700 dark:text-dark-400 dark:hover:text-white transition-colors"
|
||||
>
|
||||
{{ t('home.docs') }}
|
||||
</a>
|
||||
<a
|
||||
:href="githubUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-sm text-gray-500 hover:text-gray-700 dark:text-dark-400 dark:hover:text-white transition-colors"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
@@ -277,6 +297,7 @@ const authStore = useAuthStore();
|
||||
const siteName = ref('Sub2API');
|
||||
const siteLogo = ref('');
|
||||
const siteSubtitle = ref('AI API Gateway Platform');
|
||||
const docUrl = ref('');
|
||||
|
||||
// Theme
|
||||
const isDark = ref(document.documentElement.classList.contains('dark'));
|
||||
@@ -322,6 +343,7 @@ onMounted(async () => {
|
||||
siteName.value = settings.site_name || 'Sub2API';
|
||||
siteLogo.value = settings.site_logo || '';
|
||||
siteSubtitle.value = settings.site_subtitle || 'AI API Gateway Platform';
|
||||
docUrl.value = settings.doc_url || '';
|
||||
} catch (error) {
|
||||
console.error('Failed to load public settings:', error);
|
||||
}
|
||||
|
||||
@@ -287,6 +287,20 @@
|
||||
<p class="mt-1.5 text-xs text-gray-500 dark:text-gray-400">{{ t('admin.settings.site.contactInfoHint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Doc URL -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
{{ t('admin.settings.site.docUrl') }}
|
||||
</label>
|
||||
<input
|
||||
v-model="form.doc_url"
|
||||
type="url"
|
||||
class="input font-mono text-sm"
|
||||
placeholder="https://docs.example.com"
|
||||
/>
|
||||
<p class="mt-1.5 text-xs text-gray-500 dark:text-gray-400">{{ t('admin.settings.site.docUrlHint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Site Logo Upload -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
@@ -541,6 +555,7 @@ const form = reactive<SystemSettings>({
|
||||
site_subtitle: 'Subscription to API Conversion Platform',
|
||||
api_base_url: '',
|
||||
contact_info: '',
|
||||
doc_url: '',
|
||||
smtp_host: '',
|
||||
smtp_port: 587,
|
||||
smtp_username: '',
|
||||
|
||||
Reference in New Issue
Block a user