Track web-core frontend source
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m32s
41
web-core/.gitignore
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
output/
|
||||
*.local
|
||||
vite.config.js
|
||||
vite.config.d.ts
|
||||
src/assets/login/
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
src/types/auto-imports.d.ts
|
||||
src/types/components.d.ts
|
||||
src/views/scriptManage/components/ceshi.png
|
||||
oss
|
||||
|
||||
backup
|
||||
11
web-core/.prettierignore
Normal file
@ -0,0 +1,11 @@
|
||||
node_modules
|
||||
dist
|
||||
build
|
||||
.output
|
||||
.nuxt
|
||||
coverage
|
||||
*.min.js
|
||||
*.min.css
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
yarn.lock
|
||||
8
web-core/.prettierrc.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"printWidth": 150,
|
||||
"bracketSameLine": true,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
}
|
||||
259
web-core/LICENSE
Normal file
@ -0,0 +1,259 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
---
|
||||
|
||||
## 补充协议 | Supplementary Agreement
|
||||
|
||||
> **补充协议 | Supplementary Agreement**
|
||||
>
|
||||
> 若您将本软件或其衍生版本以产品形式分发、销售或提供给**两个及以上独立的第三方主体**使用(无论采用买断、订阅、授权或任何其他商业模式),均须事先取得 HBAI-Ltd 的**书面商业授权**。
|
||||
>
|
||||
> If you distribute, sell, or provide this software (or any derivative) as a product to **two or more independent third parties** (regardless of business model: one-time purchase, subscription, licensing, etc.), you must obtain **written commercial authorization** from HBAI-Ltd prior to such use.
|
||||
>
|
||||
> **五个以内(含五个)**的法人主体作为联合运营方共同使用本软件,且不向联合体以外的第三方分发或提供服务的,视为**内部使用,无需商业授权**。
|
||||
>
|
||||
> **Five (5) or fewer** legal entities jointly operating and using this software internally, without distributing or providing services to parties outside the joint operation, are considered **internal use** and do not require commercial authorization.
|
||||
>
|
||||
> 在使用 Toonflow 的过程中,您不得删除或修改 Toonflow 控制台或应用程序中的标识或版权信息。
|
||||
>
|
||||
> You may not remove or modify any trademarks, logos, or copyright notices in the Toonflow console or application.
|
||||
|
||||
---
|
||||
|
||||
## 永久免费场景 | Always Free — No Authorization Required
|
||||
|
||||
以下使用场景**永久免费**,无需任何授权:
|
||||
|
||||
The following uses are **always free** and require no authorization:
|
||||
|
||||
- ✅ 用 Toonflow 制作内容,在平台发布并获得分账 / Using Toonflow to produce content and earn platform revenue shares
|
||||
- ✅ 二次开发,供自己团队内部使用 / Secondary development and modification for internal team use
|
||||
- ✅ ≤ 5 个法人联合运营内部使用,不对外提供服务 / ≤5 legal entities operating jointly, internally only
|
||||
- ✅ 个人学习、研究、非商业用途 / Personal learning, research, and non-commercial purposes
|
||||
|
||||
---
|
||||
|
||||
## 授权定价 | Licensing Pricing
|
||||
|
||||
商业授权费用与被授权方业务规模挂钩:
|
||||
|
||||
Commercial licensing fees scale with the licensee's business scale:
|
||||
|
||||
| 阶段 | 年销售额 | 年费 |
|
||||
|------|---------|------|
|
||||
| 🌱 扶持期 / Nurture | < ¥10 万 / $10k | **免费 / Free** |
|
||||
| 🚀 初创期 / Startup | ¥10–50 万 / $10k–$50k | ¥5,000 / 年 / year |
|
||||
| 📈 成长期 / Growth | ¥50–150 万 / $50k–$150k | ¥20,000 / 年 / year |
|
||||
| 🏢 规模期 / Scale | ¥150–500 万 / $150k–$500k | ¥80,000 / 年 / year |
|
||||
| 🌐 企业级 / Enterprise | > ¥500 万 / $500k | 面议 / Negotiable |
|
||||
|
||||
---
|
||||
|
||||
## AGPL 用户保护条款 | AGPL User Protection
|
||||
|
||||
> **不追溯条款 | Non-Retroactivity Clause**
|
||||
>
|
||||
> 本协议变更生效日期(v1.0.8 正式发布日)前,基于 AGPL-3.0 条款使用 Toonflow 的用户,其现有使用行为不受本协议变更的约束,继续按 AGPL-3.0 条款执行。
|
||||
>
|
||||
> Users who used Toonflow under AGPL-3.0 prior to the effective date of this change (v1.0.8 official release date) are not affected by this license change. Their existing usage continues under AGPL-3.0.
|
||||
243
web-core/NOTICES.txt
Normal file
@ -0,0 +1,243 @@
|
||||
Name: @eonova/v3-directives
|
||||
License: MIT
|
||||
Repository: N/A
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @icon-park/vue-next
|
||||
License: Apache-2.0
|
||||
Repository: https://github.com/bytedance/IconPark
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @tsconfig/node22
|
||||
License: MIT
|
||||
Repository: https://github.com/tsconfig/bases
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @types/license-checker
|
||||
License: MIT
|
||||
Repository: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @types/node
|
||||
License: MIT
|
||||
Repository: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @types/uuid
|
||||
License: MIT
|
||||
Repository: N/A
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vitejs/plugin-vue
|
||||
License: MIT
|
||||
Repository: https://github.com/vitejs/vite-plugin-vue
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vue/eslint-config-prettier
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/eslint-config-prettier
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vue/eslint-config-typescript
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/eslint-config-typescript
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vue/tsconfig
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/tsconfig
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vueuse/core
|
||||
License: MIT
|
||||
Repository: https://github.com/vueuse/vueuse
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: @vueuse/core
|
||||
License: MIT
|
||||
Repository: https://github.com/vueuse/vueuse
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: ant-design-vue
|
||||
License: MIT
|
||||
Repository: https://github.com/vueComponent/ant-design-vue
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: axios
|
||||
License: MIT
|
||||
Repository: https://github.com/axios/axios
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: class-variance-authority
|
||||
License: Apache-2.0
|
||||
Repository: https://github.com/joe-bell/cva
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: clsx
|
||||
License: MIT
|
||||
Repository: https://github.com/lukeed/clsx
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: dayjs
|
||||
License: MIT
|
||||
Repository: https://github.com/iamkun/dayjs
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: element-plus
|
||||
License: MIT
|
||||
Repository: https://github.com/element-plus/element-plus
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: eslint-plugin-oxlint
|
||||
License: MIT
|
||||
Repository: https://github.com/oxc-project/eslint-plugin-oxlint
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: eslint-plugin-vue
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/eslint-plugin-vue
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: eslint
|
||||
License: MIT
|
||||
Repository: https://github.com/eslint/eslint
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: license-checker
|
||||
License: BSD-3-Clause
|
||||
Repository: https://github.com/davglass/license-checker
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: mammoth
|
||||
License: BSD-2-Clause
|
||||
Repository: https://github.com/mwilliamson/mammoth.js
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: npm-run-all2
|
||||
License: MIT
|
||||
Repository: https://github.com/bcomnes/npm-run-all2
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: oxlint
|
||||
License: MIT
|
||||
Repository: https://github.com/oxc-project/oxc
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: pinia-plugin-persistedstate
|
||||
License: MIT
|
||||
Repository: https://codeberg.org/praz/pinia-plugin-persistedstate
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: pinia
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/pinia
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: prettier
|
||||
License: MIT
|
||||
Repository: https://github.com/prettier/prettier
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: sass
|
||||
License: MIT
|
||||
Repository: https://github.com/sass/dart-sass
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: typescript
|
||||
License: Apache-2.0
|
||||
Repository: https://github.com/microsoft/TypeScript
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: unplugin-auto-import
|
||||
License: MIT
|
||||
Repository: https://github.com/unplugin/unplugin-auto-import
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: unplugin-vue-components
|
||||
License: MIT
|
||||
Repository: https://github.com/unplugin/unplugin-vue-components
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: uuid
|
||||
License: MIT
|
||||
Repository: https://github.com/uuidjs/uuid
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vite-plugin-lazy-import
|
||||
License: MIT
|
||||
Repository: https://github.com/x-extends/vite-plugin-lazy-import
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vite-plugin-singlefile
|
||||
License: MIT
|
||||
Repository: https://github.com/richardtallent/vite-plugin-singlefile
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vite
|
||||
License: MIT
|
||||
Repository: https://github.com/vitejs/vite
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vue-router
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/router
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vue-tsc
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/language-tools
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vue
|
||||
License: MIT
|
||||
Repository: https://github.com/vuejs/core
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vuedraggable
|
||||
License: MIT
|
||||
Repository: https://github.com/SortableJS/Vue.Draggable
|
||||
|
||||
-----------------------------
|
||||
|
||||
Name: vxe-table
|
||||
License: MIT
|
||||
Repository: https://github.com/x-extends/vxe-table
|
||||
487
web-core/README.md
Normal file
@ -0,0 +1,487 @@
|
||||
<p align="center">
|
||||
<strong>中文</strong> |
|
||||
<a href="./docs/README.en.md">English</a>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="./docs/logo.png" alt="Toonflow Logo" height="120"/>
|
||||
|
||||
# Toonflow Web
|
||||
|
||||
<p align="center">
|
||||
<b>
|
||||
Toonflow 前端应用
|
||||
<br />
|
||||
基于 Vue 3 + TypeScript + Vite 构建的现代化 Web 界面
|
||||
<br />
|
||||
AI短剧工厂的用户操作端 🎨
|
||||
</b>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/HBAI-Ltd/Toonflow-web/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/HBAI-Ltd/Toonflow-web?style=for-the-badge&logo=github" alt="Stars Badge" />
|
||||
</a>
|
||||
<a href="https://www.gnu.org/licenses/agpl-3.0" target="_blank">
|
||||
<img src="https://img.shields.io/badge/License-AGPL-blue.svg?style=for-the-badge" alt="AGPL License Badge" />
|
||||
</a>
|
||||
<a href="https://github.com/HBAI-Ltd/Toonflow-web/releases">
|
||||
<img alt="release" src="https://img.shields.io/github/v/release/HBAI-Ltd/Toonflow-web?style=for-the-badge" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
> 🎯 **现代化前端架构**:采用 Vue 3 组合式 API、TypeScript 类型安全、Vite 极速构建,打造流畅的用户体验!
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
# ⚠️ 重要提示
|
||||
|
||||
> **本仓库仅包含前端源代码,适用于开发者进行二次开发或定制。**
|
||||
>
|
||||
> 🎉 **如果您是普通用户,想要直接使用 Toonflow,请前往主仓库下载完整客户端:**
|
||||
>
|
||||
> | 平台 | 链接 |
|
||||
> | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
|
||||
> | <img src="https://img.shields.io/badge/GitHub-181717?style=flat&logo=github&logoColor=white" alt="GitHub" /> | 👉 [github.com/HBAI-Ltd/Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app) |
|
||||
> | <img src="https://img.shields.io/badge/Gitee-C71D23?style=flat&logo=gitee&logoColor=white" alt="Gitee" /> | 👉 [gitee.com/HBAI-Ltd/Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
>
|
||||
> 主仓库包含:
|
||||
>
|
||||
> - ✅ 完整的桌面客户端
|
||||
> - ✅ 后端服务
|
||||
> - ✅ 开箱即用的安装包
|
||||
> - ✅ 详细的使用教程
|
||||
|
||||
---
|
||||
|
||||
# 🌟 技术栈
|
||||
|
||||
- **框架**:Vue 3.5+ (组合式 API)
|
||||
- **构建工具**:Vite 5.4+
|
||||
- **语言**:TypeScript 5.6+
|
||||
- **状态管理**:Pinia 2.2+ (支持持久化)
|
||||
- **路由**:Vue Router 4.4+
|
||||
- **UI 组件库**:
|
||||
- Ant Design Vue 4.2+
|
||||
- Element Plus 2.13+
|
||||
- VXE Table 4.17+
|
||||
- **工具库**:
|
||||
- Axios - HTTP 请求
|
||||
- VueUse - Vue 组合式工具集
|
||||
- Day.js - 日期处理
|
||||
- Mammoth - Word 文档解析
|
||||
|
||||
---
|
||||
|
||||
# 🎨 主要功能模块
|
||||
|
||||
Toonflow Web 提供了完整的短剧创作前端界面,包含以下核心模块:
|
||||
|
||||
- ✅ **项目管理**
|
||||
创建、编辑和管理短剧项目,支持项目状态追踪和多项目并行开发。
|
||||
|
||||
- ✅ **原始文本编辑**
|
||||
导入和编辑小说原文,支持 Word 文档解析,智能文本清洗和章节分割。
|
||||
|
||||
- ✅ **角色素材库**
|
||||
管理角色设定、角色图片等素材,支持批量生成、手动上传和在线编辑。
|
||||
|
||||
- ✅ **大纲管理**
|
||||
可视化编辑故事大纲和事件线,支持拖拽排序和智能生成。
|
||||
|
||||
- ✅ **剧本编辑器**
|
||||
结构化剧本编辑界面,支持对话、场景、情绪等多维度标注。
|
||||
|
||||
- ✅ **分镜设计**
|
||||
可视化分镜画布,支持拖拽布局、图像检测和 AI 对话式分镜生成。
|
||||
|
||||
- ✅ **视频配置**
|
||||
配置视频生成参数,支持多家 AI 视频服务商切换和视频下载。
|
||||
|
||||
- ✅ **任务监控**
|
||||
实时查看 AI 生成任务进度,支持任务队列管理和历史记录查询。
|
||||
|
||||
- ✅ **系统设置**
|
||||
配置 AI 服务商、提示词模板、用户权限等系统级参数。
|
||||
|
||||
---
|
||||
|
||||
# 📦 应用场景
|
||||
|
||||
- 短剧内容创作的前端操作界面
|
||||
- AI 辅助编剧工具的可视化平台
|
||||
- 分镜设计与视频生成的工作台
|
||||
- 多人协作的剧本管理系统
|
||||
|
||||
---
|
||||
|
||||
# 🚀 快速开始
|
||||
|
||||
## 💡 您是哪类用户?
|
||||
|
||||
| 用户类型 | 推荐方案 | GitHub | Gitee |
|
||||
| ---------------------------------------------- | -------------- | -------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| 🎬 **普通用户** - 想直接使用 Toonflow 创作短剧 | 下载完整客户端 | [Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app) | [Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
| 👨💻 **开发者** - 想修改前端代码或二次开发 | 继续阅读本文档 | 本仓库 | 本仓库 |
|
||||
|
||||
---
|
||||
|
||||
## 前置条件
|
||||
|
||||
在开发和运行本项目之前,请确保已安装:
|
||||
|
||||
- ✅ **Node.js**:23.11.1 或更高版本
|
||||
- ✅ **Yarn**:1.22.0 或更高版本(推荐包管理器)
|
||||
- ✅ **后端服务**:确保 Toonflow 后端服务已启动并可访问(可从 [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) 或 [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) 获取)
|
||||
|
||||
## 本地开发
|
||||
|
||||
### 1. 克隆项目
|
||||
|
||||
**GitHub:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/HBAI-Ltd/Toonflow-web.git
|
||||
cd Toonflow-web
|
||||
```
|
||||
|
||||
**Gitee(国内推荐):**
|
||||
|
||||
```bash
|
||||
git clone https://gitee.com/HBAI-Ltd/Toonflow-web.git
|
||||
cd Toonflow-web
|
||||
```
|
||||
|
||||
### 2. 安装依赖
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### 3. 启动开发服务器
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
开发服务器默认运行在 `http://localhost:5173`,支持热模块替换(HMR)。
|
||||
|
||||
### 4. 构建生产版本
|
||||
|
||||
```bash
|
||||
# 开发环境构建
|
||||
yarn build:dev
|
||||
|
||||
# 生产环境构建
|
||||
yarn build:prod
|
||||
```
|
||||
|
||||
构建产物将输出到 `dist` 目录。
|
||||
|
||||
### 5. 预览生产构建
|
||||
|
||||
```bash
|
||||
yarn preview
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 生产部署
|
||||
|
||||
### 方式一:静态文件部署
|
||||
|
||||
1. **构建项目**
|
||||
|
||||
```bash
|
||||
yarn build:prod
|
||||
```
|
||||
|
||||
2. **部署到 Web 服务器**
|
||||
|
||||
将 `dist` 目录下的所有文件上传到 Nginx、Apache 或其他 Web 服务器的根目录。
|
||||
|
||||
**Nginx 配置示例:**
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
root /var/www/toonflow-web/dist;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API 代理(可选)
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:10588/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 方式二:与后端集成部署
|
||||
|
||||
将构建后的 `dist` 目录内容复制到后端的静态资源目录 `scripts/web` 中。
|
||||
|
||||
> 💡 **提示**:后端服务可从 [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) 或 [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) 仓库获取。
|
||||
|
||||
---
|
||||
|
||||
# 🔧 开发指南
|
||||
|
||||
## 开发环境准备
|
||||
|
||||
- **Node.js**:版本要求 23.11.1 及以上
|
||||
- **Yarn**:推荐作为项目包管理器
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
yarn install
|
||||
|
||||
# 启动开发服务器(支持热更新)
|
||||
yarn dev
|
||||
|
||||
# 类型检查
|
||||
yarn type-check
|
||||
|
||||
# 代码检查和自动修复
|
||||
yarn lint
|
||||
|
||||
# 代码格式化
|
||||
yarn format
|
||||
|
||||
# 构建开发版本
|
||||
yarn build:dev
|
||||
|
||||
# 构建生产版本
|
||||
yarn build:prod
|
||||
|
||||
# 预览生产构建
|
||||
yarn preview
|
||||
|
||||
# 生成第三方许可证清单
|
||||
yarn license
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
📂 Toonflow-web/
|
||||
├─ 📂 public/ # 静态资源
|
||||
├─ 📂 scripts/ # 构建脚本
|
||||
│ └─ 📄 license.ts # 许可证生成脚本
|
||||
├─ 📂 src/
|
||||
│ ├─ 📂 assets/ # 静态资源(样式、图片等)
|
||||
│ │ └─ 📄 main.css # 全局样式
|
||||
│ ├─ 📂 components/ # 公共组件
|
||||
│ │ ├─ 📄 sider.vue # 侧边栏组件
|
||||
│ │ ├─ 📂 chat/ # 聊天组件
|
||||
│ │ ├─ 📂 storyboardEditor/ # 分镜编辑器
|
||||
│ │ └─ 📂 videoConfig/ # 视频配置组件
|
||||
│ ├─ 📂 config/ # 配置文件
|
||||
│ │ └─ 📄 manufacturerConfig.ts # 厂商配置
|
||||
│ ├─ 📂 pages/ # 页面组件
|
||||
│ │ ├─ 📂 error/ # 错误页面
|
||||
│ │ ├─ 📂 login/ # 登录页面
|
||||
│ │ └─ 📂 workbench/ # 工作台
|
||||
│ ├─ 📂 router/ # 路由配置
|
||||
│ │ └─ 📄 index.ts # 路由定义
|
||||
│ ├─ 📂 stores/ # Pinia 状态管理
|
||||
│ │ ├─ 📄 index.ts # Store 入口
|
||||
│ │ ├─ 📄 loadingStore.ts # 加载状态
|
||||
│ │ ├─ 📄 user.ts # 用户状态
|
||||
│ │ └─ 📄 video.ts # 视频状态
|
||||
│ ├─ 📂 types/ # TypeScript 类型定义
|
||||
│ │ ├─ 📄 auto-imports.d.ts # 自动导入类型
|
||||
│ │ ├─ 📄 components.d.ts # 组件类型
|
||||
│ │ ├─ 📄 global.d.ts # 全局类型
|
||||
│ │ ├─ 📄 manufacturer.ts # 厂商类型
|
||||
│ │ └─ 📄 shims-vue.d.ts # Vue 模块声明
|
||||
│ ├─ 📂 utils/ # 工具函数
|
||||
│ │ ├─ 📄 axios.ts # HTTP 请求封装
|
||||
│ │ ├─ 📄 combineImages.ts # 图片合成
|
||||
│ │ ├─ 📄 error.ts # 错误处理
|
||||
│ │ ├─ 📄 parseNovel.ts # 小说解析
|
||||
│ │ ├─ 📄 splitGraph.ts # 图像分割
|
||||
│ │ ├─ 📄 throttle.ts # 节流防抖
|
||||
│ │ └─ 📄 wsClient.ts # WebSocket 客户端
|
||||
│ ├─ 📂 views/ # 视图页面
|
||||
│ │ ├─ 📂 project/ # 项目管理
|
||||
│ │ ├─ 📂 projectDetail/ # 项目详情
|
||||
│ │ │ ├─ 📂 components/
|
||||
│ │ │ │ ├─ 📂 assetsManager/ # 素材管理
|
||||
│ │ │ │ ├─ 📂 originalText/ # 原始文本
|
||||
│ │ │ │ ├─ 📂 outlineManager/ # 大纲管理
|
||||
│ │ │ │ ├─ 📂 overview/ # 项目概览
|
||||
│ │ │ │ └─ 📂 scriptManager/ # 剧本管理
|
||||
│ │ ├─ 📂 setting/ # 系统设置
|
||||
│ │ └─ 📂 taskList/ # 任务列表
|
||||
│ ├─ 📄 App.vue # 根组件
|
||||
│ └─ 📄 main.ts # 应用入口
|
||||
├─ 📄 components.d.ts # 全局组件类型
|
||||
├─ 📄 eslint.config.js # ESLint 配置
|
||||
├─ 📄 index.html # HTML 模板
|
||||
├─ 📄 package.json # 项目配置
|
||||
├─ 📄 tsconfig.json # TypeScript 配置
|
||||
├─ 📄 tsconfig.app.json # 应用 TS 配置
|
||||
├─ 📄 tsconfig.node.json # Node TS 配置
|
||||
├─ 📄 vite.config.ts # Vite 配置
|
||||
├─ 📄 LICENSE # 许可证
|
||||
├─ 📄 NOTICES.txt # 第三方依赖声明
|
||||
└─ 📄 README.md # 项目说明
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 📝 开发计划
|
||||
|
||||
我们正持续优化前端体验,以下为近期开发重点:
|
||||
|
||||
1. **UI/UX 优化**
|
||||
- `🎨 暗色主题支持` 提供优雅的暗色模式选项,保护用户视力
|
||||
- `📱 响应式布局` 优化移动端和平板设备的显示效果
|
||||
- `⌨️ 快捷键系统` 添加常用操作的快捷键,提升操作效率
|
||||
|
||||
2. **功能增强**
|
||||
- `📊 数据可视化` 增强项目数据统计和可视化图表展示
|
||||
- `🔄 实时协作` 支持多人同时编辑,实时同步状态
|
||||
- `💾 自动保存` 智能自动保存功能,防止数据丢失
|
||||
|
||||
3. **性能优化**
|
||||
- `⚡ 虚拟滚动` 大数据列表的性能优化
|
||||
- `🗜️ 资源压缩` 优化构建产物体积,提升加载速度
|
||||
- `🔌 懒加载优化` 进一步优化路由和组件的懒加载策略
|
||||
|
||||
---
|
||||
|
||||
# 🐛 常见问题
|
||||
|
||||
### Q: 启动开发服务器时端口被占用?
|
||||
|
||||
**A:** 修改 `vite.config.ts` 中的端口配置:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: 3000, // 修改为其他端口
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Q: 如何配置后端 API 地址?
|
||||
|
||||
**A:** 在 `.env.dev` 中配置后端地址:
|
||||
|
||||
```bash
|
||||
VITE_TYPE=dev
|
||||
VITE_BASE_URL=http://127.0.0.1:10588
|
||||
VITE_WS_URL=ws://127.0.0.1:10588
|
||||
```
|
||||
|
||||
### Q: 我只想使用 Toonflow,不需要开发,怎么办?
|
||||
|
||||
**A:** 请前往主仓库下载完整客户端:
|
||||
|
||||
- **GitHub**:👉 [Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app)
|
||||
- **Gitee**:👉 [Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app)
|
||||
|
||||
---
|
||||
|
||||
# 🔗 相关仓库
|
||||
|
||||
| 仓库 | 说明 | GitHub | Gitee |
|
||||
| ---------------- | -------------------------------- | -------------------------------------------------- | ------------------------------------------------ |
|
||||
| **Toonflow-app** | 完整客户端(推荐普通用户) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
| **Toonflow-web** | 前端源代码(本仓库,适合开发者) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) |
|
||||
|
||||
---
|
||||
|
||||
# 👨👩👧👦 微信交流群
|
||||
|
||||
请到主仓库中查看
|
||||
|
||||
- **GitHub**:👉 [Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app)
|
||||
- **Gitee**:👉 [Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app)
|
||||
|
||||
---
|
||||
|
||||
# 💌 联系我们
|
||||
|
||||
📧 邮箱:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow前端咨询)
|
||||
|
||||
---
|
||||
|
||||
# 📜 许可证
|
||||
|
||||
Toonflow 基于 Apache-2.0 协议开源发布,并附有补充商业协议。
|
||||
|
||||
许可证详情:https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
## 补充协议
|
||||
|
||||
- 若将本软件以产品形式分发给 **2 个及以上独立第三方**使用,须取得 HBAI-Ltd **书面商业授权**。
|
||||
- **≤ 5 个法人**联合运营内部使用,不对外提供服务的,视为内部使用,**无需授权**。
|
||||
- 不得删除或修改 Toonflow 中的标识或版权信息。
|
||||
|
||||
## 永久免费场景
|
||||
|
||||
- ✅ 用 Toonflow 制作内容并获得平台分账
|
||||
- ✅ 二次开发供自己团队内部使用
|
||||
- ✅ ≤ 5 个法人联合运营内部使用
|
||||
- ✅ 个人学习、研究、非商业用途
|
||||
|
||||
## 商业授权定价
|
||||
|
||||
| 阶段 | 年销售额 | 年费 |
|
||||
|------|---------|------|
|
||||
| 🌱 扶持期 | < ¥10 万 | **申请即可免费授权** |
|
||||
| 🚀 初创期 | ¥10–50 万 | ¥5,000/年 |
|
||||
| 📈 成长期 | ¥50–150 万 | ¥20,000/年 |
|
||||
| 🏢 规模期 | ¥150–500 万 | ¥80,000/年 |
|
||||
| 🌐 企业级 | > ¥500 万 | 面议 |
|
||||
|
||||
> **不追溯条款**:v1.0.8 发布前基于 AGPL-3.0 使用的用户,继续按 AGPL-3.0 执行,不受本协议变更约束。
|
||||
|
||||
完整协议详见 [LICENSE](./LICENSE) 文件。
|
||||
---
|
||||
|
||||
# ⭐️ 星标历史
|
||||
|
||||
[](https://www.star-history.com/#HBAI-Ltd/Toonflow-web&type=date&legend=top-left)
|
||||
|
||||
---
|
||||
|
||||
# 🙏 致谢
|
||||
|
||||
感谢以下开源项目为 Toonflow Web 提供强大支持:
|
||||
|
||||
- [Vue.js](https://vuejs.org/) - 渐进式 JavaScript 框架
|
||||
- [Vite](https://vitejs.dev/) - 下一代前端构建工具
|
||||
- [Ant Design Vue](https://antdv.com/) - 企业级 UI 组件库
|
||||
- [Element Plus](https://element-plus.org/) - 基于 Vue 3 的组件库
|
||||
- [TDesign](https://element-plus.org/) - 为设计师 & 开发者,打造工作美学
|
||||
- [Pinia](https://pinia.vuejs.org/) - Vue 的直观状态管理库
|
||||
|
||||
感谢以下组织/单位/个人为 Toonflow 提供支持:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="./docs/sponsored/sophnet.png" alt="算能云 Logo" width="48">
|
||||
</td>
|
||||
<td>
|
||||
<b>算能云</b> 提供算力赞助
|
||||
<a href="https://www.sophnet.com/">[官网]</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
完整的第三方依赖清单请查阅 `NOTICES.txt`
|
||||
|
||||
##### copyright © 北京爱阿科技有限公司
|
||||
54
web-core/components.d.ts
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
|
||||
export {};
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACheckableTag: typeof import('ant-design-vue/es')['CheckableTag']
|
||||
ACollapse: typeof import('ant-design-vue/es')['Collapse']
|
||||
ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
|
||||
ADivider: typeof import('ant-design-vue/es')['Divider']
|
||||
AImage: typeof import('ant-design-vue/es')['Image']
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||
AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
|
||||
ALayout: typeof import('ant-design-vue/es')['Layout']
|
||||
ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
|
||||
ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
|
||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||
AProgress: typeof import('ant-design-vue/es')['Progress']
|
||||
ARadio: typeof import('ant-design-vue/es')['Radio']
|
||||
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
ASteps: typeof import('ant-design-vue/es')['Steps']
|
||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
|
||||
BlurReveal: typeof import('./src/components/BlurReveal.vue')['default']
|
||||
Book: typeof import('./src/components/book/Book.vue')['default']
|
||||
BookDescription: typeof import('./src/components/book/BookDescription.vue')['default']
|
||||
BookHeader: typeof import('./src/components/book/BookHeader.vue')['default']
|
||||
BookTitle: typeof import('./src/components/book/BookTitle.vue')['default']
|
||||
ColourfulText: typeof import('./src/components/ColourfulText.vue')['default']
|
||||
FileUpload: typeof import('./src/components/fileUpload/FileUpload.vue')['default']
|
||||
FileUploadGrid: typeof import('./src/components/fileUpload/FileUploadGrid.vue')['default']
|
||||
MultiStepLoader: typeof import('./src/components/MultiStepLoader.vue')['default']
|
||||
NewAndEdit: typeof import('./src/components/newAndEdit/index.vue')['default']
|
||||
RainbowButton: typeof import('./src/components/RainbowButton.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Sider: typeof import('./src/components/sider.vue')['default']
|
||||
}
|
||||
}
|
||||
470
web-core/docs/README.en.md
Normal file
@ -0,0 +1,470 @@
|
||||
<p align="center">
|
||||
<a href="../README.md">中文</a> |
|
||||
<strong>English</strong>
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="./logo.png" alt="Toonflow Logo" height="120"/>
|
||||
|
||||
# Toonflow Web
|
||||
|
||||
<p align="center">
|
||||
<b>
|
||||
Toonflow Frontend Application
|
||||
<br />
|
||||
Modern Web interface built with Vue 3 + TypeScript + Vite
|
||||
<br />
|
||||
User frontend for AI Short Drama Factory 🎨
|
||||
</b>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/HBAI-Ltd/Toonflow-web/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/HBAI-Ltd/Toonflow-web?style=for-the-badge&logo=github" alt="Stars Badge" />
|
||||
</a>
|
||||
<a href="https://www.gnu.org/licenses/agpl-3.0" target="_blank">
|
||||
<img src="https://img.shields.io/badge/License-AGPL-blue.svg?style=for-the-badge" alt="AGPL License Badge" />
|
||||
</a>
|
||||
<a href="https://github.com/HBAI-Ltd/Toonflow-web/releases">
|
||||
<img alt="release" src="https://img.shields.io/github/v/release/HBAI-Ltd/Toonflow-web?style=for-the-badge" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
> 🎯 **Modern Frontend Architecture**: Built with Vue 3 Composition API, TypeScript type safety, and Vite for lightning-fast builds, delivering a smooth user experience!
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
# ⚠️ Important Notice
|
||||
|
||||
> **This repository only contains the frontend source code, suitable for developers for secondary development or customization.**
|
||||
>
|
||||
> 🎉 **If you are a regular user wishing to use Toonflow directly, please go to the main repository to download the full client:**
|
||||
>
|
||||
> | Platform | Link |
|
||||
> | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
|
||||
> | <img src="https://img.shields.io/badge/GitHub-181717?style=flat&logo=github&logoColor=white" alt="GitHub" /> | 👉 [github.com/HBAI-Ltd/Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app) |
|
||||
> | <img src="https://img.shields.io/badge/Gitee-C71D23?style=flat&logo=gitee&logoColor=white" alt="Gitee" /> | 👉 [gitee.com/HBAI-Ltd/Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
>
|
||||
> The main repository includes:
|
||||
>
|
||||
> - ✅ Complete desktop client
|
||||
> - ✅ Backend service
|
||||
> - ✅ Ready-to-use installer
|
||||
> - ✅ Detailed usage tutorial
|
||||
|
||||
---
|
||||
|
||||
# 🌟 Tech Stack
|
||||
|
||||
- **Framework**: Vue 3.5+ (Composition API)
|
||||
- **Build Tool**: Vite 5.4+
|
||||
- **Language**: TypeScript 5.6+
|
||||
- **State Management**: Pinia 2.2+ (supports persistence)
|
||||
- **Routing**: Vue Router 4.4+
|
||||
- **UI Component Libraries**:
|
||||
- Ant Design Vue 4.2+
|
||||
- Element Plus 2.13+
|
||||
- VXE Table 4.17+
|
||||
- **Utility Libraries**:
|
||||
- Axios - HTTP requests
|
||||
- VueUse - Vue composition utilities
|
||||
- Day.js - Date handling
|
||||
- Mammoth - Word document parsing
|
||||
|
||||
---
|
||||
|
||||
# 🎨 Main Feature Modules
|
||||
|
||||
Toonflow Web provides a complete frontend for short drama creation, including these core modules:
|
||||
|
||||
- ✅ **Project Management**
|
||||
Create, edit, and manage drama projects with project status tracking and multi-project parallel development.
|
||||
|
||||
- ✅ **Raw Text Editing**
|
||||
Import and edit novel manuscripts, supports Word document parsing, intelligent text cleansing, and chapter splitting.
|
||||
|
||||
- ✅ **Character Asset Library**
|
||||
Manage character settings and images; supports batch generation, manual upload, and online editing.
|
||||
|
||||
- ✅ **Outline Management**
|
||||
Visual editing of story outlines and event lines, with drag-and-drop sorting and smart generation.
|
||||
|
||||
- ✅ **Script Editor**
|
||||
Structured script editing interface, supports labeling dialogues, scenes, emotions, and more dimensions.
|
||||
|
||||
- ✅ **Storyboard Design**
|
||||
Visual storyboard canvas with drag-and-drop layout, image detection, and AI conversational storyboard generation.
|
||||
|
||||
- ✅ **Video Configuration**
|
||||
Configure video generation parameters, support switching among multiple AI video providers, and video downloading.
|
||||
|
||||
- ✅ **Task Monitoring**
|
||||
Real-time monitoring of AI generation tasks, supports task queue management and history search.
|
||||
|
||||
- ✅ **System Settings**
|
||||
Configure AI providers, prompt templates, user permissions, and other system-level parameters.
|
||||
|
||||
---
|
||||
|
||||
# 📦 Application Scenarios
|
||||
|
||||
- Frontend operation interface for short drama content creation
|
||||
- Visual platform for AI-assisted screenwriting tools
|
||||
- Workbench for storyboard design and video generation
|
||||
- Scenario management system for multi-user collaboration
|
||||
|
||||
---
|
||||
|
||||
# 🚀 Getting Started Quickly
|
||||
|
||||
## 💡 What kind of user are you?
|
||||
|
||||
| User Type | Recommended Solution | GitHub | Gitee |
|
||||
| ------------------------------------------- | -------------------- | -------------------------------------------------------- | ------------------------------------------------------- |
|
||||
| 🎬 **Regular User** - Want to use Toonflow | Download full client | [Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app) | [Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
| 👨💻 **Developer** - Want to modify or extend | Continue reading | This repository | This repository |
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before developing and running this project, please ensure you have installed:
|
||||
|
||||
- ✅ **Node.js**: version 23.11.1 or above
|
||||
- ✅ **Yarn**: version 1.22.0 or above (recommended package manager)
|
||||
- ✅ **Backend service**: Make sure the Toonflow backend service is running and accessible (available from [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) or [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app))
|
||||
|
||||
## Local Development
|
||||
|
||||
### 1. Clone the Project
|
||||
|
||||
**GitHub:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/HBAI-Ltd/Toonflow-web.git
|
||||
cd Toonflow-web
|
||||
```
|
||||
|
||||
**Gitee (recommended for China):**
|
||||
|
||||
```bash
|
||||
git clone https://gitee.com/HBAI-Ltd/Toonflow-web.git
|
||||
cd Toonflow-web
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### 3. Start the Development Server
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
The dev server runs at `http://localhost:5173` by default, with hot module replacement (HMR) enabled.
|
||||
|
||||
### 4. Build for Production
|
||||
|
||||
```bash
|
||||
# Development build
|
||||
yarn build:dev
|
||||
|
||||
# Production build
|
||||
yarn build:prod
|
||||
```
|
||||
|
||||
The build output will be in the `dist` directory.
|
||||
|
||||
### 5. Preview Production Build
|
||||
|
||||
```bash
|
||||
yarn preview
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Method 1: Static File Deployment
|
||||
|
||||
1. **Build the Project**
|
||||
|
||||
```bash
|
||||
yarn build:prod
|
||||
```
|
||||
|
||||
2. **Deploy to Web Server**
|
||||
|
||||
Upload all files in the `dist` directory to the root directory of Nginx, Apache, or any other web server.
|
||||
|
||||
**Sample Nginx configuration:**
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
root /var/www/toonflow-web/dist;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API Proxy (optional)
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:10588/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Method 2: Integrated deployment with backend
|
||||
|
||||
Copy the contents of the built `dist` directory into the backend's static resources directory `scripts/web`.
|
||||
|
||||
> 💡 **Note**: The backend service can be obtained from [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) or [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app).
|
||||
|
||||
---
|
||||
|
||||
# 🔧 Development Guide
|
||||
|
||||
## Prepare Development Environment
|
||||
|
||||
- **Node.js**: version 23.11.1 or above required
|
||||
- **Yarn**: recommended package manager
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
yarn install
|
||||
|
||||
# Start development server (supports hot reload)
|
||||
yarn dev
|
||||
|
||||
# Type checking
|
||||
yarn type-check
|
||||
|
||||
# Code linting and auto-fix
|
||||
yarn lint
|
||||
|
||||
# Code formatting
|
||||
yarn format
|
||||
|
||||
# Development build
|
||||
yarn build:dev
|
||||
|
||||
# Production build
|
||||
yarn build:prod
|
||||
|
||||
# Preview production build
|
||||
yarn preview
|
||||
|
||||
# Generate third-party license list
|
||||
yarn license
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
📂 Toonflow-web/
|
||||
├─ 📂 public/ # Static assets
|
||||
├─ 📂 scripts/ # Build scripts
|
||||
│ └─ 📄 license.ts # License generator script
|
||||
├─ 📂 src/
|
||||
│ ├─ 📂 assets/ # Static assets (styles, images, etc.)
|
||||
│ │ └─ 📄 main.css # Global styles
|
||||
│ ├─ 📂 components/ # Common components
|
||||
│ │ ├─ 📄 sider.vue # Sidebar component
|
||||
│ │ ├─ 📂 chat/ # Chat components
|
||||
│ │ ├─ 📂 storyboardEditor/ # Storyboard editor
|
||||
│ │ └─ 📂 videoConfig/ # Video config components
|
||||
│ ├─ 📂 config/ # Configuration files
|
||||
│ │ └─ 📄 manufacturerConfig.ts # Manufacturer configuration
|
||||
│ ├─ 📂 pages/ # Page components
|
||||
│ │ ├─ 📂 error/ # Error pages
|
||||
│ │ ├─ 📂 login/ # Login page
|
||||
│ │ └─ 📂 workbench/ # Workbench
|
||||
│ ├─ 📂 router/ # Routing configuration
|
||||
│ │ └─ 📄 index.ts # Route definitions
|
||||
│ ├─ 📂 stores/ # Pinia state management
|
||||
│ │ ├─ 📄 index.ts # Store entry
|
||||
│ │ ├─ 📄 loadingStore.ts # Loading state
|
||||
│ │ ├─ 📄 user.ts # User state
|
||||
│ │ └─ 📄 video.ts # Video state
|
||||
│ ├─ 📂 types/ # TypeScript type definitions
|
||||
│ │ ├─ 📄 auto-imports.d.ts # Auto-imported types
|
||||
│ │ ├─ 📄 components.d.ts # Component types
|
||||
│ │ ├─ 📄 global.d.ts # Global types
|
||||
│ │ ├─ 📄 manufacturer.ts # Manufacturer types
|
||||
│ │ └─ 📄 shims-vue.d.ts # Vue module declarations
|
||||
│ ├─ 📂 utils/ # Utility functions
|
||||
│ │ ├─ 📄 axios.ts # HTTP request wrapper
|
||||
│ │ ├─ 📄 combineImages.ts # Image composition
|
||||
│ │ ├─ 📄 error.ts # Error handling
|
||||
│ │ ├─ 📄 parseNovel.ts # Novel parsing
|
||||
│ │ ├─ 📄 splitGraph.ts # Image segmentation
|
||||
│ │ ├─ 📄 throttle.ts # Throttling/debouncing
|
||||
│ │ └─ 📄 wsClient.ts # WebSocket client
|
||||
│ ├─ 📂 views/ # View pages
|
||||
│ │ ├─ 📂 project/ # Project management
|
||||
│ │ ├─ 📂 projectDetail/ # Project details
|
||||
│ │ │ ├─ 📂 components/
|
||||
│ │ │ │ ├─ 📂 assetsManager/ # Asset management
|
||||
│ │ │ │ ├─ 📂 originalText/ # Raw text
|
||||
│ │ │ │ ├─ 📂 outlineManager/ # Outline management
|
||||
│ │ │ │ ├─ 📂 overview/ # Project overview
|
||||
│ │ │ │ └─ 📂 scriptManager/ # Script management
|
||||
│ │ ├─ 📂 setting/ # System settings
|
||||
│ │ └─ 📂 taskList/ # Task list
|
||||
│ ├─ 📄 App.vue # Root component
|
||||
│ └─ 📄 main.ts # App entry point
|
||||
├─ 📄 components.d.ts # Global component types
|
||||
├─ 📄 eslint.config.js # ESLint config
|
||||
├─ 📄 index.html # HTML template
|
||||
├─ 📄 package.json # Project config
|
||||
├─ 📄 tsconfig.json # TypeScript config
|
||||
├─ 📄 tsconfig.app.json # App TS config
|
||||
├─ 📄 tsconfig.node.json # Node TS config
|
||||
├─ 📄 vite.config.ts # Vite config
|
||||
├─ 📄 LICENSE # License
|
||||
├─ 📄 NOTICES.txt # Third-party notices
|
||||
└─ 📄 README.md # Project documentation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 📝 Development Plan
|
||||
|
||||
We are continuously optimizing the frontend experience. Key development focuses in the near future:
|
||||
|
||||
1. **UI/UX Optimization**
|
||||
- `🎨 Dark theme support` Elegant dark mode option to protect eyesight
|
||||
- `📱 Responsive layout` Improved display for mobile and tablet devices
|
||||
- `⌨️ Shortcut system` Adding shortcuts for common operations to improve efficiency
|
||||
|
||||
2. **Feature Enhancements**
|
||||
- `📊 Data visualization` Advanced project statistics and chart displays
|
||||
- `🔄 Real-time collaboration` Multi-user simultaneous editing and real-time sync
|
||||
- `💾 Auto-save` Smart auto-save to prevent data loss
|
||||
|
||||
3. **Performance Optimization**
|
||||
- `⚡ Virtual scrolling` High-performance optimization for large lists
|
||||
- `🗜️ Asset compression` Optimizing build size for faster loading
|
||||
- `🔌 Lazy loading optimization` Further optimize route and component lazy loading strategy
|
||||
|
||||
---
|
||||
|
||||
# 🐛 FAQ
|
||||
|
||||
### Q: Port is occupied when starting dev server?
|
||||
|
||||
**A:** Modify the port configuration in `vite.config.ts`:
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: 3000, // change to another port
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Q: How to configure the backend API address?
|
||||
|
||||
**A:** Set the backend address in `.env.dev`:
|
||||
|
||||
```bash
|
||||
VITE_TYPE=dev
|
||||
VITE_BASE_URL=http://127.0.0.1:10588
|
||||
VITE_WS_URL=ws://127.0.0.1:10588
|
||||
```
|
||||
|
||||
### Q: I just want to use Toonflow, not develop, what should I do?
|
||||
|
||||
**A:** Please go to the main repository to download the complete client:
|
||||
|
||||
- **GitHub**: 👉 [Toonflow-app](https://github.com/HBAI-Ltd/Toonflow-app)
|
||||
- **Gitee**: 👉 [Toonflow-app](https://gitee.com/HBAI-Ltd/Toonflow-app)
|
||||
|
||||
---
|
||||
|
||||
# 🔗 Related Repositories
|
||||
|
||||
| Repository | Description | GitHub | Gitee |
|
||||
| ---------------- | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ |
|
||||
| **Toonflow-app** | Complete client (recommended user) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) |
|
||||
| **Toonflow-web** | Frontend source code (this repo) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) |
|
||||
|
||||
---
|
||||
|
||||
# 👨👩👧👦 WeChat Community Group
|
||||
|
||||
~~Group 1~~
|
||||
|
||||
~~Group 2~~
|
||||
|
||||
~~Group 3~~
|
||||
|
||||
~~Group 4~~
|
||||
|
||||
~~Group 5~~
|
||||
|
||||
Group 6:
|
||||
|
||||
<img src="./chat6QR.jpg" alt="Toonflow Logo" height="400"/>
|
||||
<p>Scan with WeChat to add. If the QR code expires, submit an Issue for update.</p>
|
||||
|
||||
---
|
||||
|
||||
# 💌 Contact Us
|
||||
|
||||
📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow%20Frontend%20Consultation)
|
||||
|
||||
---
|
||||
|
||||
# 📜 License
|
||||
|
||||
Toonflow Web is open-sourced under the AGPL-3.0 license. See details: https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
You may use Toonflow Web for any purposes, including commercial, as long as you comply with the AGPL-3.0 terms and conditions.
|
||||
|
||||
If you wish to obtain a proprietary commercial license free from AGPL-3.0 restrictions, please contact us via email.
|
||||
|
||||
---
|
||||
|
||||
# ⭐️ Star History
|
||||
|
||||
[](https://www.star-history.com/#HBAI-Ltd/Toonflow-web&type=date&legend=top-left)
|
||||
|
||||
---
|
||||
|
||||
# 🙏 Acknowledgements
|
||||
|
||||
Thanks to the following open source projects for their strong support for Toonflow Web:
|
||||
|
||||
- [Vue.js](https://vuejs.org/) - Progressive JavaScript framework
|
||||
- [Vite](https://vitejs.dev/) - Next generation frontend build tool
|
||||
- [Ant Design Vue](https://antdv.com/) - Enterprise-level UI component library
|
||||
- [Element Plus](https://element-plus.org/) - Vue 3-based component library
|
||||
- [Pinia](https://pinia.vuejs.org/) - Intuitive state management library for Vue
|
||||
|
||||
Thanks to the following organizations/units/individuals for supporting Toonflow:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="./sponsored/sophnet.png" alt="Suan Neng Yun Logo" width="48">
|
||||
</td>
|
||||
<td>
|
||||
<b>Suan Neng Yun</b> provides compute sponsorship
|
||||
<a href="https://www.sophnet.com/">[Official Site]</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
For a complete list of third-party dependencies, please refer to `NOTICES.txt`
|
||||
BIN
web-core/docs/logo.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
web-core/docs/sponsored/sophnet.png
Normal file
|
After Width: | Height: | Size: 758 B |
BIN
web-core/docs/videoCover.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
web-core/docs/videoQR.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
13
web-core/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Toonflow</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
67
web-core/package.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "toonflow_web",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"preview": "vite preview",
|
||||
"build": "vue-tsc --build --force && vite build",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"license": "node scripts/license.ts",
|
||||
"i18n:check": "node scripts/findUnusedI18n.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dagrejs/dagre": "^3.0.0",
|
||||
"@devui-design/icons": "^1.4.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@tdesign-vue-next/chat": "^0.5.1",
|
||||
"@vue-flow/background": "^1.3.2",
|
||||
"@vue-flow/controls": "^1.1.3",
|
||||
"@vue-flow/core": "^1.48.2",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"@webav/av-canvas": "^1.2.8",
|
||||
"@webav/av-cliper": "^1.2.8",
|
||||
"axios": "^1.13.2",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.19",
|
||||
"js-confetti": "^0.13.1",
|
||||
"lodash": "^4.17.23",
|
||||
"mammoth": "^1.12.0",
|
||||
"md-editor-v3": "^6.4.0",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"monaco-editor-vue3": "^1.0.5",
|
||||
"p-limit": "^7.3.0",
|
||||
"pinia": "^2.2.6",
|
||||
"pinia-plugin-persistedstate": "^4.7.1",
|
||||
"sass": "^1.97.0",
|
||||
"socket.io-client": "^4.8.3",
|
||||
"splitpanes": "^4.0.4",
|
||||
"tdesign-vue-next": "^1.18.5",
|
||||
"uuid": "^13.0.0",
|
||||
"vue": "^3.5.12",
|
||||
"vue-clip-track": "^0.1.5",
|
||||
"vue-draggable-plus": "^0.6.1",
|
||||
"vue-i18n": "11",
|
||||
"vue-router": "^4.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tdesign-vue-next/auto-import-resolver": "^0.1.6",
|
||||
"@tsconfig/node22": "^22.0.0",
|
||||
"@types/license-checker": "^25.0.6",
|
||||
"@types/node": "^22.9.0",
|
||||
"@types/splitpanes": "^2.2.6",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"@vitejs/plugin-vue": "^6.0.5",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"license-checker": "^25.0.1",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "~5.6.3",
|
||||
"unplugin-auto-import": "^21.0.0",
|
||||
"unplugin-vue-components": "^31.0.0",
|
||||
"vite": "^5.4.10",
|
||||
"vite-plugin-singlefile": "^2.3.0",
|
||||
"vue-tsc": "^2.1.10"
|
||||
}
|
||||
}
|
||||
BIN
web-core/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 169 KiB |
32
web-core/public/favicon.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="ToonFlow logo">
|
||||
<defs>
|
||||
<linearGradient id="tf-stem" x1="24" y1="24" x2="96" y2="98" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#64e1d3"/>
|
||||
<stop offset="0.58" stop-color="#8ea3ff"/>
|
||||
<stop offset="1" stop-color="#ffb46b"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="tf-play" x1="63" y1="42" x2="92" y2="82" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ffffff"/>
|
||||
<stop offset="1" stop-color="#dffdf7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="128" height="128" rx="30" fill="#101828"/>
|
||||
<path
|
||||
fill="url(#tf-stem)"
|
||||
d="M28 24h72c5.52 0 10 4.48 10 10v4c0 5.52-4.48 10-10 10H74v49c0 5.52-4.48 10-10 10H52c-5.52 0-10-4.48-10-10V48H28c-5.52 0-10-4.48-10-10v-4c0-5.52 4.48-10 10-10Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#tf-stem)"
|
||||
opacity=".9"
|
||||
d="M42 74h56c6.63 0 12 5.37 12 12v2c0 6.63-5.37 12-12 12H42V74Z"
|
||||
/>
|
||||
<path
|
||||
fill="#142133"
|
||||
fill-opacity=".25"
|
||||
d="M31 32h10a4 4 0 0 1 0 8H31a4 4 0 0 1 0-8Zm44 50h14a4 4 0 0 1 0 8H75a4 4 0 0 1 0-8Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#tf-play)"
|
||||
d="M68.4 47.58c-3.32-2.09-7.65.3-7.65 4.22v32.4c0 3.92 4.33 6.31 7.65 4.22l25.7-16.2c3.1-1.95 3.1-6.49 0-8.44l-25.7-16.2Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
311
web-core/scripts/findUnusedI18n.ts
Normal file
@ -0,0 +1,311 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// 配置
|
||||
const localesDir = './src/locales/language';
|
||||
const srcDir = './src';
|
||||
|
||||
// 递归获取文件
|
||||
function getFiles(dir: string, extensions: string[]): string[] {
|
||||
const files: string[] = [];
|
||||
|
||||
function walk(currentDir: string): void {
|
||||
const items = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(currentDir, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
if (!['node_modules', 'dist', '.git', 'locales'].includes(item.name)) {
|
||||
walk(fullPath);
|
||||
}
|
||||
} else if (item.isFile()) {
|
||||
const ext = path.extname(item.name);
|
||||
if (extensions.includes(ext)) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(dir);
|
||||
return files;
|
||||
}
|
||||
|
||||
// 获取所有 i18n key
|
||||
function getAllI18nKeys(): Set<string> {
|
||||
const keys = new Set<string>();
|
||||
const files = getFiles(localesDir, ['.json']);
|
||||
|
||||
files.forEach(file => {
|
||||
const content = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
||||
extractKeys(content, '', keys);
|
||||
});
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
function extractKeys(obj: Record<string, unknown>, prefix: string, keys: Set<string>): void {
|
||||
for (const key in obj) {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key;
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
extractKeys(obj[key] as Record<string, unknown>, fullKey, keys);
|
||||
} else {
|
||||
keys.add(fullKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断字符串是否像 i18n key
|
||||
function looksLikeI18nKey(str: string): boolean {
|
||||
if (!str.includes('.')) return false;
|
||||
if (str.startsWith('http')) return false;
|
||||
if (str.includes('/')) return false;
|
||||
if (str.includes(' ')) return false;
|
||||
if (/^\d/.test(str)) return false;
|
||||
if (str.includes('@')) return false;
|
||||
return /^[a-zA-Z][a-zA-Z0-9]*(\.[a-zA-Z][a-zA-Z0-9]*)+$/.test(str);
|
||||
}
|
||||
|
||||
// 扫描源码中使用的 key
|
||||
function getUsedKeys(allKeys: Set<string>): Set<string> {
|
||||
const used = new Set<string>();
|
||||
const files = getFiles(srcDir, ['.vue', '.js', '.ts', '.jsx', '.tsx']);
|
||||
|
||||
const patterns = [
|
||||
/\$t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/\bt\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/i18n\.t\s*\(\s*['"`]([^'"`]+)['"`]/g,
|
||||
/label:\s*['"`]([^'"`]+)['"`]/g,
|
||||
/title:\s*['"`]([^'"`]+)['"`]/g,
|
||||
/placeholder:\s*['"`]([^'"`]+)['"`]/g,
|
||||
/message:\s*['"`]([^'"`]+)['"`]/g,
|
||||
/text:\s*['"`]([^'"`]+)['"`]/g,
|
||||
];
|
||||
|
||||
files.forEach(file => {
|
||||
const content = fs.readFileSync(file, 'utf-8');
|
||||
|
||||
patterns.forEach(pattern => {
|
||||
let match;
|
||||
pattern.lastIndex = 0;
|
||||
while ((match = pattern.exec(content)) !== null) {
|
||||
used.add(match[1]);
|
||||
}
|
||||
});
|
||||
|
||||
allKeys.forEach(key => {
|
||||
if (
|
||||
content.includes(`'${key}'`) ||
|
||||
content.includes(`"${key}"`) ||
|
||||
content.includes(`\`${key}\``)
|
||||
) {
|
||||
used.add(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
// 检查 key 是否存在
|
||||
function keyExists(key: string, allKeys: Set<string>): boolean {
|
||||
if (allKeys.has(key)) return true;
|
||||
for (const existKey of allKeys) {
|
||||
if (existKey.startsWith(`${key}.`)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 硬编码文本信息
|
||||
interface HardcodedText {
|
||||
file: string;
|
||||
line: number;
|
||||
text: string;
|
||||
context: string;
|
||||
}
|
||||
|
||||
// 检测硬编码的中英文
|
||||
function findHardcodedTexts(): HardcodedText[] {
|
||||
const results: HardcodedText[] = [];
|
||||
const files = getFiles(srcDir, ['.vue', '.js', '.ts', '.jsx', '.tsx']);
|
||||
|
||||
// 中文匹配
|
||||
const chinesePattern = /[\u4e00-\u9fa5]+[^'"`]*[\u4e00-\u9fa5]*/g;
|
||||
|
||||
// 英文短语匹配(至少两个单词,排除常见代码模式)
|
||||
const englishPattern = /['"`]([A-Z][a-z]+(?:\s+[a-zA-Z]+){1,10})['"` ]/g;
|
||||
|
||||
// 需要忽略的模式
|
||||
const ignorePatterns = [
|
||||
/console\.(log|warn|error|info)/,
|
||||
/\/\/.*/,
|
||||
/\/\*[\s\S]*?\*\//,
|
||||
/import\s+/,
|
||||
/export\s+/,
|
||||
/require\s*\(/,
|
||||
/^\s*\*/,
|
||||
/eslint-disable/,
|
||||
/TODO:|FIXME:|NOTE:/,
|
||||
/http[s]?:\/\//,
|
||||
/\.(vue|js|ts|css|scss|json|png|jpg|svg)/,
|
||||
];
|
||||
|
||||
// 常见的可忽略英文
|
||||
const ignoreEnglishWords = new Set([
|
||||
'New Tab',
|
||||
'Click Me',
|
||||
'Hello World',
|
||||
'Vue Router',
|
||||
'Event Bus',
|
||||
'Local Storage',
|
||||
'Session Storage',
|
||||
'Content Type',
|
||||
'User Agent',
|
||||
'Access Control',
|
||||
]);
|
||||
|
||||
files.forEach(filePath => {
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const lines = content.split('\n');
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
// 跳过注释和导入
|
||||
const shouldIgnore = ignorePatterns.some(pattern => pattern.test(line));
|
||||
if (shouldIgnore) return;
|
||||
|
||||
// 跳过已使用 $t 或 t() 的行
|
||||
if (/\$t\s*\(/.test(line) || /\bt\s*\(/.test(line)) return;
|
||||
|
||||
// 检测中文
|
||||
const chineseMatches = line.match(chinesePattern);
|
||||
if (chineseMatches) {
|
||||
chineseMatches.forEach(text => {
|
||||
// 过滤掉注释中的中文
|
||||
if (line.trimStart().startsWith('//')) return;
|
||||
if (line.trimStart().startsWith('*')) return;
|
||||
|
||||
// 检查是否在字符串中
|
||||
const inString =
|
||||
line.includes(`'${text}`) ||
|
||||
line.includes(`"${text}`) ||
|
||||
line.includes(`\`${text}`);
|
||||
|
||||
if (inString && text.length >= 2) {
|
||||
results.push({
|
||||
file: filePath,
|
||||
line: index + 1,
|
||||
text: text.trim(),
|
||||
context: line.trim().slice(0, 100),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 检测英文短语
|
||||
let match;
|
||||
englishPattern.lastIndex = 0;
|
||||
while ((match = englishPattern.exec(line)) !== null) {
|
||||
const text = match[1];
|
||||
|
||||
// 过滤
|
||||
if (ignoreEnglishWords.has(text)) continue;
|
||||
if (text.length < 5) continue;
|
||||
if (/^[A-Z_]+$/.test(text)) continue; // 常量
|
||||
if (looksLikeI18nKey(text)) continue;
|
||||
|
||||
// 看起来像用户可见文本
|
||||
if (/^[A-Z][a-z]+(\s+[a-zA-Z]+)+$/.test(text)) {
|
||||
results.push({
|
||||
file: filePath,
|
||||
line: index + 1,
|
||||
text,
|
||||
context: line.trim().slice(0, 100),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 去重
|
||||
const unique = new Map<string, HardcodedText>();
|
||||
results.forEach(item => {
|
||||
const key = `${item.file}:${item.line}:${item.text}`;
|
||||
if (!unique.has(key)) {
|
||||
unique.set(key, item);
|
||||
}
|
||||
});
|
||||
|
||||
return [...unique.values()];
|
||||
}
|
||||
|
||||
// 主逻辑
|
||||
function main(): void {
|
||||
const allKeys = getAllI18nKeys();
|
||||
const usedKeys = getUsedKeys(allKeys);
|
||||
|
||||
console.log(`\n📊 总 key 数量: ${allKeys.size}`);
|
||||
console.log(`📊 使用中的 key: ${usedKeys.size}`);
|
||||
|
||||
// 未使用的 key
|
||||
const unused = [...allKeys].filter(key => !usedKeys.has(key));
|
||||
console.log(`\n❌ 未使用的 key (${unused.length}):\n`);
|
||||
unused.sort().forEach(key => console.log(` - ${key}`));
|
||||
|
||||
// 缺失的 key
|
||||
const missing = [...usedKeys].filter(key => {
|
||||
if (!looksLikeI18nKey(key)) return false;
|
||||
return !keyExists(key, allKeys);
|
||||
});
|
||||
|
||||
if (missing.length) {
|
||||
console.log(`\n⚠️ 缺失的 key (${missing.length}):\n`);
|
||||
missing.sort().forEach(key => console.log(` - ${key}`));
|
||||
}
|
||||
|
||||
// 硬编码文本
|
||||
console.log('\n🔍 检测硬编码文本...');
|
||||
const hardcoded = findHardcodedTexts();
|
||||
|
||||
if (hardcoded.length) {
|
||||
console.log(`\n📝 硬编码文本 (${hardcoded.length}):\n`);
|
||||
|
||||
// 按文件分组
|
||||
const byFile = new Map<string, HardcodedText[]>();
|
||||
hardcoded.forEach(item => {
|
||||
const list = byFile.get(item.file) || [];
|
||||
list.push(item);
|
||||
byFile.set(item.file, list);
|
||||
});
|
||||
|
||||
byFile.forEach((items, file) => {
|
||||
console.log(`\n 📄 ${file}`);
|
||||
items.forEach(item => {
|
||||
console.log(` L${item.line}: "${item.text}"`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// // 输出报告
|
||||
// const report = {
|
||||
// summary: {
|
||||
// totalKeys: allKeys.size,
|
||||
// usedKeys: usedKeys.size,
|
||||
// unusedCount: unused.length,
|
||||
// missingCount: missing.length,
|
||||
// hardcodedCount: hardcoded.length,
|
||||
// },
|
||||
// unused,
|
||||
// missing,
|
||||
// hardcoded: hardcoded.map(h => ({
|
||||
// file: h.file,
|
||||
// line: h.line,
|
||||
// text: h.text,
|
||||
// })),
|
||||
// };
|
||||
|
||||
// fs.writeFileSync('./i18n-report.json', JSON.stringify(report, null, 2));
|
||||
// console.log('\n✅ 报告已保存到 i18n-report.json');
|
||||
}
|
||||
|
||||
main();
|
||||
72
web-core/scripts/license.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import checker from "license-checker";
|
||||
|
||||
const excludeNames = ["toonflow-serve"];
|
||||
// const strictWhiteList = ["MIT", "BSD-2-Clause", "BSD-3-Clause", "BSD", "0BSD"];
|
||||
const strictWhiteList: string[] = [];
|
||||
|
||||
// 检查是否在白名单协议
|
||||
function isStrictWhiteLicense(license: string): boolean {
|
||||
const normalized = license.replace(/[\(\)]/g, "").trim();
|
||||
const parts = normalized.split(/\s*(OR|AND|\/)\s*/i).map((part) => part.trim());
|
||||
return parts.every((part) => strictWhiteList.some((wl) => part === wl || part.replace(/ with .*/i, "") === wl));
|
||||
}
|
||||
|
||||
// 读取 package.json 里的直接依赖
|
||||
function getDirectDependencyNames(): string[] {
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), "package.json"), "utf-8"));
|
||||
const deps = Object.keys(pkg.dependencies ?? {});
|
||||
const devDeps = Object.keys(pkg.devDependencies ?? {});
|
||||
return [...deps, ...devDeps];
|
||||
}
|
||||
|
||||
// 执行主逻辑
|
||||
checker.init({ start: process.cwd() }, (err: Error, packages: Record<string, any>) => {
|
||||
if (err) {
|
||||
console.error("license-checker 出错: ", err);
|
||||
process.exit(1);
|
||||
}
|
||||
const directNames = getDirectDependencyNames();
|
||||
|
||||
interface PackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
licenses: string | string[];
|
||||
repository: string | undefined;
|
||||
}
|
||||
|
||||
const needDeclare: PackageInfo[] = [];
|
||||
for (const fullName in packages) {
|
||||
// fullName 一般形如 [@scope/]pkg@version, 但 license-checker 会带路径,如 @scope/name@1.0.0@./node_modules/@scope/name
|
||||
// 所以可以正则只保留 name@version 部分
|
||||
// nameMatch[1] 为包名,nameMatch[2] 为版本
|
||||
const nameMatch = fullName.match(/^((?:@[^\/]+\/)?[^@]+)@([^@]+)$/);
|
||||
if (!nameMatch) continue;
|
||||
const name = nameMatch[1];
|
||||
// 仅关注直接依赖
|
||||
if (!directNames.includes(name!)) continue;
|
||||
|
||||
const info = packages[fullName];
|
||||
const licenseArr: string[] = Array.isArray(info.licenses) ? info.licenses : [info.licenses];
|
||||
if (!licenseArr.every(isStrictWhiteLicense)) {
|
||||
needDeclare.push({
|
||||
name: name!,
|
||||
version: info.version,
|
||||
licenses: licenseArr,
|
||||
repository: info.repository,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 排除名单过滤
|
||||
const filteredDeclare = needDeclare.filter((pkg) => pkg.name && !excludeNames.some((exName) => pkg.name.startsWith(exName)));
|
||||
const content = filteredDeclare
|
||||
.map(
|
||||
(pkg) =>
|
||||
`Name: ${pkg.name}\nLicense: ${Array.isArray(pkg.licenses) ? pkg.licenses.join(", ") : pkg.licenses}\nRepository: ${pkg.repository ?? "N/A"}`,
|
||||
)
|
||||
.join("\n\n-----------------------------\n\n");
|
||||
fs.writeFileSync(path.resolve(process.cwd(), "NOTICES.txt"), content, "utf-8");
|
||||
console.log("已生成依赖声明 NOTICES.txt");
|
||||
});
|
||||
132
web-core/src/App.vue
Normal file
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<titleBar v-if="isElectron" />
|
||||
<t-config-provider :global-config="globalConfig">
|
||||
<router-view></router-view>
|
||||
</t-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import settingStore from "@/stores/setting";
|
||||
import { merge } from "lodash-es";
|
||||
import zhConfig from "tdesign-vue-next/es/locale/zh_CN";
|
||||
import enConfig from "tdesign-vue-next/es/locale/en_US";
|
||||
import { cachedLocale } from "@/locales";
|
||||
import { initTheme } from "@/utils/theme";
|
||||
import { normalizeApiBaseUrl } from "@/utils/apiBaseUrl";
|
||||
import { type GlobalConfigProvider } from "tdesign-vue-next";
|
||||
const { baseUrl, isElectron } = storeToRefs(settingStore());
|
||||
import { config } from "md-editor-v3";
|
||||
|
||||
watch(
|
||||
() => isElectron.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
document.body.classList.add("is-electron");
|
||||
} else {
|
||||
document.body.classList.remove("is-electron");
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
onBeforeMount(() => {
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key === "F8") {
|
||||
event.preventDefault();
|
||||
debugger;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化主题
|
||||
onMounted(() => {
|
||||
getPort();
|
||||
});
|
||||
|
||||
async function handleLinkClick(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const target = event.currentTarget as HTMLAnchorElement | null;
|
||||
const url = target?.getAttribute("data-link") || target?.getAttribute("href");
|
||||
if (!url) return false;
|
||||
|
||||
if (isElectron.value) {
|
||||
await fetch(`toonflow://openurlwithbrowser?url=${encodeURIComponent(url)}`);
|
||||
} else {
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
(window as any).handleLinkClick = handleLinkClick;
|
||||
});
|
||||
|
||||
async function getPort() {
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
baseUrl.value = normalizeApiBaseUrl(baseUrl.value);
|
||||
const canUseToonflowProtocol = navigator.userAgent.toLowerCase().includes("electron") || Boolean((window as any).electronAPI);
|
||||
if (canUseToonflowProtocol) {
|
||||
try {
|
||||
const res = await fetch("toonflow://getAppUrl");
|
||||
const data = await res.json();
|
||||
if (data?.url) {
|
||||
baseUrl.value = data.url;
|
||||
isElectron.value = true;
|
||||
}
|
||||
} catch (error) {}
|
||||
} else {
|
||||
isElectron.value = false;
|
||||
}
|
||||
|
||||
config({
|
||||
markdownItConfig(md) {
|
||||
// 自定义链接渲染
|
||||
const defaultRender =
|
||||
md.renderer.rules.link_open ||
|
||||
function (tokens, idx, options, env, self) {
|
||||
return self.renderToken(tokens, idx, options);
|
||||
};
|
||||
md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
|
||||
const token = tokens[idx];
|
||||
const href = token.attrGet("href");
|
||||
|
||||
if (href) {
|
||||
// 添加 target="_blank" 在新窗口打开
|
||||
token.attrSet("target", "_blank");
|
||||
token.attrSet("rel", "noopener noreferrer");
|
||||
|
||||
// 或者添加自定义点击事件的标识
|
||||
token.attrSet("data-link", href);
|
||||
token.attrSet("onclick", "return handleLinkClick(event)");
|
||||
}
|
||||
|
||||
return defaultRender(tokens, idx, options, env, self);
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const tdesignLocaleMap: Record<string, object> = {
|
||||
"zh-CN": zhConfig,
|
||||
en: enConfig,
|
||||
};
|
||||
|
||||
const customConfig: GlobalConfigProvider = {
|
||||
calendar: {},
|
||||
table: {},
|
||||
pagination: {},
|
||||
};
|
||||
const globalConfig = computed<GlobalConfigProvider>(() => merge({}, tdesignLocaleMap[cachedLocale.value] || zhConfig, customConfig));
|
||||
|
||||
onBeforeMount(() => {
|
||||
initTheme();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
4
web-core/src/assets/atomgit.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="96" height="96">
|
||||
<path d="M0 0 C2.60491411 3.39771405 2.43893626 6.83010556 2 11 C0.20437595 13.75329021 -1.05254922 15.52627461 -4 17 C-9.16062661 17.49941548 -9.16062661 17.49941548 -12 17 C-14.90799783 14.4555019 -15.90702057 13.04601863 -16.25 9.1875 C-16.1675 8.465625 -16.085 7.74375 -16 7 C-17.0725 7.639375 -18.145 8.27875 -19.25 8.9375 C-27.64061736 13.11803647 -42.1161507 13.9612831 -51 11 C-51.09796875 11.67804687 -51.1959375 12.35609375 -51.296875 13.0546875 C-52.09650113 18.03167082 -53.07549372 22.54151804 -55.0625 27.1875 C-58.18113878 34.59280707 -58.84191514 41.34103871 -56 49 C-51.69477815 55.71108112 -45.90514151 58.44542058 -38.375 60.3125 C-28.59646317 61.98237321 -17.61397475 61.2378015 -9 56 C-6.49898905 53.93089054 -4.42615578 51.9334749 -3 49 C-2.8015185 45.84858524 -2.8015185 45.84858524 -3 43 C-3.63502441 42.9498877 -4.27004883 42.89977539 -4.92431641 42.84814453 C-7.82522523 42.61482321 -10.72505632 42.37001416 -13.625 42.125 C-14.62402344 42.04636719 -15.62304688 41.96773437 -16.65234375 41.88671875 C-29.19293478 40.80706522 -29.19293478 40.80706522 -33 37 C-32.79953373 33.85936171 -32.54877905 31.72339057 -30.625 29.1875 C-24.50435236 24.71471903 -13.19717736 26.55890184 -6 27 C-2.41396623 27.60321914 0.69870236 28.49303823 4 30 C4.94875 30.4125 5.8975 30.825 6.875 31.25 C11.08743551 34.71906454 12.65632177 38.68972676 14 43.8125 C14.64326159 52.37282738 9.41850308 59.51339193 4.13671875 65.7421875 C-2.45750281 72.7101218 -11.41635656 78.38746195 -21.19140625 79.17700195 C-37.70773611 79.60385521 -50.14814106 78.46993862 -63 67 C-73.50321308 56.03782298 -76.52428161 45.45597262 -76.2734375 30.625 C-75.77333104 18.46399527 -69.95822491 8.40894719 -61.1875 0.1875 C-43.74979764 -14.14115465 -17.3489938 -15.03579462 0 0 Z " fill="#DA203E" transform="translate(80,13)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
BIN
web-core/src/assets/bg.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
web-core/src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
31
web-core/src/assets/logo.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="ToonFlow logo">
|
||||
<defs>
|
||||
<linearGradient id="tf-stem" x1="24" y1="24" x2="96" y2="98" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#64e1d3"/>
|
||||
<stop offset="0.58" stop-color="#8ea3ff"/>
|
||||
<stop offset="1" stop-color="#ffb46b"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="tf-play" x1="63" y1="42" x2="92" y2="82" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ffffff"/>
|
||||
<stop offset="1" stop-color="#dffdf7"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
fill="url(#tf-stem)"
|
||||
d="M28 24h72c5.52 0 10 4.48 10 10v4c0 5.52-4.48 10-10 10H74v49c0 5.52-4.48 10-10 10H52c-5.52 0-10-4.48-10-10V48H28c-5.52 0-10-4.48-10-10v-4c0-5.52 4.48-10 10-10Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#tf-stem)"
|
||||
opacity=".9"
|
||||
d="M42 74h56c6.63 0 12 5.37 12 12v2c0 6.63-5.37 12-12 12H42V74Z"
|
||||
/>
|
||||
<path
|
||||
fill="#142133"
|
||||
fill-opacity=".25"
|
||||
d="M31 32h10a4 4 0 0 1 0 8H31a4 4 0 0 1 0-8Zm44 50h14a4 4 0 0 1 0 8H75a4 4 0 0 1 0-8Z"
|
||||
/>
|
||||
<path
|
||||
fill="url(#tf-play)"
|
||||
d="M68.4 47.58c-3.32-2.09-7.65.3-7.65 4.22v32.4c0 3.92 4.33 6.31 7.65 4.22l25.7-16.2c3.1-1.95 3.1-6.49 0-8.44l-25.7-16.2Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1361
web-core/src/assets/main.scss
Normal file
BIN
web-core/src/assets/providers/ace.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
web-core/src/assets/providers/adobe.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/adobefirefly.webp
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
web-core/src/assets/providers/agentvoice.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
web-core/src/assets/providers/agui.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web-core/src/assets/providers/ai2.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
web-core/src/assets/providers/ai21.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web-core/src/assets/providers/ai302.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
web-core/src/assets/providers/ai360.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
web-core/src/assets/providers/aihubmix.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
web-core/src/assets/providers/aimass.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
web-core/src/assets/providers/aionlabs.webp
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
web-core/src/assets/providers/aistudio.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
web-core/src/assets/providers/akashchat.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
web-core/src/assets/providers/alephalpha.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
web-core/src/assets/providers/alibaba.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
web-core/src/assets/providers/alibabacloud.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/amp.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
web-core/src/assets/providers/antgroup.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
web-core/src/assets/providers/anthropic.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
web-core/src/assets/providers/antigravity.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
web-core/src/assets/providers/anyscale.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
web-core/src/assets/providers/apertis.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web-core/src/assets/providers/apple.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
web-core/src/assets/providers/arcee.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
web-core/src/assets/providers/askverdict.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
web-core/src/assets/providers/assemblyai.webp
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
web-core/src/assets/providers/atlascloud.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
web-core/src/assets/providers/automatic.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web-core/src/assets/providers/aws.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
web-core/src/assets/providers/aya.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
web-core/src/assets/providers/azure.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
web-core/src/assets/providers/azureai.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
web-core/src/assets/providers/baai.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web-core/src/assets/providers/baichuan.webp
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
web-core/src/assets/providers/baidu.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
web-core/src/assets/providers/baiducloud.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
web-core/src/assets/providers/bailian.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
web-core/src/assets/providers/baseten.webp
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
web-core/src/assets/providers/bedrock.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
web-core/src/assets/providers/bfl.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/bilibili.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/bilibiliindex.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
web-core/src/assets/providers/bing.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
web-core/src/assets/providers/briaai.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
web-core/src/assets/providers/burncloud.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
web-core/src/assets/providers/bytedance.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
web-core/src/assets/providers/capcut.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web-core/src/assets/providers/centml.webp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
web-core/src/assets/providers/cerebras.webp
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
web-core/src/assets/providers/chatglm.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
web-core/src/assets/providers/cherrystudio.webp
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
web-core/src/assets/providers/civitai.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
web-core/src/assets/providers/claude.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
web-core/src/assets/providers/claudecode.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
web-core/src/assets/providers/cline.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web-core/src/assets/providers/clipdrop.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
web-core/src/assets/providers/cloudflare.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/codeflicker.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
web-core/src/assets/providers/codegeex.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
web-core/src/assets/providers/codex.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
web-core/src/assets/providers/cogvideo.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
web-core/src/assets/providers/cogview.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
web-core/src/assets/providers/cohere.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/colab.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
web-core/src/assets/providers/cometapi.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
web-core/src/assets/providers/comfyui.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/commanda.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
web-core/src/assets/providers/copilot.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
web-core/src/assets/providers/copilotkit.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
web-core/src/assets/providers/coqui.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
web-core/src/assets/providers/coze.webp
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
web-core/src/assets/providers/crewai.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
web-core/src/assets/providers/crusoe.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
web-core/src/assets/providers/cursor.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
web-core/src/assets/providers/cybercut.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |