af-mobile-client-vue3 1.4.53 → 1.4.54

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 (29) hide show
  1. package/package.json +1 -1
  2. package/src/App.vue +14 -2
  3. package/src/components/common/MateChat/MateChat.vue +248 -0
  4. package/src/components/common/MateChat/apiService.ts +254 -0
  5. package/src/components/common/MateChat/assets/035-avatar-13.svg +1 -0
  6. package/src/components/common/MateChat/components/MateChatHeader.vue +253 -0
  7. package/src/components/common/MateChat/components/PromptList/PromptList.vue +189 -0
  8. package/src/components/common/MateChat/components/PromptList/index.ts +1 -0
  9. package/src/components/common/MateChat/useMateChat.ts +212 -0
  10. package/src/components/common/otherCharge/ChargePrintSelectorAndRemarks.vue +137 -137
  11. package/src/components/common/otherCharge/CodePayment.vue +357 -357
  12. package/src/components/common/otherCharge/FileUploader.vue +602 -602
  13. package/src/components/common/otherCharge/GridFileUploader.vue +846 -846
  14. package/src/components/common/otherCharge/PaymentMethodSelector.vue +202 -202
  15. package/src/components/common/otherCharge/PaymentMethodSelectorCard.vue +45 -45
  16. package/src/components/common/otherCharge/ReceiptModal.vue +273 -273
  17. package/src/components/common/otherCharge/index.ts +43 -43
  18. package/src/components/data/OtherCharge/OtherChargeItemModal.vue +547 -547
  19. package/src/components/data/XFormGroup/doc/DeviceForm.vue +1 -1
  20. package/src/components/data/XFormGroup/doc/UserForm.vue +1 -1
  21. package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
  22. package/src/components/data/XReportGrid/print.js +184 -184
  23. package/src/utils/queryFormDefaultRangePicker.ts +57 -57
  24. package/src/utils/timeUtil.ts +27 -27
  25. package/src/views/component/MateChat/MateChatView.vue +30 -233
  26. package/src/views/component/XCellListView/index.vue +107 -138
  27. package/src/views/component/XFormGroupView/index.vue +78 -82
  28. package/src/views/component/XFormView/index.vue +41 -46
  29. package/src/views/component/MateChat/apiService.ts +0 -104
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "af-mobile-client-vue3",
3
3
  "type": "module",
4
- "version": "1.4.53",
4
+ "version": "1.4.54",
5
5
  "packageManager": "pnpm@10.13.1",
6
6
  "description": "Vue + Vite component lib",
