feat(desktop): embed BoosAPI Desktop client as a subproject
Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as a monorepo subdirectory under desktop/. Source only — node_modules, dist, Cargo target and the upstream .git history are excluded. desktop/ keeps its own independent Cargo workspace (desktop/src-tauri with crates/*); it is not part of the backend boosapi crate, so a `cargo check` at the metapi root still compiles only the backend. Build the desktop app from desktop/src-tauri per desktop/README.md. Note: app icons are still placeholder assets pending the final BoosAPI logo. The updater signing keys live outside the repo and are not included.
This commit is contained in:
@@ -0,0 +1,483 @@
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const rootPkg = JSON.parse(
|
||||
readFileSync(resolve(__dirname, '../../../package.json'), 'utf-8'),
|
||||
);
|
||||
const APP_VERSION = rootPkg.version as string;
|
||||
|
||||
const SITE_URL = 'https://app.aqbot.top';
|
||||
const OG_IMAGE = `${SITE_URL}/og-image.png`;
|
||||
|
||||
export default defineConfig({
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Open-source AI desktop client with built-in AI gateway, multi-model chat, MCP server support. Connect OpenAI, Claude, Gemini and more LLMs in one app.',
|
||||
|
||||
base: '/',
|
||||
|
||||
lastUpdated: true,
|
||||
cleanUrls: true,
|
||||
|
||||
sitemap: {
|
||||
hostname: SITE_URL,
|
||||
},
|
||||
|
||||
vite: {
|
||||
define: {
|
||||
__APP_VERSION__: JSON.stringify(APP_VERSION),
|
||||
},
|
||||
},
|
||||
|
||||
head: [
|
||||
['link', { rel: 'icon', href: '/favicon.ico' }],
|
||||
// Primary SEO meta
|
||||
['meta', { name: 'theme-color', content: '#309731' }],
|
||||
['meta', { name: 'author', content: 'AQBot Team' }],
|
||||
['meta', { name: 'keywords', content: 'AQBot, AI desktop client, AI gateway, AI chat client, LLM client, multi-model AI, MCP server, OpenAI client, Claude client, Gemini client, AI assistant, desktop AI app, open source AI, ChatGPT alternative, AI aggregator, large language model, AI desktop application, Tauri AI app' }],
|
||||
['meta', { name: 'robots', content: 'index, follow' }],
|
||||
// Open Graph
|
||||
['meta', { property: 'og:type', content: 'website' }],
|
||||
['meta', { property: 'og:site_name', content: 'AQBot' }],
|
||||
['meta', { property: 'og:title', content: 'AQBot — Open-source AI Desktop Client & Gateway' }],
|
||||
['meta', { property: 'og:description', content: 'Free, open-source AI desktop client with built-in gateway. Connect multiple LLMs (OpenAI, Claude, Gemini, DeepSeek) in one app. MCP server support, knowledge base, and more.' }],
|
||||
['meta', { property: 'og:image', content: OG_IMAGE }],
|
||||
['meta', { property: 'og:url', content: SITE_URL }],
|
||||
['meta', { property: 'og:locale', content: 'en' }],
|
||||
['meta', { property: 'og:locale:alternate', content: 'zh_CN' }],
|
||||
// Twitter Card
|
||||
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
|
||||
['meta', { name: 'twitter:title', content: 'AQBot — Open-source AI Desktop Client & Gateway' }],
|
||||
['meta', { name: 'twitter:description', content: 'Free, open-source AI desktop client with built-in gateway. Multi-model chat, MCP server support, knowledge base.' }],
|
||||
['meta', { name: 'twitter:image', content: OG_IMAGE }],
|
||||
],
|
||||
|
||||
locales: {
|
||||
root: {
|
||||
label: '🇺🇸 English',
|
||||
lang: 'en',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Open-source AI desktop client with built-in AI gateway, multi-model chat, MCP server support.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Features', link: '/features' },
|
||||
{ text: 'Download', link: '/download' },
|
||||
{ text: 'Docs', link: '/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/guide/': [{ text: 'Getting Started', items: [
|
||||
{ text: 'Quick Start', link: '/guide/getting-started' },
|
||||
{ text: 'Configure Providers', link: '/guide/providers' },
|
||||
{ text: 'MCP Servers', link: '/guide/mcp' },
|
||||
{ text: 'API Gateway', link: '/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
},
|
||||
},
|
||||
zh: {
|
||||
label: '🇨🇳 简体中文',
|
||||
lang: 'zh-CN',
|
||||
link: '/zh/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — 开源 AI 桌面客户端,内置 AI 网关,支持多模型对话、MCP 服务器、知识库。',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: '首页', link: '/zh/' },
|
||||
{ text: '功能', link: '/zh/features' },
|
||||
{ text: '下载', link: '/zh/download' },
|
||||
{ text: '文档', link: '/zh/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/zh/guide/': [{ text: '入门', items: [
|
||||
{ text: '快速开始', link: '/zh/guide/getting-started' },
|
||||
{ text: '配置服务商', link: '/zh/guide/providers' },
|
||||
{ text: 'MCP 服务器', link: '/zh/guide/mcp' },
|
||||
{ text: 'API 网关', link: '/zh/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: '上一页', next: '下一页' },
|
||||
darkModeSwitchLabel: '外观',
|
||||
returnToTopLabel: '返回顶部',
|
||||
sidebarMenuLabel: '菜单',
|
||||
outline: { label: '页面导航' },
|
||||
},
|
||||
},
|
||||
'zh-tw': {
|
||||
label: '🇭🇰 繁體中文',
|
||||
lang: 'zh-TW',
|
||||
link: '/zh-tw/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — 開源 AI 桌面客戶端,內建 AI 網關,支援多模型對話、MCP 伺服器、知識庫。',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: '首頁', link: '/zh-tw/' },
|
||||
{ text: '功能', link: '/zh-tw/features' },
|
||||
{ text: '下載', link: '/zh-tw/download' },
|
||||
{ text: '文件', link: '/zh-tw/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/zh-tw/guide/': [{ text: '入門', items: [
|
||||
{ text: '快速開始', link: '/zh-tw/guide/getting-started' },
|
||||
{ text: '設定服務供應商', link: '/zh-tw/guide/providers' },
|
||||
{ text: 'MCP 伺服器', link: '/zh-tw/guide/mcp' },
|
||||
{ text: 'API 閘道', link: '/zh-tw/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: '上一頁', next: '下一頁' },
|
||||
darkModeSwitchLabel: '外觀',
|
||||
returnToTopLabel: '返回頂部',
|
||||
sidebarMenuLabel: '選單',
|
||||
outline: { label: '頁面導覽' },
|
||||
},
|
||||
},
|
||||
ja: {
|
||||
label: '🇯🇵 日本語',
|
||||
lang: 'ja',
|
||||
link: '/ja/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — オープンソースのAIデスクトップクライアント。AIゲートウェイ内蔵、マルチモデルチャット、MCPサーバー対応。',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'ホーム', link: '/ja/' },
|
||||
{ text: '機能', link: '/ja/features' },
|
||||
{ text: 'ダウンロード', link: '/ja/download' },
|
||||
{ text: 'ドキュメント', link: '/ja/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/ja/guide/': [{ text: 'はじめに', items: [
|
||||
{ text: 'クイックスタート', link: '/ja/guide/getting-started' },
|
||||
{ text: 'プロバイダーの設定', link: '/ja/guide/providers' },
|
||||
{ text: 'MCPサーバー', link: '/ja/guide/mcp' },
|
||||
{ text: 'APIゲートウェイ', link: '/ja/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: '前のページ', next: '次のページ' },
|
||||
darkModeSwitchLabel: '外観',
|
||||
returnToTopLabel: 'トップに戻る',
|
||||
sidebarMenuLabel: 'メニュー',
|
||||
outline: { label: 'ページナビゲーション' },
|
||||
},
|
||||
},
|
||||
ko: {
|
||||
label: '🇰🇷 한국어',
|
||||
lang: 'ko',
|
||||
link: '/ko/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — 오픈소스 AI 데스크톱 클라이언트. AI 게이트웨이 내장, 멀티 모델 채팅, MCP 서버 지원.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: '홈', link: '/ko/' },
|
||||
{ text: '기능', link: '/ko/features' },
|
||||
{ text: '다운로드', link: '/ko/download' },
|
||||
{ text: '문서', link: '/ko/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/ko/guide/': [{ text: '시작하기', items: [
|
||||
{ text: '빠른 시작', link: '/ko/guide/getting-started' },
|
||||
{ text: '제공업체 설정', link: '/ko/guide/providers' },
|
||||
{ text: 'MCP 서버', link: '/ko/guide/mcp' },
|
||||
{ text: 'API 게이트웨이', link: '/ko/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: '이전 페이지', next: '다음 페이지' },
|
||||
darkModeSwitchLabel: '외관',
|
||||
returnToTopLabel: '맨 위로',
|
||||
sidebarMenuLabel: '메뉴',
|
||||
outline: { label: '페이지 탐색' },
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
label: '🇫🇷 Français',
|
||||
lang: 'fr',
|
||||
link: '/fr/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Client de bureau IA open-source avec passerelle IA intégrée, chat multi-modèles, support serveur MCP.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Accueil', link: '/fr/' },
|
||||
{ text: 'Fonctionnalités', link: '/fr/features' },
|
||||
{ text: 'Télécharger', link: '/fr/download' },
|
||||
{ text: 'Documentation', link: '/fr/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/fr/guide/': [{ text: 'Démarrage', items: [
|
||||
{ text: 'Démarrage rapide', link: '/fr/guide/getting-started' },
|
||||
{ text: 'Configurer les fournisseurs', link: '/fr/guide/providers' },
|
||||
{ text: 'Serveurs MCP', link: '/fr/guide/mcp' },
|
||||
{ text: 'Passerelle API', link: '/fr/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'Page précédente', next: 'Page suivante' },
|
||||
darkModeSwitchLabel: 'Apparence',
|
||||
returnToTopLabel: 'Retour en haut',
|
||||
sidebarMenuLabel: 'Menu',
|
||||
outline: { label: 'Navigation de la page' },
|
||||
},
|
||||
},
|
||||
de: {
|
||||
label: '🇩🇪 Deutsch',
|
||||
lang: 'de',
|
||||
link: '/de/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Open-Source KI-Desktop-Client mit integriertem KI-Gateway, Multi-Modell-Chat, MCP-Server-Unterstützung.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Startseite', link: '/de/' },
|
||||
{ text: 'Funktionen', link: '/de/features' },
|
||||
{ text: 'Download', link: '/de/download' },
|
||||
{ text: 'Dokumentation', link: '/de/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/de/guide/': [{ text: 'Erste Schritte', items: [
|
||||
{ text: 'Schnellstart', link: '/de/guide/getting-started' },
|
||||
{ text: 'Anbieter konfigurieren', link: '/de/guide/providers' },
|
||||
{ text: 'MCP-Server', link: '/de/guide/mcp' },
|
||||
{ text: 'API-Gateway', link: '/de/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'Vorherige Seite', next: 'Nächste Seite' },
|
||||
darkModeSwitchLabel: 'Erscheinungsbild',
|
||||
returnToTopLabel: 'Nach oben',
|
||||
sidebarMenuLabel: 'Menü',
|
||||
outline: { label: 'Seitennavigation' },
|
||||
},
|
||||
},
|
||||
es: {
|
||||
label: '🇪🇸 Español',
|
||||
lang: 'es',
|
||||
link: '/es/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Cliente de escritorio IA de código abierto con pasarela IA integrada, chat multi-modelo, soporte de servidor MCP.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Inicio', link: '/es/' },
|
||||
{ text: 'Características', link: '/es/features' },
|
||||
{ text: 'Descargar', link: '/es/download' },
|
||||
{ text: 'Documentación', link: '/es/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/es/guide/': [{ text: 'Comenzar', items: [
|
||||
{ text: 'Inicio rápido', link: '/es/guide/getting-started' },
|
||||
{ text: 'Configurar proveedores', link: '/es/guide/providers' },
|
||||
{ text: 'Servidores MCP', link: '/es/guide/mcp' },
|
||||
{ text: 'Pasarela API', link: '/es/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'Página anterior', next: 'Página siguiente' },
|
||||
darkModeSwitchLabel: 'Apariencia',
|
||||
returnToTopLabel: 'Volver arriba',
|
||||
sidebarMenuLabel: 'Menú',
|
||||
outline: { label: 'Navegación de página' },
|
||||
},
|
||||
},
|
||||
ru: {
|
||||
label: '🇷🇺 Русский',
|
||||
lang: 'ru',
|
||||
link: '/ru/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — Настольный ИИ-клиент с открытым исходным кодом. Встроенный шлюз ИИ, чат с несколькими моделями, поддержка MCP-серверов.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Главная', link: '/ru/' },
|
||||
{ text: 'Функции', link: '/ru/features' },
|
||||
{ text: 'Скачать', link: '/ru/download' },
|
||||
{ text: 'Документация', link: '/ru/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/ru/guide/': [{ text: 'Начало работы', items: [
|
||||
{ text: 'Быстрый старт', link: '/ru/guide/getting-started' },
|
||||
{ text: 'Настройка провайдеров', link: '/ru/guide/providers' },
|
||||
{ text: 'MCP-серверы', link: '/ru/guide/mcp' },
|
||||
{ text: 'API-шлюз', link: '/ru/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'Предыдущая страница', next: 'Следующая страница' },
|
||||
darkModeSwitchLabel: 'Внешний вид',
|
||||
returnToTopLabel: 'Наверх',
|
||||
sidebarMenuLabel: 'Меню',
|
||||
outline: { label: 'Навигация по странице' },
|
||||
},
|
||||
},
|
||||
hi: {
|
||||
label: '🇮🇳 हिन्दी',
|
||||
lang: 'hi',
|
||||
link: '/hi/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — ओपन-सोर्स AI डेस्कटॉप क्लाइंट। बिल्ट-इन AI गेटवे, मल्टी-मॉडल चैट, MCP सर्वर समर्थन।',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'होम', link: '/hi/' },
|
||||
{ text: 'विशेषताएं', link: '/hi/features' },
|
||||
{ text: 'डाउनलोड', link: '/hi/download' },
|
||||
{ text: 'दस्तावेज़', link: '/hi/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/hi/guide/': [{ text: 'शुरुआत', items: [
|
||||
{ text: 'त्वरित प्रारंभ', link: '/hi/guide/getting-started' },
|
||||
{ text: 'प्रदाता कॉन्फ़िगर करें', link: '/hi/guide/providers' },
|
||||
{ text: 'MCP सर्वर', link: '/hi/guide/mcp' },
|
||||
{ text: 'API गेटवे', link: '/hi/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'पिछला पृष्ठ', next: 'अगला पृष्ठ' },
|
||||
darkModeSwitchLabel: 'स्वरूप',
|
||||
returnToTopLabel: 'शीर्ष पर वापस',
|
||||
sidebarMenuLabel: 'मेनू',
|
||||
outline: { label: 'पृष्ठ नेविगेशन' },
|
||||
},
|
||||
},
|
||||
ar: {
|
||||
label: '🇸🇦 العربية',
|
||||
lang: 'ar',
|
||||
link: '/ar/',
|
||||
title: 'AQBot',
|
||||
description: 'AQBot — عميل سطح مكتب AI مفتوح المصدر مع بوابة AI مدمجة، دردشة متعددة النماذج، دعم خوادم MCP.',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'الرئيسية', link: '/ar/' },
|
||||
{ text: 'الميزات', link: '/ar/features' },
|
||||
{ text: 'تنزيل', link: '/ar/download' },
|
||||
{ text: 'التوثيق', link: '/ar/guide/getting-started' },
|
||||
],
|
||||
sidebar: {
|
||||
'/ar/guide/': [{ text: 'البدء', items: [
|
||||
{ text: 'البدء السريع', link: '/ar/guide/getting-started' },
|
||||
{ text: 'إعداد المزودين', link: '/ar/guide/providers' },
|
||||
{ text: 'خوادم MCP', link: '/ar/guide/mcp' },
|
||||
{ text: 'بوابة API', link: '/ar/guide/gateway' },
|
||||
]}],
|
||||
},
|
||||
docFooter: { prev: 'الصفحة السابقة', next: 'الصفحة التالية' },
|
||||
darkModeSwitchLabel: 'المظهر',
|
||||
returnToTopLabel: 'العودة للأعلى',
|
||||
sidebarMenuLabel: 'القائمة',
|
||||
outline: { label: 'تنقل الصفحة' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
themeConfig: {
|
||||
logo: '/logo.png',
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/AQBot-Desktop/AQBot' },
|
||||
],
|
||||
search: {
|
||||
provider: 'local',
|
||||
options: {
|
||||
locales: {
|
||||
zh: {
|
||||
translations: {
|
||||
button: { buttonText: '搜索', buttonAriaLabel: '搜索' },
|
||||
modal: {
|
||||
displayDetails: '显示详细列表',
|
||||
resetButtonTitle: '重置搜索',
|
||||
noResultsText: '没有结果',
|
||||
footer: { selectText: '选择', navigateText: '导航', closeText: '关闭' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'zh-tw': {
|
||||
translations: {
|
||||
button: { buttonText: '搜尋', buttonAriaLabel: '搜尋' },
|
||||
modal: {
|
||||
displayDetails: '顯示詳細列表',
|
||||
resetButtonTitle: '重置搜尋',
|
||||
noResultsText: '無結果',
|
||||
footer: { selectText: '選擇', navigateText: '導覽', closeText: '關閉' },
|
||||
},
|
||||
},
|
||||
},
|
||||
ja: {
|
||||
translations: {
|
||||
button: { buttonText: '検索', buttonAriaLabel: '検索' },
|
||||
modal: {
|
||||
displayDetails: '詳細一覧を表示',
|
||||
resetButtonTitle: '検索をリセット',
|
||||
noResultsText: '結果なし',
|
||||
footer: { selectText: '選択', navigateText: 'ナビゲート', closeText: '閉じる' },
|
||||
},
|
||||
},
|
||||
},
|
||||
ko: {
|
||||
translations: {
|
||||
button: { buttonText: '검색', buttonAriaLabel: '검색' },
|
||||
modal: {
|
||||
displayDetails: '상세 목록 표시',
|
||||
resetButtonTitle: '검색 초기화',
|
||||
noResultsText: '결과 없음',
|
||||
footer: { selectText: '선택', navigateText: '탐색', closeText: '닫기' },
|
||||
},
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
translations: {
|
||||
button: { buttonText: 'Rechercher', buttonAriaLabel: 'Rechercher' },
|
||||
modal: {
|
||||
displayDetails: 'Afficher la liste détaillée',
|
||||
resetButtonTitle: 'Réinitialiser la recherche',
|
||||
noResultsText: 'Aucun résultat',
|
||||
footer: { selectText: 'Sélectionner', navigateText: 'Naviguer', closeText: 'Fermer' },
|
||||
},
|
||||
},
|
||||
},
|
||||
de: {
|
||||
translations: {
|
||||
button: { buttonText: 'Suchen', buttonAriaLabel: 'Suchen' },
|
||||
modal: {
|
||||
displayDetails: 'Detaillierte Liste anzeigen',
|
||||
resetButtonTitle: 'Suche zurücksetzen',
|
||||
noResultsText: 'Keine Ergebnisse',
|
||||
footer: { selectText: 'Auswählen', navigateText: 'Navigieren', closeText: 'Schließen' },
|
||||
},
|
||||
},
|
||||
},
|
||||
es: {
|
||||
translations: {
|
||||
button: { buttonText: 'Buscar', buttonAriaLabel: 'Buscar' },
|
||||
modal: {
|
||||
displayDetails: 'Mostrar lista detallada',
|
||||
resetButtonTitle: 'Restablecer búsqueda',
|
||||
noResultsText: 'Sin resultados',
|
||||
footer: { selectText: 'Seleccionar', navigateText: 'Navegar', closeText: 'Cerrar' },
|
||||
},
|
||||
},
|
||||
},
|
||||
ru: {
|
||||
translations: {
|
||||
button: { buttonText: 'Поиск', buttonAriaLabel: 'Поиск' },
|
||||
modal: {
|
||||
displayDetails: 'Показать подробный список',
|
||||
resetButtonTitle: 'Сбросить поиск',
|
||||
noResultsText: 'Нет результатов',
|
||||
footer: { selectText: 'Выбрать', navigateText: 'Навигация', closeText: 'Закрыть' },
|
||||
},
|
||||
},
|
||||
},
|
||||
hi: {
|
||||
translations: {
|
||||
button: { buttonText: 'खोजें', buttonAriaLabel: 'खोजें' },
|
||||
modal: {
|
||||
displayDetails: 'विस्तृत सूची दिखाएं',
|
||||
resetButtonTitle: 'खोज रीसेट करें',
|
||||
noResultsText: 'कोई परिणाम नहीं',
|
||||
footer: { selectText: 'चुनें', navigateText: 'नेविगेट', closeText: 'बंद करें' },
|
||||
},
|
||||
},
|
||||
},
|
||||
ar: {
|
||||
translations: {
|
||||
button: { buttonText: 'بحث', buttonAriaLabel: 'بحث' },
|
||||
modal: {
|
||||
displayDetails: 'عرض القائمة التفصيلية',
|
||||
resetButtonTitle: 'إعادة تعيين البحث',
|
||||
noResultsText: 'لا توجد نتائج',
|
||||
footer: { selectText: 'اختر', navigateText: 'تنقل', closeText: 'إغلاق' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,134 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useData } from 'vitepress';
|
||||
import {
|
||||
AppleOutlined,
|
||||
WindowsOutlined,
|
||||
ReadOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
declare const __APP_VERSION__: string;
|
||||
const VERSION = __APP_VERSION__;
|
||||
|
||||
const { lang } = useData();
|
||||
const isZh = computed(() => lang.value === 'zh-CN');
|
||||
|
||||
const detectedOS = ref<'macos' | 'windows' | 'linux'>('macos');
|
||||
|
||||
onMounted(() => {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
if (ua.includes('win')) {
|
||||
detectedOS.value = 'windows';
|
||||
} else if (ua.includes('linux')) {
|
||||
detectedOS.value = 'linux';
|
||||
} else {
|
||||
detectedOS.value = 'macos';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="download-bar">
|
||||
<a href="/download" class="dl-btn dl-primary">
|
||||
<AppleOutlined v-if="detectedOS === 'macos'" class="os-icon" />
|
||||
<WindowsOutlined v-else-if="detectedOS === 'windows'" class="os-icon" />
|
||||
<svg v-else class="os-icon" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 448 512" fill="currentColor"><path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6.2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5.1-1.3.6-3.4 1.5-3.2 2.9.1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7.1 234.8 0 132.4-.2 158 85.4 157.7 130.9c.3 30.4-16.3 51-33.4 72-15.2 18-35.1 44.3-46.5 74.4-9.3 24.6-12.9 51.8-3.7 79.1-1.4.5-2.8 1.2-4.1 2-1.4.8-2.7 1.8-4 2.9-6.6 5.6-8.7 14.3-10.5 22.4-1.9 8.1-3.6 15.7-7.2 19.7-6.3 6.7-7.1 16.5-3.5 22.9 3.6 6.4 11.5 9.5 18.5 6.9 3.6-1.3 6.5-4 9.1-6.5 2.5-2.5 4.9-5 7.9-6.5 5.4-2.8 12.4-2.3 19-1.2 6.8 1.2 13.2 3.1 18.8 1.9 12.2-2.6 16.5-11.1 23.7-16.9.5-.4.4-1.2-.1-1.6-.4-.3-1-.3-1.4.1-3.6 4-10.1 12.6-19.4 14.5-5.1 1-11.1-1-17.5-2.1-6.4-1.2-13.5-1.6-19.4 1.4-3.5 1.8-6.1 4.6-8.7 7.1-2.6 2.6-5.1 4.9-8.2 6-4.3 1.6-9.4-.3-11.7-4.4-2.3-4.1-1.7-10.6 2.6-15.1 4.5-4.9 6.3-13.5 8.2-21.5 1.9-8.1 3.9-16.3 9.6-21.1 2.4-2 5.3-3.2 8.3-3.5 2 12.3 9.2 23.4 19.5 31.1 1.4 1 1 3.6-.5 4.1-5.1 1.6-7.4 6.5-4.8 10.4 2.5 3.7 7.9 4.7 11.6 2.2 3.8-2.5 5.1-7.8 2.6-11.6-.5-.8-1.2-1.4-1.9-1.9 1.4-.5 2.4-1.8 2.1-3.2-.3-1.3-1.7-2.2-3-2.2h-.7c3.4-3.7 6.2-8.1 7.9-13 4.3.3 8.4 2 11.3 5.1 4.4 4.8 5.3 11.7 7.1 18 1.8 6.2 4.5 12.4 10.2 15.7 2.5 1.4 5.6 2 8.5 1 2.5-.9 4.3-3.1 5-5.7.4-1.5.2-3.1-.4-4.5-1.4-3.2-4.6-5-7.6-6.6-3-1.5-6.2-3-8-5.8-1.6-2.5-2-5.6-1.2-8.5.6-2.2 2.1-4.2 4.2-5 3.2-1.2 6.7.3 8.5 3.1 1 1.5 1.4 3.4 1.2 5.2.2.5.4 1 .5 1.5.3 1 .5 2.1.5 3.2 0 3.5-1.3 6.8-3.5 9.3 2.4 1.7 5.2 2.7 8.2 2.7 4.4 0 8.5-2.1 11.1-5.5 2.8-3.7 3.5-8.6 1.8-12.9z"/></svg>
|
||||
<span>{{ isZh ? '下载' : 'Download' }} v{{ VERSION }}</span>
|
||||
</a>
|
||||
<a href="/features" class="dl-btn dl-docs">
|
||||
<ReadOutlined class="os-icon" />
|
||||
<span>{{ isZh ? '文档' : 'Docs' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.download-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
padding: 32px 0 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.dl-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding: 0 36px;
|
||||
height: 56px;
|
||||
border-radius: 28px;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dl-primary {
|
||||
background: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-1);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.dl-primary:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.dark .dl-primary {
|
||||
background: var(--vp-c-bg-soft);
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.dl-docs {
|
||||
color: var(--vp-c-text-1);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: transparent;
|
||||
}
|
||||
.dl-docs:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.os-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.dl-btn {
|
||||
padding: 0 28px;
|
||||
height: 50px;
|
||||
font-size: 15px;
|
||||
border-radius: 25px;
|
||||
gap: 8px;
|
||||
}
|
||||
.download-bar {
|
||||
gap: 14px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.dl-btn {
|
||||
padding: 0 24px;
|
||||
height: 48px;
|
||||
font-size: 15px;
|
||||
border-radius: 24px;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
.download-bar {
|
||||
gap: 12px;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 24px 16px 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,452 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useData } from 'vitepress';
|
||||
import {
|
||||
AppleOutlined,
|
||||
WindowsOutlined,
|
||||
ClockCircleOutlined,
|
||||
LinkOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
declare const __APP_VERSION__: string;
|
||||
|
||||
const VERSION = __APP_VERSION__;
|
||||
const BASE = `https://github.com/AQBot-Desktop/AQBot/releases/download/v${VERSION}`;
|
||||
|
||||
type OS = 'macos' | 'windows' | 'linux';
|
||||
|
||||
interface DownloadItem {
|
||||
labelZh: string;
|
||||
labelEn: string;
|
||||
file: string;
|
||||
arch: string;
|
||||
os: OS;
|
||||
primary?: boolean;
|
||||
}
|
||||
|
||||
const downloads: DownloadItem[] = [
|
||||
{ os: 'macos', arch: 'Apple Silicon', labelEn: 'Apple Silicon (M1/M2/M3/M4)', labelZh: 'Apple Silicon(M 系列芯片)', file: `AQBot_${VERSION}_aarch64.dmg`, primary: true },
|
||||
{ os: 'macos', arch: 'Intel', labelEn: 'Intel', labelZh: 'Intel(英特尔芯片)', file: `AQBot_${VERSION}_x64.dmg`, primary: true },
|
||||
{ os: 'windows', arch: 'x64', labelEn: 'Windows x64', labelZh: 'Windows x64', file: `AQBot_${VERSION}_x64-setup.exe`, primary: true },
|
||||
{ os: 'windows', arch: 'x64 Portable', labelEn: 'Windows x64 Portable', labelZh: 'Windows x64 绿色版', file: `AQBot_v${VERSION}_windows-x64-portable.zip` },
|
||||
{ os: 'windows', arch: 'ARM64', labelEn: 'Windows ARM64', labelZh: 'Windows ARM64', file: `AQBot_${VERSION}_arm64-setup.exe` },
|
||||
{ os: 'windows', arch: 'ARM64 Portable', labelEn: 'Windows ARM64 Portable', labelZh: 'Windows ARM64 绿色版', file: `AQBot_v${VERSION}_windows-arm64-portable.zip` },
|
||||
{ os: 'linux', arch: 'x64 deb', labelEn: 'x64 .deb (Debian/Ubuntu)', labelZh: 'x64 .deb(Debian/Ubuntu)', file: `AQBot_${VERSION}_amd64.deb`, primary: true },
|
||||
{ os: 'linux', arch: 'x64 AppImage', labelEn: 'x64 AppImage', labelZh: 'x64 AppImage', file: `AQBot_${VERSION}_amd64.AppImage` },
|
||||
{ os: 'linux', arch: 'ARM64 deb', labelEn: 'ARM64 .deb', labelZh: 'ARM64 .deb', file: `AQBot_${VERSION}_arm64.deb` },
|
||||
{ os: 'linux', arch: 'x64 rpm', labelEn: 'x64 .rpm (Fedora/RHEL)', labelZh: 'x64 .rpm(Fedora/RHEL)', file: `AQBot-${VERSION}-1.x86_64.rpm` },
|
||||
{ os: 'linux', arch: 'ARM64 rpm', labelEn: 'ARM64 .rpm', labelZh: 'ARM64 .rpm', file: `AQBot-${VERSION}-1.aarch64.rpm` },
|
||||
];
|
||||
|
||||
const osTabs: { id: OS; label: string }[] = [
|
||||
{ id: 'macos', label: 'macOS' },
|
||||
{ id: 'windows', label: 'Windows' },
|
||||
{ id: 'linux', label: 'Linux' },
|
||||
];
|
||||
|
||||
const { lang } = useData();
|
||||
const isZh = computed(() => lang.value === 'zh-CN');
|
||||
|
||||
const activeOS = ref<OS>('macos');
|
||||
|
||||
onMounted(() => {
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
if (ua.includes('win')) {
|
||||
activeOS.value = 'windows';
|
||||
} else if (ua.includes('linux')) {
|
||||
activeOS.value = 'linux';
|
||||
} else {
|
||||
activeOS.value = 'macos';
|
||||
}
|
||||
});
|
||||
|
||||
const currentDownloads = computed(() =>
|
||||
downloads.filter(d => d.os === activeOS.value)
|
||||
);
|
||||
|
||||
function itemLabel(item: DownloadItem) {
|
||||
return isZh.value ? item.labelZh : item.labelEn;
|
||||
}
|
||||
|
||||
function downloadUrl(item: DownloadItem) {
|
||||
return `${BASE}/${item.file}`;
|
||||
}
|
||||
|
||||
interface InstallStep {
|
||||
titleZh: string;
|
||||
titleEn: string;
|
||||
stepsZh: string[];
|
||||
stepsEn: string[];
|
||||
}
|
||||
|
||||
const installInstructions = computed<InstallStep[]>(() => {
|
||||
const os = activeOS.value;
|
||||
if (os === 'macos') {
|
||||
return [{
|
||||
titleZh: '安装步骤',
|
||||
titleEn: 'Installation',
|
||||
stepsZh: [
|
||||
'打开下载的 .dmg 文件',
|
||||
'将 AQBot 拖入「应用程序」文件夹',
|
||||
'首次运行时,在「系统设置 → 隐私与安全性」中允许运行',
|
||||
],
|
||||
stepsEn: [
|
||||
'Open the downloaded .dmg file',
|
||||
'Drag AQBot to the Applications folder',
|
||||
'On first launch, allow it in System Settings → Privacy & Security',
|
||||
],
|
||||
}];
|
||||
}
|
||||
if (os === 'windows') {
|
||||
return [
|
||||
{
|
||||
titleZh: '安装版',
|
||||
titleEn: 'Installer',
|
||||
stepsZh: [
|
||||
'运行下载的安装程序',
|
||||
'按向导完成安装',
|
||||
'从开始菜单或桌面快捷方式启动',
|
||||
],
|
||||
stepsEn: [
|
||||
'Run the downloaded installer',
|
||||
'Follow the wizard to complete installation',
|
||||
'Launch from Start Menu or desktop shortcut',
|
||||
],
|
||||
},
|
||||
{
|
||||
titleZh: '绿色免安装版 (Portable)',
|
||||
titleEn: 'Portable',
|
||||
stepsZh: [
|
||||
'解压 .zip 文件到任意目录',
|
||||
'双击 AQBot.exe 即可运行',
|
||||
],
|
||||
stepsEn: [
|
||||
'Extract the .zip file to any directory',
|
||||
'Double-click AQBot.exe to run',
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
return [{
|
||||
titleZh: '安装步骤',
|
||||
titleEn: 'Installation',
|
||||
stepsZh: [
|
||||
'Debian/Ubuntu: sudo dpkg -i AQBot_x.x.x_amd64.deb',
|
||||
'AppImage: chmod +x AQBot_x.x.x_amd64.AppImage && ./AQBot_x.x.x_amd64.AppImage',
|
||||
'RPM: sudo rpm -i AQBot-x.x.x-1.x86_64.rpm',
|
||||
],
|
||||
stepsEn: [
|
||||
'Debian/Ubuntu: sudo dpkg -i AQBot_x.x.x_amd64.deb',
|
||||
'AppImage: chmod +x AQBot_x.x.x_amd64.AppImage && ./AQBot_x.x.x_amd64.AppImage',
|
||||
'RPM: sudo rpm -i AQBot-x.x.x-1.x86_64.rpm',
|
||||
],
|
||||
}];
|
||||
});
|
||||
|
||||
const sysReq = computed(() => {
|
||||
const os = activeOS.value;
|
||||
if (os === 'macos') return isZh.value ? 'macOS 11.0 (Big Sur) 及以上' : 'macOS 11.0 (Big Sur) or later';
|
||||
if (os === 'windows') return isZh.value ? 'Windows 10 (1803) 及以上' : 'Windows 10 (1803) or later';
|
||||
return isZh.value ? '各主流 Linux 发行版' : 'Major Linux distributions';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="download-page">
|
||||
<!-- Version badge -->
|
||||
<div class="version-header">
|
||||
<a class="version-badge" href="https://github.com/AQBot-Desktop/AQBot/releases" target="_blank" rel="noopener">
|
||||
<ClockCircleOutlined />
|
||||
{{ isZh ? '最新发行版本' : 'Latest Release' }}:v{{ VERSION }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- OS Tabs -->
|
||||
<div class="os-tabs">
|
||||
<button
|
||||
v-for="tab in osTabs"
|
||||
:key="tab.id"
|
||||
:class="['os-tab', { active: activeOS === tab.id }]"
|
||||
@click="activeOS = tab.id"
|
||||
>
|
||||
<AppleOutlined v-if="tab.id === 'macos'" class="tab-icon" />
|
||||
<WindowsOutlined v-else-if="tab.id === 'windows'" class="tab-icon" />
|
||||
<svg v-else class="tab-icon" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 448 512" fill="currentColor"><path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6.2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5.1-1.3.6-3.4 1.5-3.2 2.9.1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7.1 234.8 0 132.4-.2 158 85.4 157.7 130.9c.3 30.4-16.3 51-33.4 72-15.2 18-35.1 44.3-46.5 74.4-9.3 24.6-12.9 51.8-3.7 79.1-1.4.5-2.8 1.2-4.1 2-1.4.8-2.7 1.8-4 2.9-6.6 5.6-8.7 14.3-10.5 22.4-1.9 8.1-3.6 15.7-7.2 19.7-6.3 6.7-7.1 16.5-3.5 22.9 3.6 6.4 11.5 9.5 18.5 6.9 3.6-1.3 6.5-4 9.1-6.5 2.5-2.5 4.9-5 7.9-6.5 5.4-2.8 12.4-2.3 19-1.2 6.8 1.2 13.2 3.1 18.8 1.9 12.2-2.6 16.5-11.1 23.7-16.9.5-.4.4-1.2-.1-1.6-.4-.3-1-.3-1.4.1-3.6 4-10.1 12.6-19.4 14.5-5.1 1-11.1-1-17.5-2.1-6.4-1.2-13.5-1.6-19.4 1.4-3.5 1.8-6.1 4.6-8.7 7.1-2.6 2.6-5.1 4.9-8.2 6-4.3 1.6-9.4-.3-11.7-4.4-2.3-4.1-1.7-10.6 2.6-15.1 4.5-4.9 6.3-13.5 8.2-21.5 1.9-8.1 3.9-16.3 9.6-21.1 2.4-2 5.3-3.2 8.3-3.5 2 12.3 9.2 23.4 19.5 31.1 1.4 1 1 3.6-.5 4.1-5.1 1.6-7.4 6.5-4.8 10.4 2.5 3.7 7.9 4.7 11.6 2.2 3.8-2.5 5.1-7.8 2.6-11.6-.5-.8-1.2-1.4-1.9-1.9 1.4-.5 2.4-1.8 2.1-3.2-.3-1.3-1.7-2.2-3-2.2h-.7c3.4-3.7 6.2-8.1 7.9-13 4.3.3 8.4 2 11.3 5.1 4.4 4.8 5.3 11.7 7.1 18 1.8 6.2 4.5 12.4 10.2 15.7 2.5 1.4 5.6 2 8.5 1 2.5-.9 4.3-3.1 5-5.7.4-1.5.2-3.1-.4-4.5-1.4-3.2-4.6-5-7.6-6.6-3-1.5-6.2-3-8-5.8-1.6-2.5-2-5.6-1.2-8.5.6-2.2 2.1-4.2 4.2-5 3.2-1.2 6.7.3 8.5 3.1 1 1.5 1.4 3.4 1.2 5.2.2.5.4 1 .5 1.5.3 1 .5 2.1.5 3.2 0 3.5-1.3 6.8-3.5 9.3 2.4 1.7 5.2 2.7 8.2 2.7 4.4 0 8.5-2.1 11.1-5.5 2.8-3.7 3.5-8.6 1.8-12.9z"/></svg>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Download buttons -->
|
||||
<div class="download-section">
|
||||
<div class="download-grid">
|
||||
<a
|
||||
v-for="item in currentDownloads"
|
||||
:key="item.file"
|
||||
:href="downloadUrl(item)"
|
||||
:class="['dl-btn', item.primary ? 'dl-primary' : 'dl-secondary']"
|
||||
>
|
||||
<AppleOutlined v-if="activeOS === 'macos'" class="btn-icon" />
|
||||
<WindowsOutlined v-else-if="activeOS === 'windows'" class="btn-icon" />
|
||||
<svg v-else class="btn-icon" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 448 512" fill="currentColor"><path d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6.2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5.1-1.3.6-3.4 1.5-3.2 2.9.1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7.1 234.8 0 132.4-.2 158 85.4 157.7 130.9c.3 30.4-16.3 51-33.4 72-15.2 18-35.1 44.3-46.5 74.4-9.3 24.6-12.9 51.8-3.7 79.1-1.4.5-2.8 1.2-4.1 2-1.4.8-2.7 1.8-4 2.9-6.6 5.6-8.7 14.3-10.5 22.4-1.9 8.1-3.6 15.7-7.2 19.7-6.3 6.7-7.1 16.5-3.5 22.9 3.6 6.4 11.5 9.5 18.5 6.9 3.6-1.3 6.5-4 9.1-6.5 2.5-2.5 4.9-5 7.9-6.5 5.4-2.8 12.4-2.3 19-1.2 6.8 1.2 13.2 3.1 18.8 1.9 12.2-2.6 16.5-11.1 23.7-16.9.5-.4.4-1.2-.1-1.6-.4-.3-1-.3-1.4.1-3.6 4-10.1 12.6-19.4 14.5-5.1 1-11.1-1-17.5-2.1-6.4-1.2-13.5-1.6-19.4 1.4-3.5 1.8-6.1 4.6-8.7 7.1-2.6 2.6-5.1 4.9-8.2 6-4.3 1.6-9.4-.3-11.7-4.4-2.3-4.1-1.7-10.6 2.6-15.1 4.5-4.9 6.3-13.5 8.2-21.5 1.9-8.1 3.9-16.3 9.6-21.1 2.4-2 5.3-3.2 8.3-3.5 2 12.3 9.2 23.4 19.5 31.1 1.4 1 1 3.6-.5 4.1-5.1 1.6-7.4 6.5-4.8 10.4 2.5 3.7 7.9 4.7 11.6 2.2 3.8-2.5 5.1-7.8 2.6-11.6-.5-.8-1.2-1.4-1.9-1.9 1.4-.5 2.4-1.8 2.1-3.2-.3-1.3-1.7-2.2-3-2.2h-.7c3.4-3.7 6.2-8.1 7.9-13 4.3.3 8.4 2 11.3 5.1 4.4 4.8 5.3 11.7 7.1 18 1.8 6.2 4.5 12.4 10.2 15.7 2.5 1.4 5.6 2 8.5 1 2.5-.9 4.3-3.1 5-5.7.4-1.5.2-3.1-.4-4.5-1.4-3.2-4.6-5-7.6-6.6-3-1.5-6.2-3-8-5.8-1.6-2.5-2-5.6-1.2-8.5.6-2.2 2.1-4.2 4.2-5 3.2-1.2 6.7.3 8.5 3.1 1 1.5 1.4 3.4 1.2 5.2.2.5.4 1 .5 1.5.3 1 .5 2.1.5 3.2 0 3.5-1.3 6.8-3.5 9.3 2.4 1.7 5.2 2.7 8.2 2.7 4.4 0 8.5-2.1 11.1-5.5 2.8-3.7 3.5-8.6 1.8-12.9z"/></svg>
|
||||
<span>{{ itemLabel(item) }}</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- System requirement -->
|
||||
<div class="sys-req">
|
||||
<span class="sys-req-label">{{ isZh ? '系统要求' : 'System Requirements' }}:</span>
|
||||
{{ sysReq }}
|
||||
</div>
|
||||
|
||||
<!-- GitHub Releases link -->
|
||||
<a
|
||||
class="releases-link"
|
||||
href="https://github.com/AQBot-Desktop/AQBot/releases"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ isZh ? '前往 GitHub Releases 下载更多版本' : 'View all versions on GitHub Releases' }}
|
||||
<LinkOutlined />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Installation instructions -->
|
||||
<div class="install-section">
|
||||
<h3 class="section-title">{{ isZh ? '安装说明' : 'Installation' }}</h3>
|
||||
<div v-for="(inst, idx) in installInstructions" :key="idx" class="install-block">
|
||||
<h4 v-if="installInstructions.length > 1" class="install-subtitle">
|
||||
{{ isZh ? inst.titleZh : inst.titleEn }}
|
||||
</h4>
|
||||
<ol class="install-steps">
|
||||
<li v-for="(step, si) in (isZh ? inst.stepsZh : inst.stepsEn)" :key="si">
|
||||
{{ step }}
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.download-page {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 64px;
|
||||
}
|
||||
|
||||
/* Version header */
|
||||
.version-header {
|
||||
text-align: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.version-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-brand-1);
|
||||
background: var(--vp-c-brand-soft);
|
||||
padding: 6px 16px;
|
||||
border-radius: 20px;
|
||||
letter-spacing: 0.02em;
|
||||
text-decoration: none;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.version-badge:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* OS Tabs */
|
||||
.os-tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 32px;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.os-tab {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 24px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.os-tab:hover {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.os-tab.active {
|
||||
color: var(--vp-c-brand-1);
|
||||
border-bottom-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
flex-shrink: 0;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.os-tab.active .tab-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Download section */
|
||||
.download-section {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.download-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dl-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 24px;
|
||||
height: 52px;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.dl-btn:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
color: var(--vp-c-text-1);
|
||||
background: var(--vp-c-brand-soft);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.dl-primary {
|
||||
font-size: 16px;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.dl-secondary {
|
||||
font-size: 14px;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
flex-shrink: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* System requirements */
|
||||
.sys-req {
|
||||
margin-top: 16px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
font-size: 13px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.sys-req-label {
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
/* Releases link */
|
||||
.releases-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 16px;
|
||||
font-size: 14px;
|
||||
color: var(--vp-c-brand-1);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.releases-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Installation section */
|
||||
.install-section {
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.install-block {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.install-subtitle {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.install-steps {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
color: var(--vp-c-text-2);
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.install-steps li {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media (max-width: 640px) {
|
||||
.download-page {
|
||||
padding: 32px 16px 48px;
|
||||
}
|
||||
|
||||
.os-tabs {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.os-tab {
|
||||
padding: 10px 16px;
|
||||
font-size: 14px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.dl-btn {
|
||||
padding: 0 16px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.dl-primary {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,166 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useData } from 'vitepress';
|
||||
import {
|
||||
RobotOutlined,
|
||||
ThunderboltOutlined,
|
||||
ApiOutlined,
|
||||
CloudServerOutlined,
|
||||
BookOutlined,
|
||||
SearchOutlined,
|
||||
EditOutlined,
|
||||
DesktopOutlined,
|
||||
LockOutlined,
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
const iconMap: Record<string, any> = {
|
||||
robot: RobotOutlined,
|
||||
thunderbolt: ThunderboltOutlined,
|
||||
api: ApiOutlined,
|
||||
'cloud-server': CloudServerOutlined,
|
||||
book: BookOutlined,
|
||||
search: SearchOutlined,
|
||||
edit: EditOutlined,
|
||||
desktop: DesktopOutlined,
|
||||
lock: LockOutlined,
|
||||
};
|
||||
|
||||
const { frontmatter } = useData();
|
||||
const features = computed(() => frontmatter.value.features || []);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="features-grid" v-if="features.length">
|
||||
<div class="features-container">
|
||||
<div
|
||||
v-for="(feature, index) in features"
|
||||
:key="index"
|
||||
class="feature-card"
|
||||
>
|
||||
<div class="card-inner">
|
||||
<div class="icon-wrapper">
|
||||
<component
|
||||
:is="iconMap[feature.icon] || RobotOutlined"
|
||||
class="feature-icon"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="feature-title">{{ feature.title }}</h3>
|
||||
<p class="feature-details">{{ feature.details }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.features-grid {
|
||||
max-width: 1152px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 48px;
|
||||
}
|
||||
|
||||
.features-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
position: relative;
|
||||
border-radius: 12px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.feature-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 12px;
|
||||
padding: 1px;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
transparent 0%,
|
||||
transparent 100%
|
||||
);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
opacity: 0;
|
||||
transition: opacity 0.35s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
box-shadow:
|
||||
0 0 0 1px var(--vp-c-brand-1),
|
||||
0 4px 24px rgba(48, 151, 49, 0.15),
|
||||
0 0 48px rgba(48, 151, 49, 0.08);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.dark .feature-card:hover {
|
||||
box-shadow:
|
||||
0 0 0 1px var(--vp-c-brand-1),
|
||||
0 4px 24px rgba(63, 186, 64, 0.2),
|
||||
0 0 48px rgba(63, 186, 64, 0.1);
|
||||
}
|
||||
|
||||
.card-inner {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 10px;
|
||||
background: var(--vp-c-default-soft);
|
||||
margin-bottom: 16px;
|
||||
transition: all 0.35s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover .icon-wrapper {
|
||||
background: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 24px;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
margin: 0 0 8px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.feature-details {
|
||||
font-size: 14px;
|
||||
color: var(--vp-c-text-2);
|
||||
margin: 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.features-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.features-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.features-grid {
|
||||
padding: 0 16px 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
import { useData } from 'vitepress';
|
||||
import DownloadBar from './DownloadBar.vue';
|
||||
import ImageCarousel from './ImageCarousel.vue';
|
||||
import FeaturesGrid from './FeaturesGrid.vue';
|
||||
|
||||
const { Layout } = DefaultTheme;
|
||||
const { frontmatter } = useData();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<template #home-hero-info-after>
|
||||
<div v-if="frontmatter?.layout === 'home'" class="hero-actions-custom">
|
||||
<DownloadBar />
|
||||
</div>
|
||||
</template>
|
||||
<template #home-features-before>
|
||||
<div v-if="frontmatter?.layout === 'home'">
|
||||
<ImageCarousel />
|
||||
</div>
|
||||
</template>
|
||||
<template #home-features-after>
|
||||
<div v-if="frontmatter?.layout === 'home'">
|
||||
<FeaturesGrid />
|
||||
</div>
|
||||
</template>
|
||||
<template #layout-bottom>
|
||||
<footer class="site-footer">
|
||||
<p>© 2026 AQBot</p>
|
||||
</footer>
|
||||
</template>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.hero-actions-custom {
|
||||
width: 100%;
|
||||
}
|
||||
.site-footer {
|
||||
text-align: center;
|
||||
padding: 24px 0;
|
||||
color: var(--vp-c-text-3);
|
||||
font-size: 14px;
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
}
|
||||
.site-footer p {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,175 @@
|
||||
<script setup lang="ts">
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue';
|
||||
import { Autoplay, Pagination, Navigation } from 'swiper/modules';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next';
|
||||
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/pagination';
|
||||
import 'swiper/css/navigation';
|
||||
|
||||
const modules = [Autoplay, Pagination, Navigation];
|
||||
|
||||
const screenshots = [
|
||||
'/screenshots/s1-0412.png',
|
||||
'/screenshots/s2-0412.png',
|
||||
'/screenshots/s3-0412.png',
|
||||
'/screenshots/s4-0412.png',
|
||||
'/screenshots/s5-0412.png',
|
||||
'/screenshots/s6-0412.png',
|
||||
'/screenshots/s7-0412.png',
|
||||
'/screenshots/s8-0412.png',
|
||||
'/screenshots/s9-0412.png',
|
||||
'/screenshots/s10-0412.png',
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="carousel-section">
|
||||
<Swiper
|
||||
:modules="modules"
|
||||
:slides-per-view="1"
|
||||
:space-between="16"
|
||||
:loop="true"
|
||||
:autoplay="{ delay: 4000, disableOnInteraction: false, pauseOnMouseEnter: true }"
|
||||
:pagination="{ clickable: true }"
|
||||
:navigation="{ nextEl: '.carousel-next', prevEl: '.carousel-prev' }"
|
||||
class="screenshots-swiper"
|
||||
>
|
||||
<SwiperSlide v-for="(src, idx) in screenshots" :key="idx">
|
||||
<div class="slide-wrapper">
|
||||
<img :src="src" :alt="`AQBot Screenshot ${idx + 1}`" loading="lazy" />
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
<button class="carousel-nav carousel-prev" aria-label="Previous slide">
|
||||
<ChevronLeft :size="24" />
|
||||
</button>
|
||||
<button class="carousel-nav carousel-next" aria-label="Next slide">
|
||||
<ChevronRight :size="24" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.carousel-section {
|
||||
position: relative;
|
||||
max-width: 960px;
|
||||
margin: 40px auto 24px;
|
||||
padding: 0 24px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.carousel-section {
|
||||
padding: 0 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.carousel-section {
|
||||
padding: 0 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.screenshots-swiper {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.slide-wrapper {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
|
||||
background: var(--vp-c-bg-soft);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.slide-wrapper:hover {
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.dark .slide-wrapper {
|
||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.dark .slide-wrapper:hover {
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.slide-wrapper img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Navigation arrows */
|
||||
.carousel-nav {
|
||||
position: absolute;
|
||||
top: calc(50% - 20px);
|
||||
transform: translateY(-50%);
|
||||
z-index: 10;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg);
|
||||
color: var(--vp-c-text-2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.carousel-nav:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
color: var(--vp-c-brand-1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dark .carousel-nav {
|
||||
background: var(--vp-c-bg-soft);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.carousel-prev {
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
.carousel-next {
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.carousel-prev { left: 16px; }
|
||||
.carousel-next { right: 16px; }
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.carousel-prev { left: 28px; }
|
||||
.carousel-next { right: 28px; }
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.carousel-nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Swiper pagination bullets */
|
||||
:deep(.swiper-pagination-bullet) {
|
||||
background: var(--vp-c-text-3);
|
||||
opacity: 0.4;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
:deep(.swiper-pagination-bullet-active) {
|
||||
background: var(--vp-c-brand-1);
|
||||
opacity: 1;
|
||||
width: 24px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,209 @@
|
||||
:root {
|
||||
--vp-c-brand-1: #309731;
|
||||
--vp-c-brand-2: #27802a;
|
||||
--vp-c-brand-3: #1f6922;
|
||||
--vp-c-brand-soft: rgba(48, 151, 49, 0.14);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-c-brand-1: #3fba40;
|
||||
--vp-c-brand-2: #309731;
|
||||
--vp-c-brand-3: #27802a;
|
||||
--vp-c-brand-soft: rgba(63, 186, 64, 0.16);
|
||||
}
|
||||
|
||||
/* Hero name gradient with brand green */
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #309731 30%, #56c457);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #3fba40 30%, #7ade7b);
|
||||
}
|
||||
|
||||
/* Hero: center text, hide image area */
|
||||
.VPHero .VPImage,
|
||||
.VPHero .image-container,
|
||||
.VPHero .image {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Override default hero layout for centered text-only hero */
|
||||
.VPHero .container {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.VPHero .main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.VPHero .heading {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.VPHero .name,
|
||||
.VPHero .text {
|
||||
margin: 0 auto !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.VPHero .tagline {
|
||||
margin: 0 auto !important;
|
||||
text-align: center !important;
|
||||
max-width: 576px !important;
|
||||
}
|
||||
|
||||
/* Remove default hero actions (we use custom ones) */
|
||||
.VPHero .actions {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide default VitePress features (we render custom FeaturesGrid) */
|
||||
.VPFeatures {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Reduce hero vertical space */
|
||||
@media (min-width: 960px) {
|
||||
.VPHero {
|
||||
padding-top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) !important;
|
||||
padding-bottom: 32px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nav icons via ::before pseudo-elements */
|
||||
.VPNavBarMenuLink[href="/"],
|
||||
.VPNavBarMenuLink[href="/zh/"],
|
||||
.VPNavBarMenuLink[href="/zh-tw/"],
|
||||
.VPNavBarMenuLink[href="/ja/"],
|
||||
.VPNavBarMenuLink[href="/ko/"],
|
||||
.VPNavBarMenuLink[href="/fr/"],
|
||||
.VPNavBarMenuLink[href="/de/"],
|
||||
.VPNavBarMenuLink[href="/es/"],
|
||||
.VPNavBarMenuLink[href="/ru/"],
|
||||
.VPNavBarMenuLink[href="/hi/"],
|
||||
.VPNavBarMenuLink[href="/ar/"] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.VPNavBarMenuLink[href="/"]::before,
|
||||
.VPNavBarMenuLink[href="/zh/"]::before,
|
||||
.VPNavBarMenuLink[href="/zh-tw/"]::before,
|
||||
.VPNavBarMenuLink[href="/ja/"]::before,
|
||||
.VPNavBarMenuLink[href="/ko/"]::before,
|
||||
.VPNavBarMenuLink[href="/fr/"]::before,
|
||||
.VPNavBarMenuLink[href="/de/"]::before,
|
||||
.VPNavBarMenuLink[href="/es/"]::before,
|
||||
.VPNavBarMenuLink[href="/ru/"]::before,
|
||||
.VPNavBarMenuLink[href="/hi/"]::before,
|
||||
.VPNavBarMenuLink[href="/ar/"]::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--vp-c-text-2);
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
transition: background-color 0.25s;
|
||||
}
|
||||
|
||||
/* Home icon (nav item 1) */
|
||||
.VPNavBarMenuLink[href="/"]::before,
|
||||
.VPNavBarMenuLink[href="/zh/"]::before,
|
||||
.VPNavBarMenuLink[href="/zh-tw/"]::before,
|
||||
.VPNavBarMenuLink[href="/ja/"]::before,
|
||||
.VPNavBarMenuLink[href="/ko/"]::before,
|
||||
.VPNavBarMenuLink[href="/fr/"]::before,
|
||||
.VPNavBarMenuLink[href="/de/"]::before,
|
||||
.VPNavBarMenuLink[href="/es/"]::before,
|
||||
.VPNavBarMenuLink[href="/ru/"]::before,
|
||||
.VPNavBarMenuLink[href="/hi/"]::before,
|
||||
.VPNavBarMenuLink[href="/ar/"]::before {
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M946.5 505L560.1 118.8l-25.9-25.9a31.5 31.5 0 00-44.4 0L77.5 505a63.9 63.9 0 00-18.8 46c.4 35.2 29.7 63.3 64.9 63.3h42.5V940h691.8V614.3h43.4c17.1 0 33.2-6.7 45.3-18.8a63.6 63.6 0 0018.7-45.3c0-17-6.7-33.1-18.8-45.2zM568 868H456V664h112v204zm217.9-325.7V868H632V640c0-22.1-17.9-40-40-40H432c-22.1 0-40 17.9-40 40v228H238.1V542.3h-96l370-369.7 23.1 23.1L882 542.3h-96.1z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M946.5 505L560.1 118.8l-25.9-25.9a31.5 31.5 0 00-44.4 0L77.5 505a63.9 63.9 0 00-18.8 46c.4 35.2 29.7 63.3 64.9 63.3h42.5V940h691.8V614.3h43.4c17.1 0 33.2-6.7 45.3-18.8a63.6 63.6 0 0018.7-45.3c0-17-6.7-33.1-18.8-45.2zM568 868H456V664h112v204zm217.9-325.7V868H632V640c0-22.1-17.9-40-40-40H432c-22.1 0-40 17.9-40 40v228H238.1V542.3h-96l370-369.7 23.1 23.1L882 542.3h-96.1z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* Features icon (nav item 2) */
|
||||
.VPNavBarMenuLink[href*="/features"]::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--vp-c-text-2);
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
transition: background-color 0.25s;
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* Download icon (nav item 3) */
|
||||
.VPNavBarMenuLink[href*="/download"]::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--vp-c-text-2);
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
transition: background-color 0.25s;
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* Docs icon (nav item 4) */
|
||||
.VPNavBarMenuLink[href*="/guide/"]::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--vp-c-text-2);
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
transition: background-color 0.25s;
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M928 161H699.2c-49.1 0-97.1 14.1-138.4 40.7L512 233l-48.8-31.3A255.2 255.2 0 00324.8 161H96c-17.7 0-32 14.3-32 32v568c0 17.7 14.3 32 32 32h228.8c49.1 0 97.1 14.1 138.4 40.7l44.4 28.6c1.3.8 2.8 1.3 4.3 1.3s3-.4 4.3-1.3l44.4-28.6c41.3-26.6 89.3-40.7 138.4-40.7H928c17.7 0 32-14.3 32-32V193c0-17.7-14.3-32-32-32zM324.8 721H136V233h188.8c35.4 0 69.8 10.1 99.5 29.2l48.8 31.3 6.9 4.5v462c-47.6-25.6-100.8-39-155.2-39zm563.2 0H699.2c-54.4 0-107.6 13.4-155.2 39V298l6.9-4.5 48.8-31.3c29.7-19.1 64.1-29.2 99.5-29.2H888v488z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M928 161H699.2c-49.1 0-97.1 14.1-138.4 40.7L512 233l-48.8-31.3A255.2 255.2 0 00324.8 161H96c-17.7 0-32 14.3-32 32v568c0 17.7 14.3 32 32 32h228.8c49.1 0 97.1 14.1 138.4 40.7l44.4 28.6c1.3.8 2.8 1.3 4.3 1.3s3-.4 4.3-1.3l44.4-28.6c41.3-26.6 89.3-40.7 138.4-40.7H928c17.7 0 32-14.3 32-32V193c0-17.7-14.3-32-32-32zM324.8 721H136V233h188.8c35.4 0 69.8 10.1 99.5 29.2l48.8 31.3 6.9 4.5v462c-47.6-25.6-100.8-39-155.2-39zm563.2 0H699.2c-54.4 0-107.6 13.4-155.2 39V298l6.9-4.5 48.8-31.3c29.7-19.1 64.1-29.2 99.5-29.2H888v488z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* Features/download/docs links also need flex layout */
|
||||
.VPNavBarMenuLink[href*="/features"],
|
||||
.VPNavBarMenuLink[href*="/download"],
|
||||
.VPNavBarMenuLink[href*="/guide/"] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Nav icon color follows link text: default muted, active = brand color */
|
||||
.VPNavBarMenuLink:hover::before,
|
||||
.VPNavBarMenuLink.active::before {
|
||||
background-color: var(--vp-c-brand-1) !important;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
import { useRouter, inBrowser } from 'vitepress';
|
||||
import { onMounted } from 'vue';
|
||||
import HomeLayout from './HomeLayout.vue';
|
||||
import DownloadHero from './DownloadHero.vue';
|
||||
import './custom.css';
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout: HomeLayout,
|
||||
enhanceApp({ app }) {
|
||||
app.component('DownloadHero', DownloadHero);
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
|
||||
onMounted(() => {
|
||||
if (!inBrowser) return;
|
||||
const path = window.location.pathname;
|
||||
if (path !== '/') return;
|
||||
const lang = navigator.language || navigator.languages?.[0] || '';
|
||||
if (/^zh/i.test(lang)) {
|
||||
router.go('/zh/');
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user