@zeewain/3d-avatar-sdk 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +3 -4
  2. package/dist/assets/Build/webgl.data.unityweb +0 -0
  3. package/dist/assets/Build/webgl.framework.js.unityweb +0 -0
  4. package/dist/assets/Build/webgl.wasm.unityweb +0 -0
  5. package/dist/examples/test-umd/index.html +762 -0
  6. package/dist/examples/test-vue2/.eslintignore +45 -0
  7. package/dist/examples/test-vue2/.eslintrc.js +174 -0
  8. package/dist/examples/test-vue2/.stylelintignore +50 -0
  9. package/dist/examples/test-vue2/.stylelintrc.js +79 -0
  10. package/dist/examples/test-vue2/README.md +139 -0
  11. package/dist/examples/test-vue2/babel.config.js +14 -0
  12. package/dist/examples/test-vue2/package.json +53 -0
  13. package/dist/examples/test-vue2/pnpm-lock.yaml +8776 -0
  14. package/dist/examples/test-vue2/public/index.html +19 -0
  15. package/dist/examples/test-vue2/setup.js +170 -0
  16. package/dist/examples/test-vue2/src/App.vue +943 -0
  17. package/dist/examples/test-vue2/src/components/BroadcastAPI.vue +666 -0
  18. package/dist/examples/test-vue2/src/components/CameraAPI.vue +414 -0
  19. package/dist/examples/test-vue2/src/components/GlobalConfig.vue +200 -0
  20. package/dist/examples/test-vue2/src/components/InfoCards.vue +294 -0
  21. package/dist/examples/test-vue2/src/components/InitAPI.vue +334 -0
  22. package/dist/examples/test-vue2/src/components/LogPanel.vue +249 -0
  23. package/dist/examples/test-vue2/src/components/MotionControlAPI.vue +400 -0
  24. package/dist/examples/test-vue2/src/components/UnityPreview.vue +201 -0
  25. package/dist/examples/test-vue2/src/main.js +16 -0
  26. package/dist/examples/test-vue2/vue.config.js +41 -0
  27. package/dist/examples/test-vue3/.eslintrc +3 -0
  28. package/dist/examples/test-vue3/.stylelintignore +3 -0
  29. package/dist/examples/test-vue3/.stylelintrc +48 -0
  30. package/dist/examples/test-vue3/README.md +236 -0
  31. package/dist/examples/test-vue3/env.d.ts +8 -0
  32. package/dist/examples/test-vue3/index.html +95 -0
  33. package/dist/examples/test-vue3/package.json +55 -0
  34. package/dist/examples/test-vue3/pnpm-lock.yaml +4636 -0
  35. package/dist/examples/test-vue3/setup.js +167 -0
  36. package/dist/examples/test-vue3/src/App.vue +962 -0
  37. package/dist/examples/test-vue3/src/components/BroadcastAPI.vue +636 -0
  38. package/dist/examples/test-vue3/src/components/CameraAPI.vue +376 -0
  39. package/dist/examples/test-vue3/src/components/GlobalConfig.vue +213 -0
  40. package/dist/examples/test-vue3/src/components/InfoCards.vue +288 -0
  41. package/dist/examples/test-vue3/src/components/InitAPI.vue +339 -0
  42. package/dist/examples/test-vue3/src/components/LogPanel.vue +236 -0
  43. package/dist/examples/test-vue3/src/components/MotionControlAPI.vue +373 -0
  44. package/dist/examples/test-vue3/src/components/UnityPreview.vue +189 -0
  45. package/dist/examples/test-vue3/src/main.ts +12 -0
  46. package/dist/examples/test-vue3/src/types.ts +9 -0
  47. package/dist/examples/test-vue3/tsconfig.json +44 -0
  48. package/dist/examples/test-vue3/tsconfig.node.json +14 -0
  49. package/dist/examples/test-vue3/vite.config.ts +75 -0
  50. package/dist/index.d.ts +15 -9
  51. package/dist/index.es5.js +64 -17
  52. package/dist/index.es5.umd.js +64 -17
  53. package/dist/index.esm.js +71 -16
  54. package/dist/index.umd.cjs +71 -16
  55. package/package.json +4 -3
