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

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 +75 -27
  52. package/dist/index.es5.umd.js +75 -27
  53. package/dist/index.esm.js +78 -22
  54. package/dist/index.umd.cjs +78 -22
  55. package/package.json +4 -3
@@ -0,0 +1,288 @@
1
+ <template>
2
+ <div class="info-cards">
3
+ <el-row :gutter="16">
4
+ <el-col :xs="24"
5
+ :sm="12"
6
+ :md="8"
7
+ :lg="6"
8
+ :xl="6"
9
+ >
10
+ <el-card class="info-card" shadow="hover">
11
+ <template #header>
12
+ <div class="card-header">
13
+ <i class="el-icon-info"></i>
14
+ <span>SDK版本</span>
15
+ </div>
16
+ </template>
17
+ <div class="card-content">
18
+ <div class="version-info">
19
+ <div class="version-item">
20
+ <span class="label">当前版本:</span>
21
+ <el-tag type="primary" size="default">v1.0.0</el-tag>
22
+ </div>
23
+ <div class="version-item">
24
+ <span class="label">发布日期:</span>
25
+ <span class="value">2025-01-01</span>
26
+ </div>
27
+ <div class="version-item">
28
+ <span class="label">Unity版本:</span>
29
+ <span class="value">2022.3.0f1</span>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </el-card>
34
+ </el-col>
35
+
36
+ <el-col :xs="24"
37
+ :sm="12"
38
+ :md="8"
39
+ :lg="6"
40
+ :xl="6"
41
+ >
42
+ <el-card class="info-card" shadow="hover">
43
+ <template #header>
44
+ <div class="card-header">
45
+ <i class="el-icon-cpu"></i>
46
+ <span>系统信息</span>
47
+ </div>
48
+ </template>
49
+ <div class="card-content">
50
+ <div class="system-info">
51
+ <div class="system-item">
52
+ <span class="label">浏览器:</span>
53
+ <span class="value">{{ browserInfo }}</span>
54
+ </div>
55
+ <div class="system-item">
56
+ <span class="label">平台:</span>
57
+ <span class="value">{{ platformInfo }}</span>
58
+ </div>
59
+ <div class="system-item">
60
+ <span class="label">WebGL:</span>
61
+ <el-tag :type="webglSupported ? 'success' : 'danger'" size="default">
62
+ {{ webglSupported ? '支持' : '不支持' }}
63
+ </el-tag>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </el-card>
68
+ </el-col>
69
+
70
+ <el-col :xs="24"
71
+ :sm="12"
72
+ :md="8"
73
+ :lg="6"
74
+ :xl="6"
75
+ >
76
+ <el-card class="info-card" shadow="hover">
77
+ <template #header>
78
+ <div class="card-header">
79
+ <i class="el-icon-document"></i>
80
+ <span>快速文档</span>
81
+ </div>
82
+ </template>
83
+ <div class="card-content">
84
+ <div class="doc-links">
85
+ <el-link type="primary" size="default" >
86
+ <el-icon class="el-icon--left"><Link /></el-icon>API文档
87
+ </el-link>
88
+ <el-link type="primary" size="default" >
89
+ <el-icon class="el-icon--left"><VideoPlay /></el-icon>视频教程
90
+ </el-link>
91
+ <el-link type="primary" size="default" >
92
+ <el-icon class="el-icon--left"><ChatLineRound /></el-icon>技术支持
93
+ </el-link>
94
+ </div>
95
+ </div>
96
+ </el-card>
97
+ </el-col>
98
+
99
+ <el-col :xs="24"
100
+ :sm="12"
101
+ :md="8"
102
+ :lg="6"
103
+ :xl="6"
104
+ >
105
+ <el-card class="info-card" shadow="hover">
106
+ <template #header>
107
+ <div class="card-header">
108
+ <i class="el-icon-star-on"></i>
109
+ <span>功能特性</span>
110
+ </div>
111
+ </template>
112
+ <div class="card-content">
113
+ <div class="features">
114
+ <div class="feature-item">
115
+ <el-icon><Check /></el-icon>
116
+ <span>3D数字人渲染</span>
117
+ </div>
118
+ <div class="feature-item">
119
+ <el-icon><Check /></el-icon>
120
+ <span>智能语音播报</span>
121
+ </div>
122
+ <div class="feature-item">
123
+ <el-icon><Check /></el-icon>
124
+ <span>动作控制系统</span>
125
+ </div>
126
+ <div class="feature-item">
127
+ <el-icon><Check /></el-icon>
128
+ <span>多平台支持</span>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </el-card>
133
+ </el-col>
134
+ </el-row>
135
+ </div>
136
+ </template>
137
+
138
+ <script setup lang="ts">
139
+ import { ref, onMounted } from 'vue';
140
+ import { Check, Link, VideoPlay, ChatLineRound } from '@element-plus/icons-vue';
141
+ const browserInfo = ref('');
142
+ const platformInfo = ref('');
143
+ const webglSupported = ref(false);
144
+
145
+ function getBrowserInfo() {
146
+ const userAgent = navigator.userAgent;
147
+ if (userAgent.includes('Chrome')) {
148
+ browserInfo.value = 'Chrome';
149
+ } else if (userAgent.includes('Firefox')) {
150
+ browserInfo.value = 'Firefox';
151
+ } else if (userAgent.includes('Safari')) {
152
+ browserInfo.value = 'Safari';
153
+ } else if (userAgent.includes('Edge')) {
154
+ browserInfo.value = 'Edge';
155
+ } else {
156
+ browserInfo.value = 'Unknown';
157
+ }
158
+ }
159
+
160
+ function getPlatformInfo() {
161
+ const platform = navigator.platform;
162
+ if (platform.includes('Win')) {
163
+ platformInfo.value = 'Windows';
164
+ } else if (platform.includes('Mac')) {
165
+ platformInfo.value = 'macOS';
166
+ } else if (platform.includes('Linux')) {
167
+ platformInfo.value = 'Linux';
168
+ } else {
169
+ platformInfo.value = 'Unknown';
170
+ }
171
+ }
172
+
173
+ function checkWebGLSupport() {
174
+ try {
175
+ const canvas = document.createElement('canvas');
176
+ const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
177
+ webglSupported.value = !!gl;
178
+ } catch (e) {
179
+ webglSupported.value = false;
180
+ }
181
+ }
182
+
183
+ onMounted(() => {
184
+ getBrowserInfo();
185
+ getPlatformInfo();
186
+ checkWebGLSupport();
187
+ });
188
+ </script>
189
+
190
+ <style lang="scss" scoped>
191
+ .info-cards {
192
+ .info-card {
193
+ margin-bottom: 16px;
194
+ .card-header {
195
+ display: flex;
196
+ align-items: center;
197
+ gap: 8px;
198
+ font-weight: 600;
199
+ color: #2c3e50;
200
+ i {
201
+ font-size: 16px;
202
+ }
203
+ }
204
+ .card-content {
205
+ .version-info,
206
+ .system-info {
207
+ .version-item,
208
+ .system-item {
209
+ display: flex;
210
+ justify-content: space-between;
211
+ align-items: center;
212
+ margin-bottom: 8px;
213
+ .label {
214
+ font-size: 13px;
215
+ color: #606266;
216
+ }
217
+ .value {
218
+ font-size: 13px;
219
+ color: #2c3e50;
220
+ }
221
+ }
222
+ }
223
+ .doc-links {
224
+ display: flex;
225
+ flex-direction: column;
226
+ gap: 8px;
227
+ .el-link {
228
+ align-self: flex-start;
229
+ text-align: left;
230
+ &:hover {
231
+ color: #409eff;
232
+ }
233
+ }
234
+ }
235
+ .features {
236
+ .feature-item {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 8px;
240
+ margin-bottom: 8px;
241
+ font-size: 13px;
242
+ color: #2c3e50;
243
+ i {
244
+ color: #67c23a;
245
+ font-size: 14px;
246
+ }
247
+ }
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ // 移动端优化
254
+ @media screen and (max-width: 768px) {
255
+ .info-cards {
256
+ .info-card {
257
+ .card-header {
258
+ font-size: 14px;
259
+ i {
260
+ font-size: 14px;
261
+ }
262
+ }
263
+ .card-content {
264
+ .version-info,
265
+ .system-info {
266
+ .version-item,
267
+ .system-item {
268
+ .label,
269
+ .value {
270
+ font-size: 12px;
271
+ }
272
+ }
273
+ }
274
+ .doc-links {
275
+ .el-button {
276
+ font-size: 12px;
277
+ }
278
+ }
279
+ .features {
280
+ .feature-item {
281
+ font-size: 12px;
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ </style>
@@ -0,0 +1,339 @@
1
+ <template>
2
+ <div class="init-api">
3
+ <div class="api-description">
4
+ <el-alert
5
+ title="API说明"
6
+ type="info"
7
+ :closable="false"
8
+ show-icon
9
+ >
10
+ <template #default>
11
+ <div class="api-signature">
12
+ <code>initializeAvatar(avatarCode: string, cameraType?: AvatarCameraType): Promise&lt;IAvatarCallbackResponse&gt;</code>
13
+ </div>
14
+ <p>通过数字人编码加载数字人,token在SDK初始化时配置,无需在每次调用时传递</p>
15
+ <p class="api-features">
16
+ ✅ Promise-based异步API &nbsp;&nbsp;
17
+ ✅ 统一错误处理 &nbsp;&nbsp;
18
+ ✅ 详细响应信息
19
+ </p>
20
+ </template>
21
+ </el-alert>
22
+ </div>
23
+
24
+ <div class="api-controls">
25
+ <el-card shadow="hover" class="control-card">
26
+ <template #header>
27
+ <div class="card-header">
28
+ <span>初始化控制</span>
29
+ <el-tag v-if="sdkStatus.avatarLoaded" type="success" size="default">已加载</el-tag>
30
+ <el-tag v-else type="info" size="default">未加载</el-tag>
31
+ </div>
32
+ </template>
33
+
34
+ <div class="control-content">
35
+ <div class="status-info">
36
+ <el-row :gutter="16">
37
+ <el-col :span="12">
38
+ <div class="status-item">
39
+ <span class="status-label">Unity状态:</span>
40
+ <el-tag :type="sdkStatus.unityLoaded ? 'success' : 'info'" size="default">
41
+ {{ sdkStatus.unityLoaded ? '已加载' : '未加载' }}
42
+ </el-tag>
43
+ </div>
44
+ </el-col>
45
+ <el-col :span="12">
46
+ <div class="status-item">
47
+ <span class="status-label">Avatar状态:</span>
48
+ <el-tag :type="sdkStatus.avatarLoaded ? 'success' : 'info'" size="default">
49
+ {{ sdkStatus.avatarLoaded ? '已加载' : '未加载' }}
50
+ </el-tag>
51
+ </div>
52
+ </el-col>
53
+ </el-row>
54
+ </div>
55
+
56
+ <div class="config-info">
57
+ <el-descriptions :column="1" size="default" border>
58
+ <el-descriptions-item label="Token状态">
59
+ <el-tag :type="globalConfig.token ? 'success' : 'danger'" size="default">
60
+ {{ globalConfig.token ? '已配置' : '未配置' }}
61
+ </el-tag>
62
+ </el-descriptions-item>
63
+ <el-descriptions-item label="Avatar编码">
64
+ <span v-if="globalConfig.avatarCode" class="avatar-code">{{ globalConfig.avatarCode }}</span>
65
+ <el-tag v-else type="warning" size="default">未设置</el-tag>
66
+ </el-descriptions-item>
67
+ </el-descriptions>
68
+ </div>
69
+
70
+ <div class="action-buttons">
71
+ <el-button
72
+ type="primary"
73
+ size="default"
74
+ :loading="isLoading"
75
+ :disabled="sdkStatus.avatarLoaded || !globalConfig.token || !globalConfig.avatarCode"
76
+ @click="handleInitAvatar"
77
+ >
78
+ <template #icon>
79
+ <el-icon><VideoPlay /></el-icon>
80
+ </template>
81
+ {{ isLoading ? '初始化中...' : '初始化 Unity + Avatar' }}
82
+ </el-button>
83
+
84
+ <div class="button-tips">
85
+ <el-alert
86
+ v-if="!globalConfig.token || !globalConfig.avatarCode"
87
+ title="请先在全局配置中设置Token和Avatar Code"
88
+ type="warning"
89
+ :closable="false"
90
+ show-icon
91
+ />
92
+ <el-alert
93
+ v-else-if="sdkStatus.avatarLoaded"
94
+ title="Avatar已加载,请先卸载后再重新初始化"
95
+ type="info"
96
+ :closable="false"
97
+ show-icon
98
+ />
99
+ <el-alert
100
+ v-else-if="!sdkStatus.unityLoaded"
101
+ title="将同时初始化Unity实例和Avatar,首次加载需要一些时间"
102
+ type="info"
103
+ :closable="false"
104
+ show-icon
105
+ />
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </el-card>
110
+ </div>
111
+
112
+ <div class="api-result">
113
+ <el-card shadow="hover" class="result-card">
114
+ <template #header>
115
+ <div class="card-header">
116
+ <span>执行结果</span>
117
+ <el-link
118
+ size="default"
119
+ @click="clearResult"
120
+ >
121
+ <template #icon>
122
+ <el-icon><Refresh /></el-icon>
123
+ </template>
124
+ 清空
125
+ </el-link>
126
+ </div>
127
+ </template>
128
+
129
+ <div class="result-content">
130
+ <pre class="result-text">{{ result }}</pre>
131
+ </div>
132
+ </el-card>
133
+ </div>
134
+ </div>
135
+ </template>
136
+
137
+ <script setup lang="ts">
138
+ import { ref } from 'vue';
139
+ import { ElMessage } from 'element-plus';
140
+ import { VideoPlay, Refresh } from '@element-plus/icons-vue';
141
+
142
+ // 定义接口类型
143
+ interface ISDKStatus {
144
+ unityLoaded: boolean;
145
+ avatarLoaded: boolean;
146
+ canPlayMotion: boolean;
147
+ canBroadcast: boolean;
148
+ canGetMotion: boolean;
149
+ canControlBroadcast: boolean;
150
+ canControlCamera: boolean;
151
+ }
152
+
153
+ interface IGlobalConfig {
154
+ token: string;
155
+ avatarCode: string;
156
+ }
157
+
158
+ // 定义 props
159
+ const props = defineProps<{
160
+ sdkStatus: ISDKStatus;
161
+ globalConfig: IGlobalConfig;
162
+ }>();
163
+
164
+ // 定义 emits
165
+ const emit = defineEmits<{
166
+ 'init-avatar-with-unity': [params: { avatarCode: string }];
167
+ }>();
168
+
169
+ // 响应式数据
170
+ const result = ref('等待初始化操作...\n\n新版SDK特性:\n- token在初始化时配置,无需重复传递\n- Promise-based异步API\n- 统一的错误处理和响应格式\n- 完整的TypeScript类型支持');
171
+ const isLoading = ref(false);
172
+
173
+ // 处理初始化Avatar
174
+ async function handleInitAvatar(): Promise<void> {
175
+ if (!props.globalConfig.token || !props.globalConfig.avatarCode) {
176
+ result.value = '❌ 请先在全局配置中设置Token和Avatar Code';
177
+ ElMessage.warning('请先配置Token和Avatar Code');
178
+ return;
179
+ }
180
+
181
+ isLoading.value = true;
182
+ result.value = '🔄 正在初始化Unity实例和Avatar...\n📦 加载Unity引擎(约19MB)\n🤖 初始化数字人模型\n⚙️ 配置播报服务\n\n请稍等,这可能需要一些时间...';
183
+
184
+ try {
185
+ // 发送初始化请求
186
+ emit('init-avatar-with-unity', {
187
+ avatarCode: props.globalConfig.avatarCode
188
+ });
189
+
190
+ // 等待初始化完成的反馈
191
+ setTimeout(() => {
192
+ isLoading.value = false;
193
+ result.value = '✅ 初始化请求已发送\n📋 请查看右侧日志面板获取详细信息\n\n📝 操作说明:\n- 初始化成功后可以使用其他API功能\n- Unity实例将在中间预览窗口中显示\n- 所有操作日志会在右侧面板实时更新';
194
+ }, 1000);
195
+ } catch (error) {
196
+ isLoading.value = false;
197
+ const message = error instanceof Error ? error.message : String(error);
198
+ result.value = `❌ 初始化失败: ${message}\n\n🔍 可能的原因:\n- Token无效或已过期\n- 网络连接问题\n- Unity资源文件加载失败\n- Avatar编码不存在`;
199
+ ElMessage.error(`初始化失败: ${message}`);
200
+ }
201
+ }
202
+
203
+ // 清空结果
204
+ function clearResult(): void {
205
+ result.value = '等待初始化操作...\n\n新版SDK特性:\n- token在初始化时配置,无需重复传递\n- Promise-based异步API\n- 统一的错误处理和响应格式\n- 完整的TypeScript类型支持';
206
+ }
207
+ </script>
208
+
209
+ <style lang="scss" scoped>
210
+ .init-api {
211
+ .api-description {
212
+ margin-bottom: 20px;
213
+ .api-signature {
214
+ background-color: #f5f5f5;
215
+ padding: 8px 12px;
216
+ border-radius: 4px;
217
+ margin-bottom: 10px;
218
+ font-family: Monaco, Menlo, "Ubuntu Mono", monospace;
219
+ font-size: 12px;
220
+ border-left: 4px solid #409eff;
221
+ code {
222
+ color: #2c3e50;
223
+ font-weight: 600;
224
+ }
225
+ }
226
+ p {
227
+ margin: 5px 0;
228
+ color: #606266;
229
+ font-size: 14px;
230
+ &.api-features {
231
+ color: #67c23a;
232
+ font-weight: 500;
233
+ margin-top: 8px;
234
+ }
235
+ }
236
+ }
237
+ .api-controls {
238
+ margin-bottom: 20px;
239
+ .control-card {
240
+ .card-header {
241
+ display: flex;
242
+ justify-content: space-between;
243
+ align-items: center;
244
+ font-weight: 600;
245
+ }
246
+ .control-content {
247
+ .status-info {
248
+ margin-bottom: 15px;
249
+ .status-item {
250
+ display: flex;
251
+ align-items: center;
252
+ margin-bottom: 8px;
253
+ .status-label {
254
+ margin-right: 8px;
255
+ font-size: 13px;
256
+ color: #606266;
257
+ }
258
+ }
259
+ }
260
+ .config-info {
261
+ margin-bottom: 20px;
262
+ .avatar-code {
263
+ font-family: Monaco, Menlo, "Ubuntu Mono", monospace;
264
+ background-color: #f5f5f5;
265
+ padding: 2px 6px;
266
+ border-radius: 3px;
267
+ font-size: 12px;
268
+ }
269
+ }
270
+ .action-buttons {
271
+ .el-button {
272
+ width: 100%;
273
+ margin-bottom: 15px;
274
+ }
275
+ .button-tips {
276
+ :deep(.el-alert) {
277
+ margin-bottom: 10px;
278
+ &:last-child {
279
+ margin-bottom: 0;
280
+ }
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+ .api-result {
288
+ .result-card {
289
+ .card-header {
290
+ display: flex;
291
+ justify-content: space-between;
292
+ align-items: center;
293
+ font-weight: 600;
294
+ }
295
+ .result-content {
296
+ max-height: 300px;
297
+ overflow-y: auto;
298
+ .result-text {
299
+ margin: 0;
300
+ padding: 15px;
301
+ background-color: #f8f9fa;
302
+ border-radius: 4px;
303
+ border: 1px solid #e9ecef;
304
+ font-family: Monaco, Menlo, "Ubuntu Mono", monospace;
305
+ font-size: 13px;
306
+ line-height: 1.6;
307
+ color: #2c3e50;
308
+ white-space: pre-wrap;
309
+ word-wrap: break-word;
310
+ }
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ // 移动端优化
317
+ @media screen and (width <= 768px) {
318
+ .init-api {
319
+ .api-description {
320
+ .api-signature {
321
+ font-size: 11px;
322
+ padding: 6px 10px;
323
+ code {
324
+ word-break: break-all;
325
+ }
326
+ }
327
+ }
328
+ .control-content {
329
+ .status-info {
330
+ .el-row {
331
+ .el-col {
332
+ margin-bottom: 8px;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ </style>