7
7
  "engines": {
package/src/App.vue CHANGED
@@ -7,9 +7,21 @@ import { useHead } from '@unhead/vue'
7
7
  import {
8
8
  ConfigProvider as VanConfigProvider,
9
9
  } from 'vant/es'
10
- import { computed } from 'vue'
10
+ import { computed, getCurrentInstance } from 'vue'
11
+ import { useRoute } from 'vue-router'
11
12
  import { appDescription, appName } from './constants'
12
13
 
14
+ const instance = getCurrentInstance()
15
+ const route = useRoute()
16
+
17
+ // 是否使用 fullPath 作为 component key
18
+ // 配置:是否使用 fullPath 作为 router-view 的 component key
19
+ // 该配置作用为:区分keep-alive缓存组件,为true时 如果跳转相同的缓存组件但是url携带参数不同 就会进行区分。反之则会只会根据路由名称进行命中
20
+ // 普通走基座的项目无需进行设置,只有特殊的单项目部署的服务 需要固定缓存顶层组件时进行开启,例如微信-开启方式在自己项目的main.ts中增加 app.config.globalProperties.$useFullPathKey = false
21
+ const useFullPathKey = computed(() => {
22
+ return instance?.appContext.config.globalProperties.$useFullPathKey ?? true
23
+ })
24
+
13
25
  useHead({
14
26
  title: appName,
15
27
  meta: [
@@ -48,7 +60,7 @@ const mode = computed(() => {
48
60
  <router-view v-slot="{ Component }">
49
61
  <section class="app-wrapper">
50
62
  <keep-alive :include="keepAliveRouteNames" :max="5">
51
- <component :is="Component" :key="$route.fullPath" />
63
+ <component :is="Component" :key="useFullPathKey ? route.fullPath : undefined" />
52
64
  </keep-alive>
53
65
  </section>
54
66
  </router-view>
@@ -0,0 +1,248 @@
1
+ <script setup lang="ts">
2
+ import liuliLogo from '@af-mobile-client-vue3/assets/img/component/liuli.png'
3
+ import userAvatarImg from '@af-mobile-client-vue3/components/common/MateChat/assets/035-avatar-13.svg'
4
+ import MateChatHeader from '@af-mobile-client-vue3/components/common/MateChat/components/MateChatHeader.vue'
5
+ import { PromptList } from '@af-mobile-client-vue3/components/common/MateChat/components/PromptList'
6
+ // MateChat ai 对话相关
7
+ import { Button as VanButton } from 'vant'
8
+ import { defineProps, toRefs, withDefaults } from 'vue'
9
+ import { useMateChat } from './useMateChat'
10
+ import 'vant/es/image-preview/style'
11
+
12
+ interface MateChatPromptItem {
13
+ value: string
14
+ label: string
15
+ iconConfig?: {
16
+ name: string
17
+ color?: string
18
+ }
19
+ desc?: string
20
+ }
21
+
22
+ interface MateChatProps {
23
+ /**
24
+ * 介绍文案,不传或为空数组时不展示 McIntroduction
25
+ */
26
+ description?: string[]
27
+ /**
28
+ * 首屏推荐问题列表
29
+ */
30
+ introPrompt?: MateChatPromptItem[]
31
+ /**
32
+ * 底部快捷问题列表
33
+ */
34
+ simplePrompt?: MateChatPromptItem[]
35
+ /**
36
+ * 客服名称,默认:智能能客服
37
+ */
38
+ serviceName?: string
39
+ /**
40
+ * 是否使用流式对话
41
+ */
42
+ useStream?: boolean
43
+ }
44
+
45
+ const props = withDefaults(defineProps<MateChatProps>(), {
46
+ description: () => [],
47
+ introPrompt: () => [],
48
+ simplePrompt: () => [],
49
+ serviceName: '智能客服',
50
+ useStream: false,
51
+ })
52
+
53
+ const { description, introPrompt, simplePrompt, serviceName, useStream } = toRefs(props)
54
+
55
+ const {
56
+ startPage,
57
+ inputValue,
58
+ messages,
59
+ newConversation,
60
+ onSubmit,
61
+ } = useMateChat({
62
+ useStream: useStream.value,
63
+ })
64
+ </script>
65
+
66
+ <template>
67
+ <div id="mate-chat-view">
68
+ <McLayout class="chat-card">
69
+ <MateChatHeader
70
+ v-if="!startPage"
71
+ :logo-image="liuliLogo"
72
+ :title="serviceName"
73
+ />
74
+ <McLayoutContent
75
+ v-if="startPage"
76
+ style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px"
77
+ >
78
+ <McIntroduction
79
+ v-if="description && description.length"
80
+ :logo-img="liuliLogo"
81
+ :title="serviceName"
82
+ :sub-title="`Hi,我是${serviceName}`"
83
+ :description="description"
84
+ class="McIntroduction"
85
+ />
86
+ <PromptList
87
+ v-if="introPrompt && introPrompt.length"
88
+ :list="introPrompt"
89
+ @item-click="onSubmit($event.label)"
90
+ />
91
+ </McLayoutContent>
92
+ <McLayoutContent v-else class="content-container">
93
+ <template v-for="(msg, idx) in messages" :key="idx">
94
+ <McBubble
95
+ v-if="msg.from === 'user'"
96
+ :content="msg.content"
97
+ align="right"
98
+ :avatar-config="{ imgSrc: userAvatarImg }"
99
+ />
100
+ <McBubble
101
+ v-else-if="msg.from === 'service'"
102
+ :content="msg.content"
103
+ :avatar-config="{ imgSrc: userAvatarImg }"
104
+ />
105
+ <McBubble v-else :content="msg.content" :avatar-config="{ imgSrc: liuliLogo }" :loading="msg.loading">
106
+ <McMarkdownCard
107
+ :content="msg.content"
108
+ :typing="!useStream"
109
+ />
110
+ </McBubble>
111
+ </template>
112
+ </McLayoutContent>
113
+ <div class="shortcut" style="display: flex; align-items: center; gap: 8px">
114
+ <PromptList
115
+ v-if="!startPage && simplePrompt && simplePrompt.length"
116
+ :list="simplePrompt"
117
+ direction="horizontal"
118
+ class="shortcut-prompt"
119
+ style="flex: 1"
120
+ @item-click="onSubmit($event.label)"
121
+ />
122
+ <VanButton
123
+ style="margin-left: auto"
124
+ icon="add"
125
+ title="新建对话"
126
+ size="small"
127
+ round
128
+ @click="newConversation"
129
+ />
130
+ </div>
131
+ <McLayoutSender>
132
+ <McInput
133
+ :value="inputValue"
134
+ placeholder="请输入您的问题,我会为您解答"
135
+ :max-length="2000"
136
+ @change="(e) => (inputValue = e)"
137
+ @submit="onSubmit"
138
+ />
139
+ </McLayoutSender>
140
+ </McLayout>
141
+ </div>
142
+ </template>
143
+
144
+ <style scoped lang="less">
145
+ #mate-chat-view {
146
+ /* 外层渐变背景容器 */
147
+ width: 100%;
148
+ min-height: 100vh;
149
+ background: linear-gradient(to bottom, #a8f0ed 0%, #a8e6cf 8%, #c5b3ff 12%, #e0b3ff 40%, #fff4b8 60%, #ffb8d1 90%);
150
+ /* background: linear-gradient(to bottom, #d0c9ff 0%, #e6d6f0 8%, #f1dbea 12%, #c8dcfb 40%, #abc6f6 60%, #87aefe 90%); */
151
+ padding: 20px;
152
+ display: flex;
153
+ justify-content: center;
154
+ align-items: flex-start;
155
+ box-sizing: border-box;
156
+
157
+ /* 中间白色圆角卡片 */
158
+ .chat-card {
159
+ width: 100%;
160
+ max-width: 1200px;
161
+ height: calc(100vh - 40px);
162
+ background: #ffffff;
163
+ border-radius: 24px;
164
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
165
+ overflow: hidden;
166
+ display: flex;
167
+ flex-direction: column;
168
+ transition: all 0.3s ease;
169
+ padding: 20px;
170
+ gap: 8px;
171
+ }
172
+
173
+ .chat-card:hover {
174
+ box-shadow: 0 25px 70px rgba(0, 0, 0, 0.2);
175
+ }
176
+
177
+ /* 移动端适配 */
178
+ @media (max-width: 768px) {
179
+ padding: 8px;
180
+ .chat-card {
181
+ height: calc(100vh - 16px);
182
+ border-radius: 16px;
183
+ padding: 8px;
184
+ }
185
+ }
186
+
187
+ .content-container {
188
+ display: flex;
189
+ flex-direction: column;
190
+ gap: 8px;
191
+ overflow: auto;
192
+ }
193
+
194
+ .input-foot-wrapper {
195
+ display: flex;
196
+ justify-content: space-between;
197
+ align-items: center;
198
+ width: 100%;
199
+ height: 100%;
200
+ margin-right: 8px;
201
+
202
+ .input-foot-left {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: 8px;
206
+
207
+ span {
208
+ font-size: 14px;
209
+ line-height: 18px;
210
+ color: #252b3a;
211
+ cursor: pointer;
212
+ }
213
+
214
+ .input-foot-dividing-line {
215
+ width: 1px;
216
+ height: 14px;
217
+ background-color: #d7d8da;
218
+ }
219
+
220
+ .input-foot-maxlength {
221
+ font-size: 14px;
222
+ color: #71757f;
223
+ }
224
+ }
225
+
226
+ .input-foot-right {
227
+ .demo-button-content {
228
+ font-size: 14px;
229
+ }
230
+
231
+ & > *:not(:first-child) {
232
+ margin-left: 8px;
233
+ }
234
+ }
235
+ }
236
+ :deep(.mc-header-logo-container img) {
237
+ width: 32px;
238
+ height: 32px;
239
+ }
240
+
241
+ .McIntroduction {
242
+ :deep(.mc-introduction-logo-container img) {
243
+ width: 64px;
244
+ height: 64px;
245
+ }
246
+ }
247
+ }
248
+ </style>
@@ -0,0 +1,254 @@
1
+ import type { AxiosInstance } from 'axios'
2
+ import axios from 'axios'
3
+
4
+ /**
5
+ * 聊天消息接口
6
+ */
7
+ export interface ChatMessage {
8
+ role: 'user' | 'assistant' | 'system'
9
+ content: string
10
+ }
11
+
12
+ /**
13
+ * 聊天请求参数接口
14
+ */
15
+ export interface ChatCompletionsRequest {
16
+ chatId: string
17
+ stream: boolean
18
+ detail: boolean
19
+ variables: {
20
+ uid: string
21
+ name: string
22
+ }
23
+ messages: ChatMessage[]
24
+ }
25
+
26
+ /**
27
+ * 聊天响应使用情况接口
28
+ */
29
+ export interface ChatUsage {
30
+ prompt_tokens: number
31
+ completion_tokens: number
32
+ total_tokens: number
33
+ }
34
+
35
+ /**
36
+ * 聊天响应选择项接口
37
+ */
38
+ export interface ChatChoice {
39
+ message: {
40
+ role: 'assistant'
41
+ content: string
42
+ }
43
+ finish_reason: string
44
+ index: number
45
+ }
46
+
47
+ /**
48
+ * 聊天响应接口
49
+ */
50
+ export interface ChatCompletionsResponse {
51
+ id: string
52
+ model: string
53
+ usage: ChatUsage
54
+ choices: ChatChoice[]
55
+ }
56
+
57
+ /**
58
+ * 业务层聊天结果
59
+ */
60
+ export interface ChatBizResult {
61
+ /**
62
+ * normal: 普通回复
63
+ * transfer: 转人工
64
+ */
65
+ type: 'normal' | 'transfer'
66
+ /**
67
+ * 大模型原始返回内容
68
+ */
69
+ content: string
70
+ }
71
+
72
+ /**
73
+ * 流式对话回调
74
+ */
75
+ export interface ChatStreamCallbacks {
76
+ /**
77
+ * 每次收到 FastGPT SSE 的增量内容时触发
78
+ */
79
+ onMessage?: (chunk: string) => void
80
+ /**
81
+ * 流结束时触发(包括收到 [DONE] 或正常读取结束)
82
+ */
83
+ onComplete?: () => void
84
+ /**
85
+ * 请求或解析发生异常时触发
86
+ */
87
+ onError?: (error: unknown) => void
88
+ }
89
+
90
+ /**
91
+ * 创建独立的 axios 实例,不经过拦截器
92
+ */
93
+ const chatAxiosInstance: AxiosInstance = axios.create({
94
+ baseURL: import.meta.env.VITE_APP_API_BASE_URL || '',
95
+ timeout: 20000,
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ },
99
+ })
100
+
101
+ /**
102
+ * 发送聊天请求
103
+ * @param content 用户输入的内容
104
+ * @returns Promise<ChatCompletionsResponse>
105
+ */
106
+ export function chatCompletions(content: string): Promise<ChatCompletionsResponse> {
107
+ const requestData: ChatCompletionsRequest = {
108
+ chatId: 'chatId13333113',
109
+ stream: false,
110
+ detail: false,
111
+ variables: {
112
+ uid: 'asdfadsfasfd2323',
113
+ name: '张三',
114
+ },
115
+ messages: [
116
+ {
117
+ role: 'user',
118
+ content,
119
+ },
120
+ ],
121
+ }
122
+
123
+ return chatAxiosInstance.post<ChatCompletionsResponse>(
124
+ '/v1/chat/completions',
125
+ requestData,
126
+ {
127
+ headers: {
128
+ Authorization: 'Bearer fastgpt-f5FO1pkucnrEJvQsP4g8N9V3mUZNI396eiuef5PJjYty4vJztufB1',
129
+ },
130
+ },
131
+ ).then(response => response.data)
132
+ }
133
+
134
+ /**
135
+ * 封装后的业务聊天请求
136
+ * - 负责从大模型返回中解析出业务含义(普通回复 / 转人工)
137
+ * - UI 层只需要根据 type 决定渲染哪种气泡
138
+ */
139
+ export async function chatBiz(content: string): Promise<ChatBizResult> {
140
+ const response = await chatCompletions(content)
141
+
142
+ if (!response.choices || response.choices.length === 0) {
143
+ throw new Error('响应数据格式错误')
144
+ }
145
+
146
+ const text = response.choices[0].message.content
147
+
148
+ try {
149
+ const parsed = JSON.parse(text) as { msgType?: string }
150
+ if (parsed.msgType === 'transfer') {
151
+ return {
152
+ type: 'transfer',
153
+ content: text,
154
+ }
155
+ }
156
+ }
157
+ catch {
158
+ // 忽略解析错误,按普通文本处理
159
+ }
160
+
161
+ return {
162
+ type: 'normal',
163
+ content: text,
164
+ }
165
+ }
166
+
167
+ /**
168
+ * 使用 FastGPT /v1/chat/completions 的 stream=true 进行流式对话
169
+ * 参考官方文档: https://doc.fastgpt.io/docs/introduction/development/openapi/chat
170
+ */
171
+ export async function chatCompletionsStream(
172
+ content: string,
173
+ callbacks: ChatStreamCallbacks,
174
+ ): Promise<void> {
175
+ const { onMessage, onComplete, onError } = callbacks
176
+
177
+ const requestData: ChatCompletionsRequest = {
178
+ chatId: 'chatId13333113',
179
+ stream: true,
180
+ detail: false,
181
+ variables: {
182
+ uid: 'asdfadsfasfd2323',
183
+ name: '张三',
184
+ },
185
+ messages: [
186
+ {
187
+ role: 'user',
188
+ content,
189
+ },
190
+ ],
191
+ }
192
+
193
+ try {
194
+ const baseUrl = import.meta.env.VITE_APP_API_BASE_URL || ''
195
+ const res = await fetch(`${baseUrl}/v1/chat/completions`, {
196
+ method: 'POST',
197
+ headers: {
198
+ 'Content-Type': 'application/json',
199
+ 'Authorization': 'Bearer fastgpt-f5FO1pkucnrEJvQsP4g8N9V3mUZNI396eiuef5PJjYty4vJztufB1',
200
+ },
201
+ body: JSON.stringify(requestData),
202
+ })
203
+
204
+ if (!res.ok || !res.body) {
205
+ throw new Error(`请求失败: ${res.status}`)
206
+ }
207
+
208
+ const reader = res.body.getReader()
209
+ const decoder = new TextDecoder('utf-8')
210
+ let buffer = ''
211
+
212
+ while (true) {
213
+ const { done, value } = await reader.read()
214
+ if (done)
215
+ break
216
+
217
+ buffer += decoder.decode(value, { stream: true })
218
+ const lines = buffer.split('\n')
219
+ buffer = lines.pop() ?? ''
220
+
221
+ for (const rawLine of lines) {
222
+ const line = rawLine.trim()
223
+ if (!line.startsWith('data:'))
224
+ continue
225
+
226
+ const dataStr = line.slice(5).trim()
227
+ if (!dataStr || dataStr === '[DONE]') {
228
+ onComplete?.()
229
+ return
230
+ }
231
+
232
+ try {
233
+ const json = JSON.parse(dataStr) as {
234
+ choices?: Array<{ delta?: { content?: string } }>
235
+ }
236
+ const delta = json.choices?.[0]?.delta
237
+ const chunkText = delta?.content || ''
238
+ if (chunkText) {
239
+ onMessage?.(chunkText)
240
+ }
241
+ }
242
+ catch (e) {
243
+ console.error('解析数据失败', e, dataStr)
244
+ }
245
+ }
246
+ }
247
+
248
+ onComplete?.()
249
+ }
250
+ catch (error) {
251
+ console.error('FastGPT 流式请求异常', error)
252
+ onError?.(error)
253
+ }
254
+ }
@@ -0,0 +1 @@
1
+ <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1764664883478" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17459" xmlns:xlink="http://www.w3.org/1999/xlink" width="192" height="192"><path d="M896 803.94V992H128v-188.06a128 128 0 0 1 96.96-124.18L384 640a57.878 57.878 0 0 0 32-51.78V480h192v108.22A57.878 57.878 0 0 0 640 640l159.04 39.76A128 128 0 0 1 896 803.94z" fill="#FDC8A2" p-id="17460"></path><path d="M608 480v101.34l-12.8 17.06c-1.02 1.36-2.08 2.66-3.2 3.92A63.984 63.984 0 0 1 544 624h-64a63.984 63.984 0 0 1-48-21.68c-1.12-1.26-2.18-2.56-3.2-3.92l-12.8-17.06V480z" fill="#FDBF92" p-id="17461"></path><path d="M873.72 731.78a128.2 128.2 0 0 0-74.68-52.02L640 640c-23.12 57.76-75.56 86.66-128 86.66s-104.88-28.9-128-86.66l-159.04 39.76A128 128 0 0 0 128 803.94V992h768v-188.06a127.624 127.624 0 0 0-22.28-72.16z" fill="#E9D6BB" p-id="17462"></path><path d="M672 240v186.66a64.034 64.034 0 0 1-12.8 38.4l-64 85.34c-1.02 1.36-2.08 2.66-3.2 3.92A63.984 63.984 0 0 1 544 576h-64a63.984 63.984 0 0 1-48-21.68c-1.12-1.26-2.18-2.56-3.2-3.92l-64-85.34a64.034 64.034 0 0 1-12.8-38.4V240c0-88.36 71.64-144 160-144 44.18 0 84.18 13.92 113.14 38.86S672 195.82 672 240z" fill="#FDC8A2" p-id="17463"></path><path d="M428 336a28 28 0 1 1 28-28 28.03 28.03 0 0 1-28 28zM596 336a28 28 0 1 1 28-28 28.03 28.03 0 0 1-28 28z" fill="#91563A" p-id="17464"></path><path d="M344 368h8v-112h-8a56 56 0 0 0-56 56 56 56 0 0 0 56 56zM680 256h-8v112h8a56 56 0 0 0 56-56 56 56 0 0 0-56-56z" fill="#FDB683" p-id="17465"></path><path d="M608 128l64 128V144a64 64 0 0 0-64-64zM352 256V128h64z" fill="#2B4266" p-id="17466"></path><path d="M608 80v48H352a79.75 79.75 0 0 1 23.44-56.56 81.26 81.26 0 0 1 12.08-9.94 79.324 79.324 0 0 1 29.62-12.12A80.848 80.848 0 0 1 432 48h124.22A57.878 57.878 0 0 1 608 80z" fill="#34507B" p-id="17467"></path><path d="M880 864h32v128h-32zM802.92 664.238l-157.2-39.3A41.854 41.854 0 0 1 624 588.22v-49.554l48-64.012a80.568 80.568 0 0 0 16-48v-43.11a71.988 71.988 0 0 0 0-143.088V144a80.102 80.102 0 0 0-70.528-79.42A73.4 73.4 0 0 0 556.222 32H432c-27.334 0-51.164 14.36-51.164 14.36l6.34 12.662L408.368 112H370a63.432 63.432 0 0 1 10.8-22.4l-25.6-19.22A95.2 95.2 0 0 0 336 128v112.456a71.988 71.988 0 0 0 0 143.088v43.116a80.578 80.578 0 0 0 16 48l48 64v49.56a41.634 41.634 0 0 1-21.718 36.718l-157.2 39.298A143.8 143.8 0 0 0 112 803.94V992h32v-188.06A111.8 111.8 0 0 1 161.366 744l51.32 51.318 22.628-22.628-53.064-53.07a111.828 111.828 0 0 1 46.6-24.338l146.1-36.526c26.208 52.094 77.538 83.904 137.05 83.904s110.842-31.8 137.058-83.904l146.102 36.528a111.8 111.8 0 0 1 46.6 24.336l-53.064 53.066 22.628 22.628L862.634 744A111.8 111.8 0 0 1 880 803.94V830h32v-26.06a143.786 143.786 0 0 0-109.08-139.702zM720 312a40.076 40.076 0 0 1-32 39.2v-78.4a40.076 40.076 0 0 1 32 39.2z m-64-168v44.222l-32-64v-25.48A48.084 48.084 0 0 1 656 144z m-64-59.904V112h-21.168l-19.2-48S577.5 63 592 84.096zM506.832 112l-19.2-48h29.536l19.2 48z m-53.664-48l19.2 48h-29.536l-18.988-47.47c2.688-0.33 29.324-0.53 29.324-0.53z m-63.056 80L368 188.222V144zM304 312a40.076 40.076 0 0 1 32-39.2v78.4a40.076 40.076 0 0 1-32-39.2z m64 114.66v-166.882L425.888 144h172.224L656 259.778v166.882a48.342 48.342 0 0 1-9.6 28.8s-65.536 87.308-66.4 88.286A47.964 47.964 0 0 1 544 560h-64a48 48 0 0 1-36.04-16.306c-0.822-0.926-66.354-88.228-66.354-88.228A48.35 48.35 0 0 1 368 426.66z m144 284c-36.948 0-83.13-17.29-107.694-64.73A73.42 73.42 0 0 0 432 588.22v-12.242A79.974 79.974 0 0 0 480 592h64a80.018 80.018 0 0 0 48-16.014v12.234a73.79 73.79 0 0 0 27.712 57.676C595.152 693.36 548.956 710.66 512 710.66z" p-id="17468"></path><path d="M512 784c-69.65 0-97.6-39.308-98.76-40.982l-26.552 17.858C388.188 763.126 424.444 816 512 816s123.812-52.874 125.312-55.124l-26.624-17.752C610.414 743.534 582.622 784 512 784zM240 899.43c-19.884-20.152-29.754-54.956-32.2-69.98l-31.6 5.078c0.546 3.426 13.22 79.016 63.8 104.214V992h32v-176h-32zM784 899.43V816h-32v176h32v-53.258c50.578-25.2 63.252-100.788 63.8-104.214l-31.6-5.078c-2.446 15.024-12.316 49.828-32.2 69.98zM456 308a28 28 0 1 0-28 28 28.03 28.03 0 0 0 28-28zM596 336a28 28 0 1 0-28-28 28.03 28.03 0 0 0 28 28zM496 320h32v64h-32zM565.738 446.936l-11.476-29.872c-0.364 0.142-36.8 13.942-72.568 10.14l-3.388 31.82a152.936 152.936 0 0 0 16.2 0.834 220.662 220.662 0 0 0 71.232-12.922z" p-id="17469"></path></svg>