@@ -0,0 +1,201 @@
1
+ <template>
2
+ <el-card class="unity-preview" shadow="hover">
3
+ <div slot="header" class="card-header">
4
+ <span>Unity 预览</span>
5
+ <el-tag v-if="sdkStatus.unityLoaded" type="success" size="mini">已加载</el-tag>
6
+ <el-tag v-else type="info" size="mini">未加载</el-tag>
7
+ </div>
8
+
9
+ <div class="unity-container-wrapper">
10
+ <div id="unity-container" class="unity-container">
11
+ <div v-if="!sdkStatus.unityLoaded" class="unity-tip">
12
+ <i class="el-icon-monitor"></i>
13
+ <p>Unity 内容将在此处加载...</p>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="unity-controls">
19
+ <el-button-group>
20
+ <el-button
21
+ type="warning"
22
+ size="small"
23
+ icon="el-icon-close"
24
+ :disabled="!sdkStatus.avatarLoaded"
25
+ @click="handleUnloadAvatar"
26
+ >
27
+ 卸载Avatar
28
+ </el-button>
29
+ <el-button
30
+ type="danger"
31
+ size="small"
32
+ icon="el-icon-delete"
33
+ :disabled="!sdkStatus.unityLoaded"
34
+ @click="handleDestroySDK"
35
+ >
36
+ 销毁实例
37
+ </el-button>
38
+ </el-button-group>
39
+ </div>
40
+
41
+ <!-- 加载进度显示 -->
42
+ <div v-if="loadingProgress > 0 && loadingProgress < 1" class="loading-progress">
43
+ <el-progress
44
+ :percentage="Math.round(loadingProgress * 100)"
45
+ :stroke-width="6"
46
+ text-inside
47
+ />
48
+ <p class="progress-text">Unity 加载中,请稍候...</p>
49
+ </div>
50
+ </el-card>
51
+ </template>
52
+
53
+ <script>
54
+ export default {
55
+ name: 'UnityPreview',
56
+ props: {
57
+ sdkStatus: {
58
+ type: Object,
59
+ required: true,
60
+ default: () => ({
61
+ unityLoaded: false,
62
+ avatarLoaded: false
63
+ })
64
+ },
65
+ loadingProgress: {
66
+ type: Number,
67
+ default: 0
68
+ }
69
+ },
70
+ methods: {
71
+ handleUnloadAvatar () {
72
+ this.$emit('unload-avatar')
73
+ },
74
+
75
+ handleDestroySDK () {
76
+ this.$emit('destroy-sdk')
77
+ }
78
+ }
79
+ }
80
+ </script>
81
+
82
+ <style lang="scss" scoped>
83
+ // Unity预览
84
+ .unity-preview {
85
+ position: relative;
86
+ display: flex;
87
+ width: 100%;
88
+ height: 100%;
89
+ overflow: hidden;
90
+ flex-direction: column;
91
+
92
+ .card-header {
93
+ display: flex;
94
+ justify-content: space-between;
95
+ align-items: center;
96
+ font-weight: 600;
97
+ }
98
+
99
+ :deep(.el-card__body) {
100
+ display: flex;
101
+ width: 100%;
102
+ height: 100%;
103
+ flex-direction: column;
104
+ box-sizing: border-box;
105
+ }
106
+
107
+ .unity-container-wrapper {
108
+ position: relative;
109
+ width: 100%;
110
+ max-height: 600px; // 添加最大高度限制
111
+ margin-bottom: 15px;
112
+ overflow: hidden; // 防止内容溢出
113
+ flex: 1;
114
+ }
115
+
116
+ .unity-container {
117
+ position: relative;
118
+ width: 100%;
119
+ height: 100%;
120
+ max-height: 100%; // 确保不超过父容器
121
+ overflow: hidden;
122
+ background-color: #000;
123
+ border-radius: 4px;
124
+ }
125
+
126
+ .unity-tip {
127
+ position: absolute;
128
+ top: 50%;
129
+ left: 50%;
130
+ color: white; // 确保在黑色背景上文字可见
131
+ text-align: center;
132
+ transform: translate(-50%, -50%);
133
+
134
+ i {
135
+ margin-bottom: 10px;
136
+ font-size: 48px;
137
+ }
138
+
139
+ p {
140
+ margin: 0;
141
+ font-size: 14px;
142
+ }
143
+ }
144
+
145
+ .unity-controls {
146
+ display: flex;
147
+ justify-content: center;
148
+ padding-top: 10px;
149
+ }
150
+
151
+ .loading-progress {
152
+ position: absolute;
153
+ top: 50%;
154
+ left: 50%;
155
+ width: 80%;
156
+ transform: translate(-50%, -50%);
157
+ text-align: center;
158
+ z-index: 10;
159
+
160
+ .progress-text {
161
+ color: white;
162
+ margin-top: 10px;
163
+ font-size: 14px;
164
+ }
165
+ }
166
+ }
167
+
168
+ // 移动端优化
169
+ @media screen and (width <= 768px) {
170
+ .unity-preview {
171
+ .unity-container-wrapper {
172
+ height: 250px;
173
+ max-height: 250px; // 确保移动端不会超过设定高度
174
+ flex: none;
175
+ overflow: hidden; // 防止内容溢出
176
+ }
177
+
178
+ .unity-controls {
179
+ .el-button-group {
180
+ display: flex;
181
+ flex-direction: column;
182
+
183
+ .el-button {
184
+ margin: 2px 0;
185
+ }
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ // 平板端优化
192
+ @media screen and (width <= 992px) and (width > 768px) {
193
+ .unity-preview {
194
+ .unity-container-wrapper {
195
+ height: 300px; // 平板端适中高度
196
+ max-height: 300px; // 确保平板端不会超过设定高度
197
+ overflow: hidden; // 防止内容溢出
198
+ }
199
+ }
200
+ }
201
+ </style>
@@ -0,0 +1,16 @@
1
+ import Vue from 'vue'
2
+ import App from './App.vue'
3
+
4
+ // 引入Element-UI
5
+ import ElementUI from 'element-ui'
6
+ import 'element-ui/lib/theme-chalk/index.css'
7
+
8
+ // 使用Element-UI
9
+ Vue.use(ElementUI)
10
+
11
+ // 关闭生产提示
12
+ Vue.config.productionTip = false
13
+
14
+ new Vue({
15
+ render: h => h(App)
16
+ }).$mount('#app')
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @fileoverview Vue CLI 配置文件
3
+ * @description 支持本地开发和npm包两种模式的动态配置
4
+ */
5
+
6
+ const { defineConfig } = require('@vue/cli-service')
7
+ const path = require('path')
8
+
9
+ // 检查是否使用本地开发版本(通过环境变量控制)
10
+ const useLocalSDK = process.env.VUE_APP_USE_LOCAL_SDK === 'true'
11
+ const localSDKPath = path.resolve(__dirname, '../../dist')
12
+
13
+ console.log('🔧 Vue 配置信息:')
14
+ console.log(` - 使用本地 SDK: ${useLocalSDK ? '✅ 是' : '❌ 否'}`)
15
+ if (useLocalSDK) {
16
+ console.log(` - 本地 SDK 路径: ${localSDKPath}`)
17
+ console.log(' - 运行模式: 开发模式')
18
+ } else {
19
+ console.log(' - 运行模式: npm包模式')
20
+ }
21
+
22
+ module.exports = defineConfig({
23
+ transpileDependencies: true,
24
+ publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
25
+ devServer: {
26
+ port: 8080,
27
+ host: 'localhost',
28
+ open: true
29
+ },
30
+ configureWebpack: {
31
+ resolve: {
32
+ alias: {
33
+ '@': require('path').resolve(__dirname, 'src'),
34
+ // 如果启用本地开发模式,将 SDK 指向本地构建版本
35
+ ...(useLocalSDK && {
36
+ '@zeewain/3d-avatar-sdk': path.resolve(localSDKPath, 'index.esm.js')
37
+ })
38
+ }
39
+ }
40
+ }
41
+ })
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "@cyril_m"
3
+ }
@@ -0,0 +1,3 @@
1
+ dist*/
2
+ node_modules/
3
+ src/assets/sprites/
@@ -0,0 +1,48 @@
1
+ {
2
+ "extends": [
3
+ "stylelint-config-standard",
4
+ "stylelint-config-standard-scss",
5
+ "stylelint-config-standard-vue/scss"
6
+ ],
7
+ "plugins": [
8
+ "stylelint-scss"
9
+ ],
10
+ "customSyntax": "postcss-html",
11
+ "rules": {
12
+ "indentation": 2,
13
+ "rule-empty-line-before": "never",
14
+ "at-rule-empty-line-before": "never",
15
+ "at-rule-no-unknown": null,
16
+ "no-descending-specificity": null,
17
+ "selector-pseudo-class-no-unknown": null,
18
+ "property-no-unknown": null,
19
+ "font-family-no-missing-generic-family-keyword": null,
20
+ "selector-id-pattern": null,
21
+ "selector-class-pattern": null,
22
+ "scss/no-global-function-names": null,
23
+ "scss/at-import-partial-extension": null,
24
+ "function-no-unknown": [
25
+ true,
26
+ {
27
+ "ignoreFunctions": [
28
+ "v-bind",
29
+ "map-get",
30
+ "lighten",
31
+ "darken",
32
+ "themed"
33
+ ]
34
+ }
35
+ ],
36
+ "property-no-vendor-prefix": [
37
+ true,
38
+ {
39
+ "ignoreProperties": [
40
+ "mask-image"
41
+ ]
42
+ }
43
+ ],
44
+ "max-line-length": null,
45
+ "no-empty-source": null,
46
+ "color-function-notation": null
47
+ }
48
+ }
@@ -0,0 +1,236 @@
1
+ # ZEE 3D Avatar SDK - Vue3 测试项目
2
+
3
+ ## 📋 项目概述
4
+
5
+ 这是一个基于 Vue3 + TypeScript + Vite + Element Plus 技术栈的 ZEE 3D Avatar SDK 测试项目,展示了如何在现代 Vue3 应用中集成和使用最新的统一架构 SDK。
6
+
7
+ ## ✨ 技术栈
8
+
9
+ - **Vue 3.4+** - 渐进式 JavaScript 框架
10
+ - **TypeScript** - JavaScript 的超集,提供类型安全
11
+ - **Vite 5.0+** - 下一代前端构建工具
12
+ - **Element Plus** - 基于 Vue3 的组件库
13
+ - **Sass/SCSS** - CSS 预处理器
14
+ - **ESLint + Prettier** - 代码规范和格式化
15
+ - **Stylelint** - CSS 代码规范
16
+
17
+ ## 🚀 核心特性
18
+
19
+ ### SDK 统一架构
20
+ - **单一入口**:使用 `ZEEAvatarSDK` 统一类管理所有功能
21
+ - **一步初始化**:`initializeAvatar()` 方法统一完成 Unity 初始化和数字人加载
22
+ - **多实例支持**:支持同页面多个独立 SDK 实例
23
+ - **完整类型支持**:TypeScript 类型定义,智能提示
24
+
25
+ ### 功能模块
26
+ - **全局配置管理** - Token 和 Avatar 编码配置
27
+ - **Avatar 初始化** - 统一的数字人初始化流程
28
+ - **动作控制** - 播放动作、获取当前动作信息
29
+ - **智能播报** - 文本转语音、音频播报、播报控制
30
+ - **镜头控制** - 全身、半身、面部镜头切换
31
+ - **实时日志** - 操作日志记录和显示
32
+ - **响应式布局** - 支持 PC 和移动端适配
33
+
34
+ ## 📦 安装和运行
35
+
36
+ ### 环境要求
37
+ - Node.js 18.0+
38
+ - pnpm 8.0+
39
+
40
+ ### 安装依赖
41
+ ```bash
42
+ cd examples/test-vue3
43
+ pnpm install
44
+ ```
45
+
46
+ ### 开发模式
47
+ ```bash
48
+ # 使用本地 SDK 源码(推荐)
49
+ pnpm run dev
50
+
51
+ # 使用 npm 包版本
52
+ pnpm run dev:npm
53
+ ```
54
+
55
+ ### 构建项目
56
+ ```bash
57
+ pnpm run build
58
+ ```
59
+
60
+ ### 预览构建结果
61
+ ```bash
62
+ pnpm run preview
63
+ ```
64
+
65
+ ## 🛠️ 开发命令
66
+
67
+ ### 代码检查和格式化
68
+ ```bash
69
+ # ESLint 检查
70
+ pnpm run lint:js
71
+
72
+ # Stylelint 检查
73
+ pnpm run lint:css
74
+
75
+ # 修复 ESLint 问题
76
+ pnpm run lint:fix
77
+
78
+ # 修复 Stylelint 问题
79
+ pnpm run lint:css-fix
80
+
81
+ # 检查和修复所有问题
82
+ pnpm run lint:all-fix
83
+ ```
84
+
85
+ ### TypeScript 类型检查
86
+ ```bash
87
+ pnpm run type-check
88
+ ```
89
+
90
+ ## 📁 项目结构
91
+
92
+ ```
93
+ examples/test-vue3/
94
+ ├── public/ # 静态资源
95
+ │ ├── index.html # HTML 模板
96
+ │ └── assets/ # Unity 构建文件(自动复制)
97
+ ├── src/ # 源代码
98
+ │ ├── components/ # Vue 组件
99
+ │ │ ├── GlobalConfig.vue # 全局配置组件
100
+ │ │ ├── InitApi.vue # 初始化 API 组件
101
+ │ │ ├── MotionControlApi.vue # 动作控制 API 组件
102
+ │ │ ├── BroadcastApi.vue # 播报 API 组件
103
+ │ │ ├── CameraApi.vue # 镜头控制 API 组件
104
+ │ │ ├── UnityPreview.vue # Unity 预览组件
105
+ │ │ ├── LogPanel.vue # 日志面板组件
106
+ │ │ └── InfoCards.vue # 信息卡片组件
107
+ │ ├── styles/ # 样式文件
108
+ │ │ └── global.scss # 全局样式
109
+ │ ├── types/ # TypeScript 类型定义
110
+ │ │ └── index.ts # 类型定义文件
111
+ │ ├── App.vue # 根组件
112
+ │ └── main.ts # 应用入口
113
+ ├── setup.js # 项目设置脚本
114
+ ├── vite.config.ts # Vite 配置
115
+ ├── tsconfig.json # TypeScript 配置
116
+ ├── package.json # 项目配置
117
+ └── README.md # 项目说明
118
+ ```
119
+
120
+ ## 🔧 核心组件说明
121
+
122
+ ### App.vue
123
+ 主应用组件,使用 Vue3 Composition API 和 TypeScript:
124
+ - 统一的 SDK 实例管理
125
+ - 响应式布局适配
126
+ - 全局状态管理
127
+ - 事件处理和错误管理
128
+
129
+ ### GlobalConfig.vue
130
+ 全局配置组件:
131
+ - Token 和 Avatar 编码配置
132
+ - 本地存储管理
133
+ - 配置验证和应用
134
+
135
+ ### InitApi.vue
136
+ 初始化 API 组件:
137
+ - 使用统一的 `initializeAvatar()` 方法
138
+ - 自动完成 Unity 初始化和数字人加载
139
+ - 进度显示和状态管理
140
+
141
+ ### MotionControlApi.vue
142
+ 动作控制 API 组件:
143
+ - 播放指定动作
144
+ - 获取当前动作信息
145
+ - 动作状态管理
146
+
147
+ ### BroadcastApi.vue
148
+ 播报 API 组件:
149
+ - 文本转语音播报
150
+ - 音频文件播报
151
+ - 播报控制(暂停、恢复、停止)
152
+
153
+ ### CameraApi.vue
154
+ 镜头控制 API 组件:
155
+ - 全身、半身、面部镜头切换
156
+ - 实时镜头状态显示
157
+
158
+ ### UnityPreview.vue
159
+ Unity 预览组件:
160
+ - Unity 容器管理
161
+ - 加载进度显示
162
+ - 资源管理操作
163
+
164
+ ### LogPanel.vue
165
+ 日志面板组件:
166
+ - 实时日志显示
167
+ - 日志类型区分
168
+ - 日志清理功能
169
+
170
+ ## 🎯 使用示例
171
+
172
+ ### 基础使用
173
+ ```typescript
174
+ import { ZEEAvatarSDK, AvatarCameraType, BroadcastType } from '@zeewain/3d-avatar-sdk'
175
+
176
+ // 创建 SDK 实例
177
+ const sdk = new ZEEAvatarSDK({
178
+ loaderUrl: './assets/Build/webgl.loader.js',
179
+ dataUrl: './assets/Build/webgl.data.unityweb',
180
+ frameworkUrl: './assets/Build/webgl.framework.js.unityweb',
181
+ codeUrl: './assets/Build/webgl.wasm.unityweb',
182
+ containerId: 'unity-container',
183
+ token: 'your-token',
184
+ env: 'prod'
185
+ })
186
+
187
+ // 初始化数字人
188
+ await sdk.initializeAvatar('avatar001', AvatarCameraType.WHOLE)
189
+
190
+ // 播放动作
191
+ await sdk.playMotion('wave_hand')
192
+
193
+ // 文本播报
194
+ await sdk.startBroadcast({
195
+ type: BroadcastType.TEXT,
196
+ humanCode: 'avatar001',
197
+ text: '欢迎使用 ZEE 3D Avatar SDK',
198
+ voiceCode: 'VOICE001',
199
+ volume: 1.0,
200
+ speed: 1.0,
201
+ isSubtitle: false
202
+ })
203
+ ```
204
+
205
+ ### 错误处理
206
+ ```typescript
207
+ try {
208
+ await sdk.initializeAvatar('avatar001')
209
+ } catch (error) {
210
+ if (error instanceof SDKError) {
211
+ console.error('SDK错误:', error.message, '错误码:', error.code)
212
+ } else {
213
+ console.error('系统错误:', error)
214
+ }
215
+ }
216
+ ```
217
+
218
+ ## 🔍 开发调试
219
+
220
+ ### 浏览器开发者工具
221
+ - 打开浏览器开发者工具
222
+ - 查看 Console 面板的日志输出
223
+ - 检查 Network 面板的网络请求
224
+ - 使用 Vue DevTools 调试组件状态
225
+
226
+ ### 日志系统
227
+ 项目内置了完整的日志系统:
228
+ - 实时显示操作日志
229
+ - 按类型区分日志级别
230
+ - 支持日志清理和导出
231
+
232
+ ### 常见问题
233
+ 1. **Unity 无法加载**:检查 assets 目录是否包含 Unity 构建文件
234
+ 2. **Token 认证失败**:确认 Token 配置正确且有效
235
+ 3. **播报无声音**:检查音量设置和浏览器音频策略
236
+ 4. **类型错误**:确保使用正确的 TypeScript 类型定义
@@ -0,0 +1,8 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare module '*.vue' {
4
+ import type { DefineComponent } from 'vue'
5
+ const component: DefineComponent<{}, {}, any>
6
+ export default component
7
+ }
8
+
@@ -0,0 +1,95 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>ZEE 3D Avatar SDK - Vue3 测试项目</title>
7
+ <meta name="description" content="ZEE 3D Avatar SDK Vue3 + TypeScript + Vite 测试项目" />
8
+ <meta name="keywords" content="ZEE, 3D, Avatar, SDK, Vue3, TypeScript, Vite" />
9
+ <meta name="author" content="ZEEWain" />
10
+ <!-- 样式重置 -->
11
+ <style>
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ html, body {
19
+ height: 100%;
20
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
21
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
22
+ sans-serif;
23
+ -webkit-font-smoothing: antialiased;
24
+ -moz-osx-font-smoothing: grayscale;
25
+ }
26
+
27
+ #app {
28
+ height: 100%;
29
+ }
30
+
31
+ /* 加载动画 */
32
+ .loading-container {
33
+ position: fixed;
34
+ top: 0;
35
+ left: 0;
36
+ width: 100%;
37
+ height: 100%;
38
+ background: #f5f5f5;
39
+ display: flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ z-index: 9999;
43
+ }
44
+
45
+ .loading-spinner {
46
+ width: 40px;
47
+ height: 40px;
48
+ border: 4px solid #e0e0e0;
49
+ border-top: 4px solid #409eff;
50
+ border-radius: 50%;
51
+ animation: spin 1s linear infinite;
52
+ }
53
+
54
+ @keyframes spin {
55
+ 0% { transform: rotate(0deg); }
56
+ 100% { transform: rotate(360deg); }
57
+ }
58
+
59
+ .loading-text {
60
+ margin-top: 16px;
61
+ color: #666;
62
+ font-size: 14px;
63
+ }
64
+ </style>
65
+ </head>
66
+ <body>
67
+ <div id="app">
68
+ <!-- 初始加载动画 -->
69
+ <div class="loading-container" id="initial-loading">
70
+ <div>
71
+ <div class="loading-spinner"></div>
72
+ <div class="loading-text">加载中...</div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+
77
+ <script type="module" src="/src/main.ts"></script>
78
+
79
+ <!-- 移除初始加载动画 -->
80
+ <script>
81
+ window.addEventListener('load', () => {
82
+ setTimeout(() => {
83
+ const loading = document.getElementById('initial-loading');
84
+ if (loading) {
85
+ loading.style.opacity = '0';
86
+ loading.style.transition = 'opacity 0.3s ease';
87
+ setTimeout(() => {
88
+ loading.remove();
89
+ }, 300);
90
+ }
91
+ }, 500);
92
+ });
93
+ </script>
94
+ </body>
95
+ </html>