format
This commit is contained in:
parent
a0cfe7df4a
commit
d958f8d31f
@ -117,7 +117,8 @@ For more detailed guidelines, please refer to our [Contributing Guide](./CONTRIB
|
|||||||
Thank you for your support and contributions!
|
Thank you for your support and contributions!
|
||||||
|
|
||||||
## Related Projects
|
## Related Projects
|
||||||
* [one-api](https://github.com/songquanpeng/one-api):LLM API management and distribution system, supporting mainstream models like OpenAI, Azure, and Anthropic. Features unified API interface, suitable for key management and secondary distribution.
|
|
||||||
|
- [one-api](https://github.com/songquanpeng/one-api):LLM API management and distribution system, supporting mainstream models like OpenAI, Azure, and Anthropic. Features unified API interface, suitable for key management and secondary distribution.
|
||||||
|
|
||||||
# 🚀 Contributors
|
# 🚀 Contributors
|
||||||
|
|
||||||
|
|||||||
@ -118,7 +118,8 @@ Cherry Studioへの貢献を歓迎します!以下の方法で貢献できま
|
|||||||
ご支援と貢献に感謝します!
|
ご支援と貢献に感謝します!
|
||||||
|
|
||||||
## 関連頁版
|
## 関連頁版
|
||||||
* [one-api](https://github.com/songquanpeng/one-api):LLM APIの管理・配信システム。OpenAI、Azure、Anthropicなどの主要モデルに対応し、統一APIインターフェースを提供。APIキー管理と再配布に利用可能。
|
|
||||||
|
- [one-api](https://github.com/songquanpeng/one-api):LLM APIの管理・配信システム。OpenAI、Azure、Anthropicなどの主要モデルに対応し、統一APIインターフェースを提供。APIキー管理と再配布に利用可能。
|
||||||
|
|
||||||
# 🚀 コントリビューター
|
# 🚀 コントリビューター
|
||||||
|
|
||||||
|
|||||||
@ -118,7 +118,8 @@ $ yarn build:linux
|
|||||||
感谢您的支持和贡献!
|
感谢您的支持和贡献!
|
||||||
|
|
||||||
## 相关项目
|
## 相关项目
|
||||||
* [one-api](https://github.com/songquanpeng/one-api):LLM API管理及分发系统,支持OpenAI、Azure、Anthropic等主流模型,统一API接口,可用于密钥管理与二次分发。
|
|
||||||
|
- [one-api](https://github.com/songquanpeng/one-api):LLM API管理及分发系统,支持OpenAI、Azure、Anthropic等主流模型,统一API接口,可用于密钥管理与二次分发。
|
||||||
|
|
||||||
# 🚀 贡献者
|
# 🚀 贡献者
|
||||||
|
|
||||||
|
|||||||
@ -1,118 +1,111 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>CherryStudio 许可协议-ZH/EN</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
<head>
|
<body class="bg-gray-100 p-8">
|
||||||
<meta charset="UTF-8" />
|
<div class="container mx-auto bg-white p-6 rounded shadow-lg">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<h1 class="text-3xl font-bold mb-6 text-center">Cherry Studio 许可协议</h1>
|
||||||
<title>CherryStudio 许可协议-ZH/EN</title>
|
<div class="mb-8">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet" />
|
<h2 class="text-2xl font-semibold mb-4">许可协议</h2>
|
||||||
</head>
|
<p class="mb-4">
|
||||||
|
本软件采用 <strong>Apache License 2.0</strong> 许可。除 Apache License 2.0 规定的条款外,您在使用 Cherry
|
||||||
<body class="bg-gray-100 p-8">
|
Studio 时还应遵守以下附加条款:
|
||||||
<div class="container mx-auto bg-white p-6 rounded shadow-lg">
|
</p>
|
||||||
<h1 class="text-3xl font-bold mb-6 text-center">Cherry Studio 许可协议</h1>
|
<h3 class="text-xl font-semibold mb-2">一. 商用许可</h3>
|
||||||
<div class="mb-8">
|
<ol class="list-decimal list-inside mb-4">
|
||||||
<h2 class="text-2xl font-semibold mb-4">许可协议</h2>
|
<li><strong>免费商用</strong>:用户在不修改代码的情况下,可以免费用于商业目的。</li>
|
||||||
<p class="mb-4">
|
<li>
|
||||||
本软件采用 <strong>Apache License 2.0</strong> 许可。除 Apache License 2.0 规定的条款外,您在使用 Cherry
|
<strong>商业授权</strong>:如果您满足以下任意条件之一,需取得商业授权:
|
||||||
Studio 时还应遵守以下附加条款:
|
<ol class="list-decimal list-inside ml-4">
|
||||||
</p>
|
<li>对本软件进行二次修改、开发(包括但不限于修改应用名称、logo、代码以及功能)。</li>
|
||||||
<h3 class="text-xl font-semibold mb-2">一. 商用许可</h3>
|
<li>为企业客户提供多租户服务,且该服务支持 10 人或以上的使用。</li>
|
||||||
<ol class="list-decimal list-inside mb-4">
|
<li>预装或集成到硬件设备或产品中进行捆绑销售。</li>
|
||||||
<li><strong>免费商用</strong>:用户在不修改代码的情况下,可以免费用于商业目的。</li>
|
<li>政府或教育机构的大规模采购项目,特别是涉及安全、数据隐私等敏感需求时。</li>
|
||||||
<li>
|
</ol>
|
||||||
<strong>商业授权</strong>:如果您满足以下任意条件之一,需取得商业授权:
|
</li>
|
||||||
<ol class="list-decimal list-inside ml-4">
|
</ol>
|
||||||
<li>对本软件进行二次修改、开发(包括但不限于修改应用名称、logo、代码以及功能)。</li>
|
<h3 class="text-xl font-semibold mb-2">二. 贡献者协议</h3>
|
||||||
<li>为企业客户提供多租户服务,且该服务支持 10 人或以上的使用。</li>
|
<ol class="list-decimal list-inside mb-4">
|
||||||
<li>预装或集成到硬件设备或产品中进行捆绑销售。</li>
|
<li><strong>许可调整</strong>:生产者有权根据需要对开源协议进行调整,使其更加严格或宽松。</li>
|
||||||
<li>政府或教育机构的大规模采购项目,特别是涉及安全、数据隐私等敏感需求时。</li>
|
<li><strong>商业用途</strong>:您贡献的代码可能会被用于商业用途,包括但不限于云业务运营。</li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
<h3 class="text-xl font-semibold mb-2">三. 其他条款</h3>
|
||||||
</ol>
|
<ol class="list-decimal list-inside mb-4">
|
||||||
<h3 class="text-xl font-semibold mb-2">二. 贡献者协议</h3>
|
<li>本协议条款的解释权归 Cherry Studio 开发者所有。</li>
|
||||||
<ol class="list-decimal list-inside mb-4">
|
<li>本协议可能根据实际情况进行更新,更新时将通过本软件通知用户。</li>
|
||||||
<li><strong>许可调整</strong>:生产者有权根据需要对开源协议进行调整,使其更加严格或宽松。</li>
|
</ol>
|
||||||
<li><strong>商业用途</strong>:您贡献的代码可能会被用于商业用途,包括但不限于云业务运营。</li>
|
<p class="mb-4">如有任何问题或需申请商业授权,请联系 Cherry Studio 开发团队。</p>
|
||||||
</ol>
|
<p>
|
||||||
<h3 class="text-xl font-semibold mb-2">三. 其他条款</h3>
|
除上述特定条件外,其他所有权利和限制均遵循 Apache License 2.0。有关 Apache License 2.0 的详细信息,请访问
|
||||||
<ol class="list-decimal list-inside mb-4">
|
<a href="http://www.apache.org/licenses/LICENSE-2.0" class="text-blue-500 underline"
|
||||||
<li>本协议条款的解释权归 Cherry Studio 开发者所有。</li>
|
>http://www.apache.org/licenses/LICENSE-2.0</a
|
||||||
<li>本协议可能根据实际情况进行更新,更新时将通过本软件通知用户。</li>
|
>
|
||||||
</ol>
|
</p>
|
||||||
<p class="mb-4">如有任何问题或需申请商业授权,请联系 Cherry Studio 开发团队。</p>
|
</div>
|
||||||
<p>
|
<h1 class="text-3xl font-bold mb-6 text-center">Cherry Studio License</h1>
|
||||||
除上述特定条件外,其他所有权利和限制均遵循 Apache License 2.0。有关 Apache License 2.0 的详细信息,请访问
|
<div class="mb-8">
|
||||||
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
<h2 class="text-2xl font-semibold mb-4">License Agreement</h2>
|
||||||
class="text-blue-500 underline">http://www.apache.org/licenses/LICENSE-2.0</a>
|
<p class="mb-4">
|
||||||
</p>
|
This software is licensed under the <strong>Apache License 2.0</strong>. In addition to the terms of the
|
||||||
|
Apache License 2.0, the following additional terms apply to the use of Cherry Studio:
|
||||||
|
</p>
|
||||||
|
<h3 class="text-xl font-semibold mb-2">I. Commercial Use License</h3>
|
||||||
|
<ol class="list-decimal list-inside mb-4">
|
||||||
|
<li>
|
||||||
|
<strong>Free Commercial Use</strong>: Users can use the software for commercial purposes without modifying
|
||||||
|
the code.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Commercial License Required</strong>: A commercial license is required if any of the following
|
||||||
|
conditions are met:
|
||||||
|
<ol class="list-decimal list-inside ml-4">
|
||||||
|
<li>
|
||||||
|
You modify, develop, or alter the software, including but not limited to changes to the application
|
||||||
|
name, logo, code, or functionality.
|
||||||
|
</li>
|
||||||
|
<li>You provide multi-tenant services to enterprise customers with 10 or more users.</li>
|
||||||
|
<li>
|
||||||
|
You pre-install or integrate the software into hardware devices or products and bundle it for sale.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
You are engaging in large-scale procurement for government or educational institutions, especially
|
||||||
|
involving security, data privacy, or other sensitive requirements.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h3 class="text-xl font-semibold mb-2">II. Contributor Agreement</h3>
|
||||||
|
<ol class="list-decimal list-inside mb-4">
|
||||||
|
<li>
|
||||||
|
<strong>License Adjustment</strong>: The producer reserves the right to adjust the open-source license as
|
||||||
|
needed, making it stricter or more lenient.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Commercial Use</strong>: Any code you contribute may be used for commercial purposes, including but
|
||||||
|
not limited to cloud business operations.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h3 class="text-xl font-semibold mb-2">III. Other Terms</h3>
|
||||||
|
<ol class="list-decimal list-inside mb-4">
|
||||||
|
<li>The interpretation of these terms is subject to the discretion of Cherry Studio developers.</li>
|
||||||
|
<li>These terms may be updated, and users will be notified through the software when changes occur.</li>
|
||||||
|
</ol>
|
||||||
|
<p class="mb-4">
|
||||||
|
For any questions or to request a commercial license, please contact the Cherry Studio development team.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache
|
||||||
|
License 2.0. Detailed information about the Apache License 2.0 can be found at
|
||||||
|
<a href="http://www.apache.org/licenses/LICENSE-2.0" class="text-blue-500 underline"
|
||||||
|
>http://www.apache.org/licenses/LICENSE-2.0</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-3xl font-bold mb-6 text-center">Cherry Studio License</h1>
|
</body>
|
||||||
<div class="mb-8">
|
</html>
|
||||||
<h2 class="text-2xl font-semibold mb-4">License Agreement</h2>
|
|
||||||
<p class="mb-4">
|
|
||||||
This software is licensed under the <strong>Apache License 2.0</strong>. In addition to the terms of the
|
|
||||||
Apache License 2.0, the following additional terms apply to the use of Cherry Studio:
|
|
||||||
</p>
|
|
||||||
<h3 class="text-xl font-semibold mb-2">I. Commercial Use License</h3>
|
|
||||||
<ol class="list-decimal list-inside mb-4">
|
|
||||||
<li>
|
|
||||||
<strong>Free Commercial Use</strong>: Users can use the software for commercial purposes without
|
|
||||||
modifying
|
|
||||||
the code.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Commercial License Required</strong>: A commercial license is required if any of the
|
|
||||||
following
|
|
||||||
conditions are met:
|
|
||||||
<ol class="list-decimal list-inside ml-4">
|
|
||||||
<li>
|
|
||||||
You modify, develop, or alter the software, including but not limited to changes to the
|
|
||||||
application
|
|
||||||
name, logo, code, or functionality.
|
|
||||||
</li>
|
|
||||||
<li>You provide multi-tenant services to enterprise customers with 10 or more users.</li>
|
|
||||||
<li>
|
|
||||||
You pre-install or integrate the software into hardware devices or products and bundle it
|
|
||||||
for sale.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You are engaging in large-scale procurement for government or educational institutions,
|
|
||||||
especially
|
|
||||||
involving security, data privacy, or other sensitive requirements.
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<h3 class="text-xl font-semibold mb-2">II. Contributor Agreement</h3>
|
|
||||||
<ol class="list-decimal list-inside mb-4">
|
|
||||||
<li>
|
|
||||||
<strong>License Adjustment</strong>: The producer reserves the right to adjust the open-source
|
|
||||||
license as
|
|
||||||
needed, making it stricter or more lenient.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Commercial Use</strong>: Any code you contribute may be used for commercial purposes,
|
|
||||||
including but
|
|
||||||
not limited to cloud business operations.
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<h3 class="text-xl font-semibold mb-2">III. Other Terms</h3>
|
|
||||||
<ol class="list-decimal list-inside mb-4">
|
|
||||||
<li>The interpretation of these terms is subject to the discretion of Cherry Studio developers.</li>
|
|
||||||
<li>These terms may be updated, and users will be notified through the software when changes occur.</li>
|
|
||||||
</ol>
|
|
||||||
<p class="mb-4">
|
|
||||||
For any questions or to request a commercial license, please contact the Cherry Studio development team.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache
|
|
||||||
License 2.0. Detailed information about the Apache License 2.0 can be found at
|
|
||||||
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
|
||||||
class="text-blue-500 underline">http://www.apache.org/licenses/LICENSE-2.0</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Github Releases Timeline</title>
|
<title>Github Releases Timeline</title>
|
||||||
@ -9,194 +8,201 @@
|
|||||||
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
|
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/typography@0.5.10/dist/typography.min.css"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/typography@0.5.10/dist/typography.min.css"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<div :class="isDark ? 'dark-bg' : 'bg'" class="min-h-screen">
|
<div :class="isDark ? 'dark-bg' : 'bg'" class="min-h-screen">
|
||||||
<div class="max-w-3xl mx-auto py-12 px-4">
|
<div class="max-w-3xl mx-auto py-12 px-4">
|
||||||
<h1 class="text-3xl font-bold mb-8" :class="isDark ? 'text-white' : 'text-gray-900'">Release Timeline</h1>
|
<h1 class="text-3xl font-bold mb-8" :class="isDark ? 'text-white' : 'text-gray-900'">Release Timeline</h1>
|
||||||
|
|
||||||
<!-- Loading状态 -->
|
<!-- Loading状态 -->
|
||||||
<div v-if="loading" class="text-center py-8">
|
<div v-if="loading" class="text-center py-8">
|
||||||
<div class="inline-block animate-spin rounded-full h-8 w-8 border-4"
|
<div
|
||||||
:class="isDark ? 'border-gray-700 border-t-blue-500' : 'border-gray-300 border-t-blue-500'"></div>
|
class="inline-block animate-spin rounded-full h-8 w-8 border-4"
|
||||||
</div>
|
:class="isDark ? 'border-gray-700 border-t-blue-500' : 'border-gray-300 border-t-blue-500'"></div>
|
||||||
|
|
||||||
<!-- Error 状态 -->
|
|
||||||
<div v-else-if="error" class="text-red-500 text-center py-8">{{ error }}</div>
|
|
||||||
|
|
||||||
<!-- Release 列表 -->
|
|
||||||
<div v-else class="space-y-8">
|
|
||||||
<div v-for="release in releases" :key="release.id" class="relative pl-8"
|
|
||||||
:class="isDark ? 'border-l-2 border-gray-700' : 'border-l-2 border-gray-200'">
|
|
||||||
<div class="absolute -left-2 top-0 w-4 h-4 rounded-full bg-green-500"></div>
|
|
||||||
<div class="rounded-lg shadow-sm p-6 transition-shadow"
|
|
||||||
:class="isDark ? 'bg-black hover:shadow-md hover:shadow-black' : 'bg-white hover:shadow-md'">
|
|
||||||
<div class="flex items-start justify-between mb-4">
|
|
||||||
<div>
|
|
||||||
<h2 class="text-xl font-semibold" :class="isDark ? 'text-white' : 'text-gray-900'">
|
|
||||||
{{ release.name || release.tag_name }}
|
|
||||||
</h2>
|
|
||||||
<p class="text-sm mt-1" :class="isDark ? 'text-gray-400' : 'text-gray-500'">
|
|
||||||
{{ formatDate(release.published_at) }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium"
|
|
||||||
:class="isDark ? 'bg-green-900 text-green-200' : 'bg-green-100 text-green-800'">
|
|
||||||
{{ release.tag_name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="prose" :class="isDark ? 'text-gray-300 dark-prose' : 'text-gray-600'"
|
|
||||||
v-html="renderMarkdown(release.body)"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Error 状态 -->
|
||||||
|
<div v-else-if="error" class="text-red-500 text-center py-8">{{ error }}</div>
|
||||||
|
|
||||||
|
<!-- Release 列表 -->
|
||||||
|
<div v-else class="space-y-8">
|
||||||
|
<div
|
||||||
|
v-for="release in releases"
|
||||||
|
:key="release.id"
|
||||||
|
class="relative pl-8"
|
||||||
|
:class="isDark ? 'border-l-2 border-gray-700' : 'border-l-2 border-gray-200'">
|
||||||
|
<div class="absolute -left-2 top-0 w-4 h-4 rounded-full bg-green-500"></div>
|
||||||
|
<div
|
||||||
|
class="rounded-lg shadow-sm p-6 transition-shadow"
|
||||||
|
:class="isDark ? 'bg-black hover:shadow-md hover:shadow-black' : 'bg-white hover:shadow-md'">
|
||||||
|
<div class="flex items-start justify-between mb-4">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-xl font-semibold" :class="isDark ? 'text-white' : 'text-gray-900'">
|
||||||
|
{{ release.name || release.tag_name }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-sm mt-1" :class="isDark ? 'text-gray-400' : 'text-gray-500'">
|
||||||
|
{{ formatDate(release.published_at) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium"
|
||||||
|
:class="isDark ? 'bg-green-900 text-green-200' : 'bg-green-100 text-green-800'">
|
||||||
|
{{ release.tag_name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="prose"
|
||||||
|
:class="isDark ? 'text-gray-300 dark-prose' : 'text-gray-600'"
|
||||||
|
v-html="renderMarkdown(release.body)"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const md = window.markdownit({
|
const md = window.markdownit({
|
||||||
breaks: true,
|
breaks: true,
|
||||||
linkify: true
|
linkify: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const { createApp } = Vue
|
const { createApp } = Vue
|
||||||
|
|
||||||
createApp({
|
createApp({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
releases: [],
|
releases: [],
|
||||||
loading: true,
|
loading: true,
|
||||||
error: null,
|
error: null,
|
||||||
isDark: false
|
isDark: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchReleases() {
|
async fetchReleases() {
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.error = null
|
this.error = null
|
||||||
const response = await fetch('https://api.github.com/repos/kangfenmao/cherry-studio/releases')
|
const response = await fetch('https://api.github.com/repos/kangfenmao/cherry-studio/releases')
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Failed to fetch releases')
|
throw new Error('Failed to fetch releases')
|
||||||
}
|
}
|
||||||
this.releases = await response.json()
|
this.releases = await response.json()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.error = 'Error loading releases: ' + err.message
|
this.error = 'Error loading releases: ' + err.message
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
|
||||||
},
|
|
||||||
formatDate(dateString) {
|
|
||||||
return new Date(dateString).toLocaleDateString('en-US', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
renderMarkdown(content) {
|
|
||||||
if (!content) return ''
|
|
||||||
return md.render(content)
|
|
||||||
},
|
|
||||||
initTheme() {
|
|
||||||
// 从 URL 参数获取主题设置
|
|
||||||
const url = new URL(window.location.href)
|
|
||||||
const theme = url.searchParams.get('theme')
|
|
||||||
this.isDark = theme === 'dark'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initTheme()
|
|
||||||
this.fetchReleases()
|
|
||||||
}
|
}
|
||||||
}).mount('#app')
|
},
|
||||||
|
formatDate(dateString) {
|
||||||
|
return new Date(dateString).toLocaleDateString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
renderMarkdown(content) {
|
||||||
|
if (!content) return ''
|
||||||
|
return md.render(content)
|
||||||
|
},
|
||||||
|
initTheme() {
|
||||||
|
// 从 URL 参数获取主题设置
|
||||||
|
const url = new URL(window.location.href)
|
||||||
|
const theme = url.searchParams.get('theme')
|
||||||
|
this.isDark = theme === 'dark'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initTheme()
|
||||||
|
this.fetchReleases()
|
||||||
|
}
|
||||||
|
}).mount('#app')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* 基础的 Markdown 样式 */
|
/* 基础的 Markdown 样式 */
|
||||||
.prose {
|
.prose {
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose h1 {
|
.prose h1 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
margin: 0.8em 0;
|
margin: 0.8em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose h3 {
|
.prose h3 {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
margin: 0.6em 0;
|
margin: 0.6em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose code {
|
.prose code {
|
||||||
padding: 0.2em 0.4em;
|
padding: 0.2em 0.4em;
|
||||||
border-radius: 0.2em;
|
border-radius: 0.2em;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .prose code {
|
.dark .prose code {
|
||||||
background-color: #1f2937;
|
background-color: #1f2937;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose code {
|
.prose code {
|
||||||
background-color: #f3f4f6;
|
background-color: #f3f4f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose pre code {
|
.prose pre code {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose a {
|
.prose a {
|
||||||
color: #3b82f6;
|
color: #3b82f6;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .prose a {
|
.dark .prose a {
|
||||||
color: #60a5fa;
|
color: #60a5fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose blockquote {
|
.prose blockquote {
|
||||||
border-left: 4px solid #e5e7eb;
|
border-left: 4px solid #e5e7eb;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .prose blockquote {
|
.dark .prose blockquote {
|
||||||
border-left-color: #374151;
|
border-left-color: #374151;
|
||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .prose {
|
.dark .prose {
|
||||||
color: #e5e7eb;
|
color: #e5e7eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-bg {
|
.dark-bg {
|
||||||
background-color: #151515;
|
background-color: #151515;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg {
|
.bg {
|
||||||
background-color: #f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</body>
|
</body>
|
||||||
|
</html>
|
||||||
</html>
|
|
||||||
|
|||||||
@ -1,42 +1,41 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
||||||
|
<meta
|
||||||
|
http-equiv="Content-Security-Policy"
|
||||||
|
content="default-src 'self'; connect-src blob: *; script-src 'self' 'unsafe-eval' *; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' data: *; img-src 'self' data: file: * blob:; frame-src * file:" />
|
||||||
|
|
||||||
<head>
|
<style>
|
||||||
<meta charset="UTF-8" />
|
html,
|
||||||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
body {
|
||||||
<meta http-equiv="Content-Security-Policy"
|
margin: 0;
|
||||||
content="default-src 'self'; connect-src blob: *; script-src 'self' 'unsafe-eval' *; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' *; font-src 'self' data: *; img-src 'self' data: file: * blob:; frame-src * file:" />
|
}
|
||||||
|
|
||||||
<style>
|
#spinner {
|
||||||
html,
|
position: fixed;
|
||||||
body {
|
width: 100vw;
|
||||||
margin: 0;
|
height: 100vh;
|
||||||
}
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#spinner {
|
#spinner img {
|
||||||
position: fixed;
|
width: 100px;
|
||||||
width: 100vw;
|
border-radius: 50px;
|
||||||
height: 100vh;
|
}
|
||||||
flex-direction: row;
|
</style>
|
||||||
justify-content: center;
|
</head>
|
||||||
align-items: center;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#spinner img {
|
<body>
|
||||||
width: 100px;
|
<div id="root"></div>
|
||||||
border-radius: 50px;
|
<div id="spinner">
|
||||||
}
|
<img src="/src/assets/images/logo.png" />
|
||||||
</style>
|
</div>
|
||||||
</head>
|
<script type="module" src="/src/init.ts"></script>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
<body>
|
</body>
|
||||||
<div id="root"></div>
|
</html>
|
||||||
<div id="spinner">
|
|
||||||
<img src="/src/assets/images/logo.png" />
|
|
||||||
</div>
|
|
||||||
<script type="module" src="/src/init.ts"></script>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|||||||
@ -95,14 +95,14 @@ export const Box = styled.div<BoxProps>`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: ${(props) => props?.border || 'none'};
|
border: ${(props) => props?.border || 'none'};
|
||||||
gap: ${(p) => (p.gap ? getElementValue(p.gap) : 0)};
|
gap: ${(p) => (p.gap ? getElementValue(p.gap) : 0)};
|
||||||
margin: ${(props) => (props.m || props.margin ? props.m ?? props.margin : 'none')};
|
margin: ${(props) => (props.m || props.margin ? (props.m ?? props.margin) : 'none')};
|
||||||
margin-top: ${(props) => (props.mt || props.marginTop ? getElementValue(props.mt || props.marginTop) : 'default')};
|
margin-top: ${(props) => (props.mt || props.marginTop ? getElementValue(props.mt || props.marginTop) : 'default')};
|
||||||
margin-bottom: ${(props) =>
|
margin-bottom: ${(props) =>
|
||||||
props.mb || props.marginBottom ? getElementValue(props.mb ?? props.marginBottom) : 'default'};
|
props.mb || props.marginBottom ? getElementValue(props.mb ?? props.marginBottom) : 'default'};
|
||||||
margin-left: ${(props) => (props.ml || props.marginLeft ? getElementValue(props.ml ?? props.marginLeft) : 'default')};
|
margin-left: ${(props) => (props.ml || props.marginLeft ? getElementValue(props.ml ?? props.marginLeft) : 'default')};
|
||||||
margin-right: ${(props) =>
|
margin-right: ${(props) =>
|
||||||
props.mr || props.marginRight ? getElementValue(props.mr ?? props.marginRight) : 'default'};
|
props.mr || props.marginRight ? getElementValue(props.mr ?? props.marginRight) : 'default'};
|
||||||
padding: ${(props) => (props.p || props.padding ? props.p ?? props.padding : 'none')};
|
padding: ${(props) => (props.p || props.padding ? (props.p ?? props.padding) : 'none')};
|
||||||
padding-top: ${(props) => (props.pt || props.paddingTop ? getElementValue(props.pt ?? props.paddingTop) : 'auto')};
|
padding-top: ${(props) => (props.pt || props.paddingTop ? getElementValue(props.pt ?? props.paddingTop) : 'auto')};
|
||||||
padding-bottom: ${(props) =>
|
padding-bottom: ${(props) =>
|
||||||
props.pb || props.paddingBottom ? getElementValue(props.pb ?? props.paddingBottom) : 'auto'};
|
props.pb || props.paddingBottom ? getElementValue(props.pb ?? props.paddingBottom) : 'auto'};
|
||||||
|
|||||||
@ -1,146 +1,144 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
<meta charset="UTF-8" />
|
||||||
<meta charset="UTF-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<title>Selection Menu</title>
|
||||||
<title>Selection Menu</title>
|
<style>
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--bg-color: rgba(255, 255, 255, 0.95);
|
|
||||||
--button-bg: #f5f5f5;
|
|
||||||
--button-hover: #e8e8e8;
|
|
||||||
--text-color: #333;
|
|
||||||
--border-color: rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
:root {
|
||||||
--bg-color: rgba(80, 80, 80, 0.95);
|
--bg-color: rgba(255, 255, 255, 0.95);
|
||||||
--button-bg: #2c2c2c;
|
--button-bg: #f5f5f5;
|
||||||
--button-hover: #383838;
|
--button-hover: #e8e8e8;
|
||||||
--text-color: #e0e0e0;
|
--text-color: #333;
|
||||||
--border-color: rgba(255, 255, 255, 0.08);
|
--border-color: rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
@media (prefers-color-scheme: dark) {
|
||||||
margin: 0;
|
:root {
|
||||||
padding: 0;
|
--bg-color: rgba(80, 80, 80, 0.95);
|
||||||
box-sizing: border-box;
|
--button-bg: #2c2c2c;
|
||||||
user-select: none;
|
--button-hover: #383838;
|
||||||
}
|
--text-color: #e0e0e0;
|
||||||
|
--border-color: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
* {
|
||||||
width: 280px;
|
margin: 0;
|
||||||
height: 40px;
|
padding: 0;
|
||||||
background: var(--bg-color);
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
user-select: none;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drag-handle {
|
body {
|
||||||
width: 20px;
|
width: 280px;
|
||||||
height: 100%;
|
height: 40px;
|
||||||
display: flex;
|
background: var(--bg-color);
|
||||||
align-items: center;
|
overflow: hidden;
|
||||||
justify-content: center;
|
display: flex;
|
||||||
gap: 2px;
|
align-items: center;
|
||||||
-webkit-app-region: drag;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.drag-handle::before,
|
.drag-handle {
|
||||||
.drag-handle::after {
|
width: 20px;
|
||||||
content: '';
|
height: 100%;
|
||||||
width: 2px;
|
display: flex;
|
||||||
height: 16px;
|
align-items: center;
|
||||||
background-color: var(--border-color);
|
justify-content: center;
|
||||||
border-radius: 1px;
|
gap: 2px;
|
||||||
}
|
-webkit-app-region: drag;
|
||||||
|
}
|
||||||
|
|
||||||
menu {
|
.drag-handle::before,
|
||||||
display: flex;
|
.drag-handle::after {
|
||||||
align-items: center;
|
content: '';
|
||||||
height: 40px;
|
width: 2px;
|
||||||
flex: 1;
|
height: 16px;
|
||||||
margin-right: 10px;
|
background-color: var(--border-color);
|
||||||
gap: 5px;
|
border-radius: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
menu {
|
||||||
flex: 1;
|
display: flex;
|
||||||
min-width: 0;
|
align-items: center;
|
||||||
height: 32px;
|
height: 40px;
|
||||||
border: none;
|
flex: 1;
|
||||||
background: transparent;
|
margin-right: 10px;
|
||||||
border-radius: 6px;
|
gap: 5px;
|
||||||
cursor: pointer;
|
}
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--text-color);
|
|
||||||
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 4px;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
button {
|
||||||
background: var(--button-hover);
|
flex: 1;
|
||||||
}
|
min-width: 0;
|
||||||
|
height: 32px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-color);
|
||||||
|
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
button:active {
|
button:hover {
|
||||||
transform: scale(0.95);
|
background: var(--button-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
button:active {
|
||||||
width: 16px;
|
transform: scale(0.95);
|
||||||
height: 16px;
|
}
|
||||||
fill: currentColor;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
svg {
|
||||||
<div class="drag-handle"></div>
|
width: 16px;
|
||||||
<menu>
|
height: 16px;
|
||||||
<button data-action="chat">
|
fill: currentColor;
|
||||||
<svg viewBox="0 0 24 24">
|
}
|
||||||
<path d="M20,2H4C2.9,2,2,2.9,2,4v18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,16H6l-2,2V4h16V16z" />
|
</style>
|
||||||
</svg>
|
</head>
|
||||||
提问
|
|
||||||
</button>
|
|
||||||
<button data-action="explanation">
|
|
||||||
<svg viewBox="0 0 24 24">
|
|
||||||
<path
|
|
||||||
d="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M13,17h-2v-6h2V17z M13,9h-2V7h2V9z" />
|
|
||||||
</svg>
|
|
||||||
释义
|
|
||||||
</button>
|
|
||||||
<button data-action="translate">
|
|
||||||
<svg viewBox="0 0 24 24">
|
|
||||||
<path d="M6 4h12v2H6zM6 10h12v2H6zM6 16h8v2H6z" />
|
|
||||||
</svg>
|
|
||||||
翻译
|
|
||||||
</button>
|
|
||||||
<button data-action="summary">
|
|
||||||
<svg viewBox="0 0 24 24">
|
|
||||||
<path d="M14,17H4v2h10V17z M20,9H4v2h16V9z M4,15h16v-2H4V15z M4,5v2h16V5H4z" />
|
|
||||||
</svg>
|
|
||||||
总结
|
|
||||||
</button>
|
|
||||||
</menu>
|
|
||||||
|
|
||||||
<script>
|
<body>
|
||||||
document.querySelectorAll('button').forEach(button => {
|
<div class="drag-handle"></div>
|
||||||
button.addEventListener('click', () => {
|
<menu>
|
||||||
const action = button.getAttribute('data-action')
|
<button data-action="chat">
|
||||||
window.api.selectionMenu.action(action)
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path d="M20,2H4C2.9,2,2,2.9,2,4v18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,16H6l-2,2V4h16V16z" />
|
||||||
|
</svg>
|
||||||
|
提问
|
||||||
|
</button>
|
||||||
|
<button data-action="explanation">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M13,17h-2v-6h2V17z M13,9h-2V7h2V9z" />
|
||||||
|
</svg>
|
||||||
|
释义
|
||||||
|
</button>
|
||||||
|
<button data-action="translate">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path d="M6 4h12v2H6zM6 10h12v2H6zM6 16h8v2H6z" />
|
||||||
|
</svg>
|
||||||
|
翻译
|
||||||
|
</button>
|
||||||
|
<button data-action="summary">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path d="M14,17H4v2h10V17z M20,9H4v2h16V9z M4,15h16v-2H4V15z M4,5v2h16V5H4z" />
|
||||||
|
</svg>
|
||||||
|
总结
|
||||||
|
</button>
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.querySelectorAll('button').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const action = button.getAttribute('data-action')
|
||||||
|
window.api.selectionMenu.action(action)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
</script>
|
||||||
</script>
|
</body>
|
||||||
</body>
|
</html>
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user