fmode-ng 0.0.41 → 0.0.43
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.
- package/LICENSE.md +8 -0
- package/esm2022/fmode-ng.mjs +10 -5
- package/esm2022/lib/aigc/agent/agent.prompt.mjs +10 -122
- package/esm2022/lib/aigc/agent/index.mjs +10 -2
- package/esm2022/lib/aigc/avatar/avatar.module.mjs +10 -45
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/avatar.role.mjs +10 -2
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/comp-avatar-particle.component.mjs +10 -315
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/index.mjs +10 -3
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/role-points.class.mjs +10 -57
- package/esm2022/lib/aigc/avatar/comp-avatar-role-image/comp-avatar-role-image.component.mjs +10 -97
- package/esm2022/lib/aigc/avatar/comp-avatar-role-video/comp-avatar-role-video.component.mjs +10 -104
- package/esm2022/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs +10 -111
- package/esm2022/lib/aigc/avatar/index.mjs +10 -8
- package/esm2022/lib/aigc/avatar/interface-avatar-role.mjs +10 -2
- package/esm2022/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs +8 -166
- package/esm2022/lib/aigc/chat/chat-header-area/comp-header-area.component.mjs +10 -36
- package/esm2022/lib/aigc/chat/chat-header-area/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/chat-list/chat-list.component.mjs +8 -141
- package/esm2022/lib/aigc/chat/chat-list/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/chat-message-area/comp-message-area.component.mjs +10 -40
- package/esm2022/lib/aigc/chat/chat-message-area/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/chat-message-card/comp-message-card.component.mjs +10 -92
- package/esm2022/lib/aigc/chat/chat-message-card/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/chat-modal-input/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.mjs +8 -207
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +10 -236
- package/esm2022/lib/aigc/chat/chat-panel/chat-panel.component.mjs +10 -137
- package/esm2022/lib/aigc/chat/comp-role-prompt/comp-role-prompt.component.mjs +10 -69
- package/esm2022/lib/aigc/chat/comp-role-prompt/index.mjs +10 -2
- package/esm2022/lib/aigc/chat/index.mjs +10 -8
- package/esm2022/lib/aigc/comp-markdown-preview/clipboard.service.mjs +10 -82
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-parse.mjs +8 -269
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.component.mjs +10 -51
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.module.mjs +10 -24
- package/esm2022/lib/aigc/comp-markdown-preview/plugins/md-mathjax/index.mjs +10 -94
- package/esm2022/lib/aigc/index.mjs +10 -13
- package/esm2022/lib/aigc/service-fmai/fmai.service.mjs +10 -21
- package/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs +8 -736
- package/esm2022/lib/aigc/service-fmai/service-chat/chat.service.mjs +8 -181
- package/esm2022/lib/aigc/service-fmai/service-chat/index.mjs +10 -7
- package/esm2022/lib/aigc/service-fmai/service-chat/mask-list.mjs +9 -194
- package/esm2022/lib/aigc/service-fmai/service-chat/pipes/chat-content.pipe.mjs +10 -27
- package/esm2022/lib/aigc/service-fmai/service-chat/pipes/hidexml.pipe.mjs +10 -27
- package/esm2022/lib/aigc/service-fmai/service-chat/utilnow.pipe.mjs +10 -68
- package/esm2022/lib/aigc/service-fmai/service-imagine/imagine.service.mjs +8 -229
- package/esm2022/lib/aigc/service-fmai/service-imagine/index.mjs +10 -2
- package/esm2022/lib/aigc/voice/audio.player.mjs +10 -52
- package/esm2022/lib/aigc/voice/class-asr.mjs +8 -79
- package/esm2022/lib/aigc/voice/fmode-voice.service.mjs +8 -501
- package/esm2022/lib/aigc/voice/index.mjs +10 -3
- package/esm2022/lib/aigc/voice/lib/pcm2wav.mjs +10 -38
- package/esm2022/lib/aigc/voice/lib/resample.mjs +10 -34
- package/esm2022/lib/aigc/voice/stream.player.mjs +10 -0
- package/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs +8 -233
- package/esm2022/lib/aigc/voice/tts/index.mjs +10 -2
- package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.component.mjs +10 -190
- package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.module.mjs +10 -33
- package/esm2022/lib/map/index.mjs +10 -4
- package/esm2022/lib/map/map.module.mjs +10 -61
- package/esm2022/lib/map/page-loca-scatter/page-loca-scatter.component.mjs +10 -110
- package/esm2022/lib/map/page-map.start/page-map.start.component.mjs +8 -98
- package/esm2022/lib/map/page-plan-route/page-plan-route.component.mjs +8 -100
- package/esm2022/lib/nova-cloud/index.mjs +10 -2
- package/esm2022/lib/nova-cloud/nova-cloud.service.mjs +10 -148
- package/esm2022/lib/platform/cross.service.mjs +10 -63
- package/esm2022/lib/platform/index.mjs +10 -2
- package/esm2022/lib/social/index.mjs +10 -2
- package/esm2022/lib/social/wechat/wechat-jssdk.service.mjs +8 -236
- package/esm2022/lib/storage/comp-hwobs-manager/hwobs-manager.component.mjs +10 -59
- package/esm2022/lib/storage/index.mjs +10 -5
- package/esm2022/lib/storage/service-hwobs/hwobs.service.mjs +8 -130
- package/esm2022/lib/storage/service-upload/index.mjs +10 -2
- package/esm2022/lib/storage/service-upload/nova-upload.service.mjs +8 -462
- package/esm2022/lib/storage/service-upload/util-file-md5.mjs +10 -28
- package/esm2022/lib/storage/storage.module.mjs +10 -41
- package/esm2022/lib/user/account/account.service.mjs +10 -221
- package/esm2022/lib/user/captcha/captcha.component.mjs +10 -135
- package/esm2022/lib/user/comp-user-avatar/comp-user-avatar.component.mjs +10 -62
- package/esm2022/lib/user/index.mjs +10 -17
- package/esm2022/lib/user/login/auth.guard.mjs +10 -28
- package/esm2022/lib/user/login/auth.service.mjs +8 -373
- package/esm2022/lib/user/login/login.component.mjs +10 -913
- package/esm2022/lib/user/modal-user-login/modal-user-login.component.mjs +10 -273
- package/esm2022/lib/user/profile/auth-profile.guard.mjs +10 -27
- package/esm2022/lib/user/profile/auth-profile.service.mjs +10 -122
- package/esm2022/lib/user/profile/profile-bind/profile-bind.component.mjs +10 -115
- package/esm2022/lib/user/profile/profile.module.mjs +10 -57
- package/esm2022/lib/user/staff/index.mjs +10 -4
- package/esm2022/lib/user/staff/staff.guard.mjs +10 -26
- package/esm2022/lib/user/staff/staff.module.mjs +10 -18
- package/esm2022/lib/user/staff/staff.service.mjs +10 -85
- package/esm2022/lib/user/user-name.pipe.mjs +10 -29
- package/esm2022/lib/user/user.module.mjs +10 -106
- package/esm2022/lib/video/fm-video/fm-video.component.mjs +10 -67
- package/esm2022/lib/video/index.mjs +10 -2
- package/esm2022/public-api.mjs +10 -13
- package/fesm2022/fmode-ng.mjs +7 -8895
- package/fesm2022/fmode-ng.mjs.map +1 -1
- package/lib/aigc/voice/fmode-voice.service.d.ts +18 -1
- package/lib/aigc/voice/stream.player.d.ts +10 -0
- package/lib/aigc/voice/tts/fmode-tts-class.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,236 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// import { AccountService } from 'projects/nova-aigc/src/modules/account/account.service';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import { IonButton, IonContent, IonIcon, IonInput, IonItem, IonList, IonModal, IonPopover, IonTextarea, IonToolbar } from '@ionic/angular/standalone';
|
|
12
|
-
import { CommonModule } from '@angular/common';
|
|
13
|
-
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
14
|
-
import { NzModalModule } from 'ng-zorro-antd/modal';
|
|
15
|
-
import { ModalAudioMessageComponent } from "./modal-audio-message/modal-audio-message.component";
|
|
16
|
-
import * as i0 from "@angular/core";
|
|
17
|
-
import * as i1 from "@ionic/angular";
|
|
18
|
-
import * as i2 from "@angular/router";
|
|
19
|
-
import * as i3 from "../../service-fmai/service-imagine/imagine.service";
|
|
20
|
-
import * as i4 from "../../service-fmai/service-chat";
|
|
21
|
-
import * as i5 from "ng-zorro-antd/message";
|
|
22
|
-
import * as i6 from "@angular/common";
|
|
23
|
-
import * as i7 from "@angular/forms";
|
|
24
|
-
import * as i8 from "ng-zorro-antd/modal";
|
|
25
|
-
export class FmChatModalInput {
|
|
26
|
-
closeAudio() {
|
|
27
|
-
this.audioComp?.cancel();
|
|
28
|
-
this.isAudioModal = false;
|
|
29
|
-
}
|
|
30
|
-
constructor(toastCtrl, alertCtrl, navCtrl, router, imagineServ,
|
|
31
|
-
// private authServ:AuthService,
|
|
32
|
-
chatServ,
|
|
33
|
-
// private account:AccountService,
|
|
34
|
-
route, messages) {
|
|
35
|
-
this.toastCtrl = toastCtrl;
|
|
36
|
-
this.alertCtrl = alertCtrl;
|
|
37
|
-
this.navCtrl = navCtrl;
|
|
38
|
-
this.router = router;
|
|
39
|
-
this.imagineServ = imagineServ;
|
|
40
|
-
this.chatServ = chatServ;
|
|
41
|
-
this.route = route;
|
|
42
|
-
this.messages = messages;
|
|
43
|
-
this.errorText = ``;
|
|
44
|
-
this.isAudioModal = false;
|
|
45
|
-
//分享弹框组件
|
|
46
|
-
this.isShare = false;
|
|
47
|
-
// this.chatServ.getChatSession().then(()=>{
|
|
48
|
-
// console.log(this.chatServ.chatList);
|
|
49
|
-
// })
|
|
50
|
-
this.user = Parse.User.current();
|
|
51
|
-
}
|
|
52
|
-
ngOnInit() {
|
|
53
|
-
this.loadModel();
|
|
54
|
-
// console.log(this.chat);
|
|
55
|
-
}
|
|
56
|
-
// ngAfterViewInit(): void {
|
|
57
|
-
// console.log(this.chat)
|
|
58
|
-
// }
|
|
59
|
-
async loadModel() {
|
|
60
|
-
let model = this.chat?.role?.get("model");
|
|
61
|
-
await this.chatServ.loadModelList(model);
|
|
62
|
-
}
|
|
63
|
-
async setMessageImage() {
|
|
64
|
-
// let url = `https://file-cloud.fmode.cn/Svehl6FceL/20240515/061503671.jpeg`;
|
|
65
|
-
let url = await this.imagineServ.getimg();
|
|
66
|
-
this.chat.userImage = url;
|
|
67
|
-
console.log(this.chat?.userImage);
|
|
68
|
-
// content是数组,添加
|
|
69
|
-
// content非数组,重组
|
|
70
|
-
}
|
|
71
|
-
onKeyDown(event) {
|
|
72
|
-
// 检查是否按下了Ctrl键和Enter键
|
|
73
|
-
if (event.ctrlKey && event.key === 'Enter') {
|
|
74
|
-
// 执行相应的逻辑
|
|
75
|
-
console.log('Ctrl+Enter 被按下');
|
|
76
|
-
this.sendMessage();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
async sendMessage() {
|
|
80
|
-
// 检测用户登录情况
|
|
81
|
-
// let isLoginLock = await this.authServ.checkLoginLock()
|
|
82
|
-
// if(!isLoginLock) return false
|
|
83
|
-
// 检测余额及模型付费限制
|
|
84
|
-
// let payCheck = await this.checkBalance()
|
|
85
|
-
// if(!payCheck) return false
|
|
86
|
-
// 检测用户输入内容空值
|
|
87
|
-
if (!this.chat.userInput) {
|
|
88
|
-
this.errorText = `内容不能为空`;
|
|
89
|
-
let toast = await this.toastCtrl.create({
|
|
90
|
-
message: this.errorText,
|
|
91
|
-
position: "top",
|
|
92
|
-
icon: 'alert',
|
|
93
|
-
color: "warning-circle",
|
|
94
|
-
duration: 1000
|
|
95
|
-
});
|
|
96
|
-
toast.present();
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// 正常发送消息
|
|
100
|
-
// this.chat.isTalkMode=true; // 开启说话模式
|
|
101
|
-
this.chat?.sendMessage(this.chat?.userInput, this.chat?.userImage, (msg) => { }, {
|
|
102
|
-
onSSMLComplete: (voice) => {
|
|
103
|
-
console.log(voice);
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
this.chat.userInput = ``;
|
|
107
|
-
this.chat.userImage = ``;
|
|
108
|
-
}
|
|
109
|
-
async checkBalance() {
|
|
110
|
-
if (!this.chatServ?.currentModel?.get("payLimit"))
|
|
111
|
-
return true; // 模型是否开启付费限制
|
|
112
|
-
// 校验账户余额
|
|
113
|
-
let billing = await this.account.getBilling();
|
|
114
|
-
// let price = await this.calcPrice()
|
|
115
|
-
let price = 10;
|
|
116
|
-
if (billing?.credit?.balance < price) {
|
|
117
|
-
let alert = await this.alertCtrl.create({
|
|
118
|
-
header: "注意",
|
|
119
|
-
subHeader: "您的余额不足,请充值后解锁高级模型",
|
|
120
|
-
buttons: [
|
|
121
|
-
{
|
|
122
|
-
role: "cancel",
|
|
123
|
-
text: "取消"
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
role: "destructive",
|
|
127
|
-
text: "充值",
|
|
128
|
-
handler: () => {
|
|
129
|
-
// 待更换成原地弹窗,原地付费,避免页面跳转
|
|
130
|
-
this.router.navigateByUrl("/account/billing");
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
]
|
|
134
|
-
});
|
|
135
|
-
alert.present();
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
//查询问答内容分享数据表:ChatShare
|
|
141
|
-
async getChatShare() {
|
|
142
|
-
this.user = Parse.User.current();
|
|
143
|
-
let query = new Parse.Query('ChatShare');
|
|
144
|
-
query.equalTo('user', Parse.User.current().id);
|
|
145
|
-
query.equalTo('session', this.chat?.sessionId);
|
|
146
|
-
let chatShare = await query.first();
|
|
147
|
-
// console.log(chatShare);
|
|
148
|
-
}
|
|
149
|
-
async toggleChatShare() {
|
|
150
|
-
//获取ChatShare数据表
|
|
151
|
-
let query = new Parse.Query('ChatShare');
|
|
152
|
-
query.equalTo('user', Parse.User.current().id);
|
|
153
|
-
query.equalTo('role', this.chat?.role.id);
|
|
154
|
-
query.equalTo('session', this.chat?.sessionId);
|
|
155
|
-
// query.equalTo('messageList', this.chat?.messageList);
|
|
156
|
-
query.select('objectId');
|
|
157
|
-
let share = await query.first();
|
|
158
|
-
// console.log(share);
|
|
159
|
-
//如果id不存在,在数据表内创建新的记录
|
|
160
|
-
if (!share?.id) {
|
|
161
|
-
let obj = Parse.Object.extend('ChatShare');
|
|
162
|
-
share = new obj();
|
|
163
|
-
share.set('user', {
|
|
164
|
-
"__type": "Pointer",
|
|
165
|
-
"className": "_User",
|
|
166
|
-
"objectId": Parse.User.current()?.id
|
|
167
|
-
});
|
|
168
|
-
share.set('session', {
|
|
169
|
-
"__type": "Pointer",
|
|
170
|
-
"className": "ChatSession",
|
|
171
|
-
"objectId": this.chat?.sessionId
|
|
172
|
-
});
|
|
173
|
-
share.set('role', {
|
|
174
|
-
"__type": "Pointer",
|
|
175
|
-
"className": "AvatarRole",
|
|
176
|
-
"objectId": this.chat?.role.id
|
|
177
|
-
});
|
|
178
|
-
share.set('company', {
|
|
179
|
-
"__type": "Pointer",
|
|
180
|
-
"className": "Company",
|
|
181
|
-
"objectId": "E4KpGvTEto"
|
|
182
|
-
});
|
|
183
|
-
share.set('messageList', this.chat?.messageList);
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
//id存在,点击分享按钮执行更新messageList数据的操作
|
|
187
|
-
share.set('messageList', this.chat?.messageList);
|
|
188
|
-
}
|
|
189
|
-
await share.save();
|
|
190
|
-
this.getChatShare();
|
|
191
|
-
}
|
|
192
|
-
chatShareSuccessMessage() {
|
|
193
|
-
this.messages.success('分享成功');
|
|
194
|
-
}
|
|
195
|
-
showShare() {
|
|
196
|
-
this.isShare = true;
|
|
197
|
-
}
|
|
198
|
-
handleOkShare() {
|
|
199
|
-
// console.log(this.chat);
|
|
200
|
-
// console.log(this.chat?.sessionId);
|
|
201
|
-
// console.log(this.chat?.messageList);
|
|
202
|
-
// console.log(this.chat?.role.id);
|
|
203
|
-
this.toggleChatShare();
|
|
204
|
-
this.chatShareSuccessMessage();
|
|
205
|
-
this.isShare = false;
|
|
206
|
-
}
|
|
207
|
-
handleCancelShare() {
|
|
208
|
-
this.isShare = false;
|
|
209
|
-
}
|
|
210
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmChatModalInput, deps: [{ token: i1.ToastController }, { token: i1.AlertController }, { token: i1.NavController }, { token: i2.Router }, { token: i3.ImagineService }, { token: i4.ChatService }, { token: i2.ActivatedRoute }, { token: i5.NzMessageService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
211
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FmChatModalInput, isStandalone: true, selector: "fm-chat-modal-input", inputs: { chat: "chat", message: "message", role: "role" }, viewQueries: [{ propertyName: "audioComp", first: true, predicate: ModalAudioMessageComponent, descendants: true }], ngImport: i0, template: "<ion-toolbar>\n <ion-item class=\"button-item\" lines=\"none\">\n <!-- \u8BBE\u7F6E -->\n <!-- <ion-button fill=\"outline\" slot=\"start\">\n <ion-icon name=\"settings-outline\"></ion-icon> \n </ion-button> -->\n <ng-container *ngFor=\"let button of chat?.leftButtons\">\n <ion-button style=\"--padding-start:10px;--padding-end:10px;\"\n shape=\"round\" *ngIf=\"button.show()\" fill=\"outline\" [title]=\"button?.title\" slot=\"start\" (click)=\"button.onClick()\">\n <ion-icon [name]=\"button?.icon\" [slot]=\"button?.showTitle?'start':'icon-only'\"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor=\"let button of chat?.role?.get('buttons')\">\n <ion-button shape=\"round\" (click)=\"chatServ.doButtonAction(button)\" fill=\"outline\" slot=\"start\">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n <!--\u5206\u4EAB\u6309\u94AE-->\n <ion-button shape=\"round\" *ngIf=\"chat?.messageList?.length>1\" (click)=\"showShare()\" fill=\"outline\" title=\"\u5206\u4EAB\" slot=\"end\">\n <ion-icon name=\"share-social-outline\"></ion-icon>\n </ion-button>\n <!-- <button nz-button *ngIf=\"chat?.messageList?.length>1\"\n nzType=\"primary\" title=\"\u5206\u4EAB\" (click)=\"showShare()\" style=\"width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;\"> <span class=\"iconfont icon-fenxiang\" style=\"color: #4588ff;\"></span></button>\n -->\n <ion-modal [isOpen]=\"isShare\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"handleCancelShare()\">\u53D6\u6D88</ion-button>\n </ion-buttons>\n <ion-title>\u5BF9\u8BDD\u5206\u4EAB</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"handleOkShare()\">\u5206\u4EAB</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <div class=\"popup-content\">\n <div *ngFor=\"let message of chat?.messageList\">\n <!-- \u5934\u50CF -->\n <div class=\"item-row user\" *ngIf=\"message?.role!='system'\">\n <div>\n <nz-avatar *ngIf=\"message?.role!='user'\" [nzSrc]=\"(chat?.role?.get('avatar') || chat?.role?.get('thumb') || 'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png')+'?'+'x-image-process=image/resize,m_fixed,w_100'+'&imageView2/1/w/32/h/32'\"></nz-avatar>\n </div>\n <div class=\"user-question\">\n <app-comp-user-avatar [user]=\"user\" *ngIf=\"message?.role=='user'\"></app-comp-user-avatar>\n </div>\n </div>\n <!-- \u5185\u5BB9 -->\n <div class=\"message-wrapper\">\n <div class=\"message-content-user\">\n <div class=\"user-message\" *ngIf=\"message?.role === 'user'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-role\">\n <div class=\"role-message\" *ngIf=\"message?.role !== 'user' && message?.role !== 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-system\">\n <div class=\"system-message\" *ngIf=\"message?.role === 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class=\"chat-time\" *ngIf=\"message?.createdAt\" [ngClass]=\"{'role-time': message?.role !== 'user'}\">\n <span>{{message?.createdAt | date:\"dd/MM/yyyy, HH/mm/ss a\"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n <nz-modal *ngIf=\"false\"\n [(nzVisible)]=\"isShare\"\n nzTitle=\"\u95EE\u7B54\u5206\u4EAB\"\n nzCentered\n nzOkText=\"\u5206\u4EAB\"\n nzCancelText=\"\u53D6\u6D88\"\n (nzOnCancel)=\"handleCancelShare()\"\n (nzOnOk)=\"handleOkShare()\"\n >\n <ng-container *nzModalContent>\n <div class=\"popup-content\">\n <div *ngFor=\"let message of chat?.messageList\">\n <!-- \u5934\u50CF -->\n <div class=\"item-row user\" *ngIf=\"message?.role!='system'\">\n <div>\n <nz-avatar *ngIf=\"message?.role!='user'\" [nzSrc]=\"(chat?.role?.get('thumb') || 'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png')+'?'+'x-image-process=image/resize,m_fixed,w_100'+'&imageView2/1/w/32/h/32'\"></nz-avatar>\n </div>\n <div class=\"user-question\">\n <app-comp-user-avatar [user]=\"user\" *ngIf=\"message?.role=='user'\"></app-comp-user-avatar>\n </div>\n </div>\n <!-- \u5185\u5BB9 -->\n <div class=\"message-wrapper\">\n <div class=\"message-content-user\">\n <div class=\"user-message\" *ngIf=\"message?.role === 'user'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-role\">\n <div class=\"role-message\" *ngIf=\"message?.role !== 'user' && message?.role !== 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-system\">\n <div class=\"system-message\" *ngIf=\"message?.role === 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class=\"chat-time\" *ngIf=\"message?.createdAt\" [ngClass]=\"{'role-time': message?.role !== 'user'}\">\n <span>{{message?.createdAt | date:\"dd/MM/yyyy, HH/mm/ss a\"}}</span>\n </div>\n </div>\n </div> \n </ng-container>\n </nz-modal>\n\n <!-- \u56FE\u7247 -->\n <ion-button shape=\"round\" *ngIf=\"chatServ?.currentModel?.get('config')?.imageEnabled\" fill=\"outline\" slot=\"end\" (click)=\"setMessageImage()\">\n <ion-icon name=\"image-outline\"></ion-icon>\n </ion-button>\n <!-- \u6A21\u578B -->\n <ion-button shape=\"round\" fill=\"outline\" slot=\"end\" id=\"model-button\">\n <ion-icon name=\"chevron-down-outline\"></ion-icon>\n {{chatServ?.currentModel?.get&&chatServ?.currentModel?.get(\"name\")||\"\u98DE\u78014.0\"}}\n </ion-button>\n <ion-popover trigger=\"model-button\" [dismissOnSelect]=\"true\">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor=\"let model of chatServ.modelList\">\n <ion-item (click)=\"chatServ.currentModel = model\" [button]=\"true\" [detail]=\"false\">\n {{model?.get(\"name\")}}\n <ion-note slot=\"end\">{{model?.get(\"credit\")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n\n </ion-item>\n\n <ion-item class=\"input-item\" lines=\"none\">\n <!-- \u8BED\u97F3\u6D88\u606F\u8F93\u5165 -->\n <ng-container *ngIf=\"chat?.isVoiceInputMode\">\n <!-- \u5207\u6362\u6587\u672C\u8F93\u5165 -->\n <ion-button class=\"btn-input-change\" color=\"primary\" (click)=\"chat.isVoiceInputMode=false\" shape=\"round\" size=\"large\">\n <ion-icon name=\"chatbox-ellipses-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n \n <div class=\"btn-voice-start\" (click)=\"isAudioModal=true\">\n <span>\n \u70B9\u51FB\u8BB2\u8BDD\n </span> \n </div>\n </ng-container>\n\n <!-- \u6587\u672C\u6D88\u606F\u8F93\u5165 -->\n <ng-container *ngIf=\"!chat?.isVoiceInputMode\">\n <!-- \u5207\u6362\u8BED\u97F3\u8F93\u5165 -->\n <ion-button [style.display]=\"chat.isTexting?'none':'flex'\" class=\"btn-input-change\" color=\"primary\" *ngIf=\"chat?.role?.get('voiceConfig')\" (click)=\"chat.isVoiceInputMode=true\" shape=\"round\" size=\"large\">\n <ion-icon name=\"mic-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n\n <!-- \u6587\u672C\u8F93\u5165\u533A\u57DF -->\n <ion-textarea *ngIf=\"chat\" (keydown)=\"onKeyDown($event)\"\n [errorText]=\"errorText\"\n [(ngModel)]=\"chat.userInput\"\n (ionFocus)=\"chat.isTexting=true\"\n (ionBlur)=\"chat.isTexting=false\"\n [autoGrow]=\"true\" shape=\"round\" fill=\"outline\"\n label=\"Ctrl + Enter \u53D1\u9001\u6D88\u606F\" placeholder=\"\u8BF7\u8F93\u5165\u60A8\u7684\u63D0\u793A\u8BCD\"\n labelPlacement=\"floating\"></ion-textarea>\n \n <!-- \u6587\u672C\u53D1\u9001\u6309\u94AE -->\n <ion-button color=\"primary\" shape=\"round\" size=\"large\" (click)=\"sendMessage()\">\n <ion-icon name=\"paper-plane-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n<!-- \u8BED\u97F3\u6D88\u606F\u8F93\u5165\uFF1A\u5F39\u51FA\u533A\u57DF -->\n<ion-modal #audioModal [isOpen]=\"isAudioModal\" (willDismiss)=\"closeAudio()\" [initialBreakpoint]=\"0.35\" [breakpoints]=\"[0, 0.35, 0.5]\">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf=\"isAudioModal\" [chat]=\"chat\" [modal]=\"audioModal\"></fm-modal-audio-message>\n </ng-template>\n</ion-modal>", styles: ["@charset \"UTF-8\";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i6.DatePipe, name: "date" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "ngmodule", type: NzModalModule }, { kind: "component", type: i8.NzModalComponent, selector: "nz-modal", inputs: ["nzMask", "nzMaskClosable", "nzCloseOnNavigation", "nzVisible", "nzClosable", "nzOkLoading", "nzOkDisabled", "nzCancelDisabled", "nzCancelLoading", "nzKeyboard", "nzNoAnimation", "nzCentered", "nzDraggable", "nzContent", "nzFooter", "nzZIndex", "nzWidth", "nzWrapClassName", "nzClassName", "nzStyle", "nzTitle", "nzCloseIcon", "nzMaskStyle", "nzBodyStyle", "nzOkText", "nzCancelText", "nzOkType", "nzOkDanger", "nzIconType", "nzModalType", "nzAutofocus", "nzOnOk", "nzOnCancel"], outputs: ["nzOnOk", "nzOnCancel", "nzAfterOpen", "nzAfterClose", "nzVisibleChange"], exportAs: ["nzModal"] }, { kind: "directive", type: i8.NzModalContentDirective, selector: "[nzModalContent]", exportAs: ["nzModalContent"] }, { kind: "component", type:
|
|
212
|
-
//
|
|
213
|
-
ModalAudioMessageComponent, selector: "fm-modal-audio-message", inputs: ["chat", "modal"] }] }); }
|
|
214
|
-
}
|
|
215
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FmChatModalInput, decorators: [{
|
|
216
|
-
type: Component,
|
|
217
|
-
args: [{ selector: 'fm-chat-modal-input', standalone: true, imports: [
|
|
218
|
-
CommonModule, FormsModule, ReactiveFormsModule,
|
|
219
|
-
RouterModule,
|
|
220
|
-
IonToolbar, IonItem, IonButton, IonList, IonModal,
|
|
221
|
-
IonInput, IonIcon, IonTextarea, IonPopover, IonContent,
|
|
222
|
-
NzModalModule,
|
|
223
|
-
//
|
|
224
|
-
ModalAudioMessageComponent
|
|
225
|
-
], template: "<ion-toolbar>\n <ion-item class=\"button-item\" lines=\"none\">\n <!-- \u8BBE\u7F6E -->\n <!-- <ion-button fill=\"outline\" slot=\"start\">\n <ion-icon name=\"settings-outline\"></ion-icon> \n </ion-button> -->\n <ng-container *ngFor=\"let button of chat?.leftButtons\">\n <ion-button style=\"--padding-start:10px;--padding-end:10px;\"\n shape=\"round\" *ngIf=\"button.show()\" fill=\"outline\" [title]=\"button?.title\" slot=\"start\" (click)=\"button.onClick()\">\n <ion-icon [name]=\"button?.icon\" [slot]=\"button?.showTitle?'start':'icon-only'\"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor=\"let button of chat?.role?.get('buttons')\">\n <ion-button shape=\"round\" (click)=\"chatServ.doButtonAction(button)\" fill=\"outline\" slot=\"start\">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n <!--\u5206\u4EAB\u6309\u94AE-->\n <ion-button shape=\"round\" *ngIf=\"chat?.messageList?.length>1\" (click)=\"showShare()\" fill=\"outline\" title=\"\u5206\u4EAB\" slot=\"end\">\n <ion-icon name=\"share-social-outline\"></ion-icon>\n </ion-button>\n <!-- <button nz-button *ngIf=\"chat?.messageList?.length>1\"\n nzType=\"primary\" title=\"\u5206\u4EAB\" (click)=\"showShare()\" style=\"width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;\"> <span class=\"iconfont icon-fenxiang\" style=\"color: #4588ff;\"></span></button>\n -->\n <ion-modal [isOpen]=\"isShare\">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"handleCancelShare()\">\u53D6\u6D88</ion-button>\n </ion-buttons>\n <ion-title>\u5BF9\u8BDD\u5206\u4EAB</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"handleOkShare()\">\u5206\u4EAB</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class=\"ion-padding\">\n <div class=\"popup-content\">\n <div *ngFor=\"let message of chat?.messageList\">\n <!-- \u5934\u50CF -->\n <div class=\"item-row user\" *ngIf=\"message?.role!='system'\">\n <div>\n <nz-avatar *ngIf=\"message?.role!='user'\" [nzSrc]=\"(chat?.role?.get('avatar') || chat?.role?.get('thumb') || 'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png')+'?'+'x-image-process=image/resize,m_fixed,w_100'+'&imageView2/1/w/32/h/32'\"></nz-avatar>\n </div>\n <div class=\"user-question\">\n <app-comp-user-avatar [user]=\"user\" *ngIf=\"message?.role=='user'\"></app-comp-user-avatar>\n </div>\n </div>\n <!-- \u5185\u5BB9 -->\n <div class=\"message-wrapper\">\n <div class=\"message-content-user\">\n <div class=\"user-message\" *ngIf=\"message?.role === 'user'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-role\">\n <div class=\"role-message\" *ngIf=\"message?.role !== 'user' && message?.role !== 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-system\">\n <div class=\"system-message\" *ngIf=\"message?.role === 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class=\"chat-time\" *ngIf=\"message?.createdAt\" [ngClass]=\"{'role-time': message?.role !== 'user'}\">\n <span>{{message?.createdAt | date:\"dd/MM/yyyy, HH/mm/ss a\"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n <nz-modal *ngIf=\"false\"\n [(nzVisible)]=\"isShare\"\n nzTitle=\"\u95EE\u7B54\u5206\u4EAB\"\n nzCentered\n nzOkText=\"\u5206\u4EAB\"\n nzCancelText=\"\u53D6\u6D88\"\n (nzOnCancel)=\"handleCancelShare()\"\n (nzOnOk)=\"handleOkShare()\"\n >\n <ng-container *nzModalContent>\n <div class=\"popup-content\">\n <div *ngFor=\"let message of chat?.messageList\">\n <!-- \u5934\u50CF -->\n <div class=\"item-row user\" *ngIf=\"message?.role!='system'\">\n <div>\n <nz-avatar *ngIf=\"message?.role!='user'\" [nzSrc]=\"(chat?.role?.get('thumb') || 'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png')+'?'+'x-image-process=image/resize,m_fixed,w_100'+'&imageView2/1/w/32/h/32'\"></nz-avatar>\n </div>\n <div class=\"user-question\">\n <app-comp-user-avatar [user]=\"user\" *ngIf=\"message?.role=='user'\"></app-comp-user-avatar>\n </div>\n </div>\n <!-- \u5185\u5BB9 -->\n <div class=\"message-wrapper\">\n <div class=\"message-content-user\">\n <div class=\"user-message\" *ngIf=\"message?.role === 'user'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-role\">\n <div class=\"role-message\" *ngIf=\"message?.role !== 'user' && message?.role !== 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class=\"message-content-system\">\n <div class=\"system-message\" *ngIf=\"message?.role === 'system'\">\n <div class=\"item-content\">\n <!-- <fm-markdown-preview *ngIf=\"!message?.complete\" class=\"content-style\" [content]=\"message?.content\" [render]=\"false\"></fm-markdown-preview> -->\n <fm-markdown-preview *ngIf=\"message?.complete\" class=\"content-style\" [content]=\"message?.content\"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class=\"chat-time\" *ngIf=\"message?.createdAt\" [ngClass]=\"{'role-time': message?.role !== 'user'}\">\n <span>{{message?.createdAt | date:\"dd/MM/yyyy, HH/mm/ss a\"}}</span>\n </div>\n </div>\n </div> \n </ng-container>\n </nz-modal>\n\n <!-- \u56FE\u7247 -->\n <ion-button shape=\"round\" *ngIf=\"chatServ?.currentModel?.get('config')?.imageEnabled\" fill=\"outline\" slot=\"end\" (click)=\"setMessageImage()\">\n <ion-icon name=\"image-outline\"></ion-icon>\n </ion-button>\n <!-- \u6A21\u578B -->\n <ion-button shape=\"round\" fill=\"outline\" slot=\"end\" id=\"model-button\">\n <ion-icon name=\"chevron-down-outline\"></ion-icon>\n {{chatServ?.currentModel?.get&&chatServ?.currentModel?.get(\"name\")||\"\u98DE\u78014.0\"}}\n </ion-button>\n <ion-popover trigger=\"model-button\" [dismissOnSelect]=\"true\">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor=\"let model of chatServ.modelList\">\n <ion-item (click)=\"chatServ.currentModel = model\" [button]=\"true\" [detail]=\"false\">\n {{model?.get(\"name\")}}\n <ion-note slot=\"end\">{{model?.get(\"credit\")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n\n </ion-item>\n\n <ion-item class=\"input-item\" lines=\"none\">\n <!-- \u8BED\u97F3\u6D88\u606F\u8F93\u5165 -->\n <ng-container *ngIf=\"chat?.isVoiceInputMode\">\n <!-- \u5207\u6362\u6587\u672C\u8F93\u5165 -->\n <ion-button class=\"btn-input-change\" color=\"primary\" (click)=\"chat.isVoiceInputMode=false\" shape=\"round\" size=\"large\">\n <ion-icon name=\"chatbox-ellipses-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n \n <div class=\"btn-voice-start\" (click)=\"isAudioModal=true\">\n <span>\n \u70B9\u51FB\u8BB2\u8BDD\n </span> \n </div>\n </ng-container>\n\n <!-- \u6587\u672C\u6D88\u606F\u8F93\u5165 -->\n <ng-container *ngIf=\"!chat?.isVoiceInputMode\">\n <!-- \u5207\u6362\u8BED\u97F3\u8F93\u5165 -->\n <ion-button [style.display]=\"chat.isTexting?'none':'flex'\" class=\"btn-input-change\" color=\"primary\" *ngIf=\"chat?.role?.get('voiceConfig')\" (click)=\"chat.isVoiceInputMode=true\" shape=\"round\" size=\"large\">\n <ion-icon name=\"mic-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n\n <!-- \u6587\u672C\u8F93\u5165\u533A\u57DF -->\n <ion-textarea *ngIf=\"chat\" (keydown)=\"onKeyDown($event)\"\n [errorText]=\"errorText\"\n [(ngModel)]=\"chat.userInput\"\n (ionFocus)=\"chat.isTexting=true\"\n (ionBlur)=\"chat.isTexting=false\"\n [autoGrow]=\"true\" shape=\"round\" fill=\"outline\"\n label=\"Ctrl + Enter \u53D1\u9001\u6D88\u606F\" placeholder=\"\u8BF7\u8F93\u5165\u60A8\u7684\u63D0\u793A\u8BCD\"\n labelPlacement=\"floating\"></ion-textarea>\n \n <!-- \u6587\u672C\u53D1\u9001\u6309\u94AE -->\n <ion-button color=\"primary\" shape=\"round\" size=\"large\" (click)=\"sendMessage()\">\n <ion-icon name=\"paper-plane-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n<!-- \u8BED\u97F3\u6D88\u606F\u8F93\u5165\uFF1A\u5F39\u51FA\u533A\u57DF -->\n<ion-modal #audioModal [isOpen]=\"isAudioModal\" (willDismiss)=\"closeAudio()\" [initialBreakpoint]=\"0.35\" [breakpoints]=\"[0, 0.35, 0.5]\">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf=\"isAudioModal\" [chat]=\"chat\" [modal]=\"audioModal\"></fm-modal-audio-message>\n </ng-template>\n</ion-modal>", styles: ["@charset \"UTF-8\";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n"] }]
|
|
226
|
-
}], ctorParameters: () => [{ type: i1.ToastController }, { type: i1.AlertController }, { type: i1.NavController }, { type: i2.Router }, { type: i3.ImagineService }, { type: i4.ChatService }, { type: i2.ActivatedRoute }, { type: i5.NzMessageService }], propDecorators: { audioComp: [{
|
|
227
|
-
type: ViewChild,
|
|
228
|
-
args: [ModalAudioMessageComponent]
|
|
229
|
-
}], chat: [{
|
|
230
|
-
type: Input
|
|
231
|
-
}], message: [{
|
|
232
|
-
type: Input
|
|
233
|
-
}], role: [{
|
|
234
|
-
type: Input
|
|
235
|
-
}] } });
|
|
236
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtaW5wdXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZm1vZGUtbmcvc3JjL2xpYi9haWdjL2NoYXQvY2hhdC1tb2RhbC1pbnB1dC9tb2RhbC1pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9mbW9kZS1uZy9zcmMvbGliL2FpZ2MvY2hhdC9jaGF0LW1vZGFsLWlucHV0L21vZGFsLWlucHV0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFnQyxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUFFLGNBQWMsRUFBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQVksZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0YsT0FBTyxFQUFFLFNBQVMsRUFBbUIsTUFBTSxpQ0FBaUMsQ0FBQztBQUM3RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFOUQsMENBQTBDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQiwyRkFBMkY7QUFDM0YsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDekQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9EQUFvRCxDQUFDO0FBQ3BGLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN0SixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxxREFBcUQsQ0FBQzs7Ozs7Ozs7OztBQWlCakcsTUFBTSxPQUFPLGdCQUFnQjtJQVUzQixVQUFVO1FBQ1IsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsWUFBWSxHQUFDLEtBQUssQ0FBQztJQUMxQixDQUFDO0lBSUQsWUFDVSxTQUF5QixFQUN6QixTQUF5QixFQUN6QixPQUFxQixFQUNyQixNQUFhLEVBQ2IsV0FBMEI7SUFDbEMsZ0NBQWdDO0lBQ3pCLFFBQW9CO0lBQzNCLGtDQUFrQztJQUMxQixLQUFvQixFQUNwQixRQUEwQjtRQVQxQixjQUFTLEdBQVQsU0FBUyxDQUFnQjtRQUN6QixjQUFTLEdBQVQsU0FBUyxDQUFnQjtRQUN6QixZQUFPLEdBQVAsT0FBTyxDQUFjO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQU87UUFDYixnQkFBVyxHQUFYLFdBQVcsQ0FBZTtRQUUzQixhQUFRLEdBQVIsUUFBUSxDQUFZO1FBRW5CLFVBQUssR0FBTCxLQUFLLENBQWU7UUFDcEIsYUFBUSxHQUFSLFFBQVEsQ0FBa0I7UUFwQnBDLGNBQVMsR0FBVSxFQUFFLENBQUE7UUFFckIsaUJBQVksR0FBVyxLQUFLLENBQUM7UUFxTDdCLFFBQVE7UUFDUixZQUFPLEdBQUcsS0FBSyxDQUFDO1FBbEtkLDRDQUE0QztRQUM1Qyx5Q0FBeUM7UUFDekMsS0FBSztRQUNMLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUVuQyxDQUFDO0lBQ0QsUUFBUTtRQUNOLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNqQiwwQkFBMEI7SUFDNUIsQ0FBQztJQUVELDRCQUE0QjtJQUM1QiwyQkFBMkI7SUFDM0IsSUFBSTtJQUVKLEtBQUssQ0FBQyxTQUFTO1FBQ2IsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3pDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDMUMsQ0FBQztJQUVELEtBQUssQ0FBQyxlQUFlO1FBQ25CLDhFQUE4RTtRQUM5RSxJQUFJLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNsQyxnQkFBZ0I7UUFDaEIsZ0JBQWdCO0lBQ2xCLENBQUM7SUFHRCxTQUFTLENBQUMsS0FBbUI7UUFDM0Isc0JBQXNCO1FBQ3RCLElBQUksS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQzNDLFVBQVU7WUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDOUIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBQ0QsS0FBSyxDQUFDLFdBQVc7UUFFZixXQUFXO1FBQ1gseURBQXlEO1FBQ3pELGdDQUFnQztRQUVoQyxjQUFjO1FBQ2QsMkNBQTJDO1FBQzNDLDZCQUE2QjtRQUU3QixhQUFhO1FBQ2IsSUFBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLENBQUM7WUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUE7WUFDekIsSUFBSSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztnQkFDdEMsT0FBTyxFQUFDLElBQUksQ0FBQyxTQUFTO2dCQUN0QixRQUFRLEVBQUMsS0FBSztnQkFDZCxJQUFJLEVBQUMsT0FBTztnQkFDWixLQUFLLEVBQUMsZ0JBQWdCO2dCQUN0QixRQUFRLEVBQUMsSUFBSTthQUNkLENBQUMsQ0FBQTtZQUNGLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoQixPQUFNO1FBQ1IsQ0FBQztRQUVELFNBQVM7UUFDVCx1Q0FBdUM7UUFDdkMsSUFBSSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUMsQ0FBQyxHQUFHLEVBQUMsRUFBRSxHQUFDLENBQUMsRUFBQztZQUN6RSxjQUFjLEVBQUMsQ0FBQyxLQUFTLEVBQUMsRUFBRTtnQkFDMUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNwQixDQUFDO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFBO1FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQTtJQUMxQixDQUFDO0lBQ0QsS0FBSyxDQUFDLFlBQVk7UUFDaEIsSUFBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQSxDQUFDLGFBQWE7UUFDM0UsU0FBUztRQUNULElBQUksT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM5QyxxQ0FBcUM7UUFDckMsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2YsSUFBSSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sR0FBRyxLQUFLLEVBQUUsQ0FBQztZQUNyQyxJQUFJLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO2dCQUN0QyxNQUFNLEVBQUMsSUFBSTtnQkFDWCxTQUFTLEVBQUMsbUJBQW1CO2dCQUM3QixPQUFPLEVBQUM7b0JBQ047d0JBQ0UsSUFBSSxFQUFDLFFBQVE7d0JBQ2IsSUFBSSxFQUFDLElBQUk7cUJBQ1Y7b0JBQ0Q7d0JBQ0UsSUFBSSxFQUFDLGFBQWE7d0JBQ2xCLElBQUksRUFBQyxJQUFJO3dCQUNULE9BQU8sRUFBQyxHQUFFLEVBQUU7NEJBQ1YsdUJBQXVCOzRCQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO3dCQUMvQyxDQUFDO3FCQUNGO2lCQUNGO2FBQ0YsQ0FBQyxDQUFBO1lBQ0YsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFBO1lBQ2YsT0FBTyxLQUFLLENBQUE7UUFDZCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUE7SUFDYixDQUFDO0lBRUQsdUJBQXVCO0lBQ3ZCLEtBQUssQ0FBQyxZQUFZO1FBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDekMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBQzlDLElBQUksU0FBUyxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ25DLDBCQUEwQjtJQUM1QixDQUFDO0lBRUQsS0FBSyxDQUFDLGVBQWU7UUFDbkIsZ0JBQWdCO1FBQ2hCLElBQUksS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN6QyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDL0Msd0RBQXdEO1FBQ3hELEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDeEIsSUFBSSxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDaEMsc0JBQXNCO1FBRXRCLHFCQUFxQjtRQUNyQixJQUFHLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBQyxDQUFDO1lBQ2IsSUFBSSxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDMUMsS0FBSyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7WUFDakIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUU7Z0JBQ2hCLFFBQVEsRUFBRSxTQUFTO2dCQUNuQixXQUFXLEVBQUUsT0FBTztnQkFDcEIsVUFBVSxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRTthQUNyQyxDQUFDLENBQUE7WUFDRixLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRTtnQkFDbkIsUUFBUSxFQUFFLFNBQVM7Z0JBQ25CLFdBQVcsRUFBRSxhQUFhO2dCQUMxQixVQUFVLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTO2FBQ2pDLENBQUMsQ0FBQTtZQUNGLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFO2dCQUNoQixRQUFRLEVBQUUsU0FBUztnQkFDbkIsV0FBVyxFQUFFLFlBQVk7Z0JBQ3pCLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFO2FBQy9CLENBQUMsQ0FBQTtZQUNGLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFO2dCQUNuQixRQUFRLEVBQUUsU0FBUztnQkFDbkIsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLFVBQVUsRUFBRSxZQUFZO2FBQ3pCLENBQUMsQ0FBQTtZQUNGLEtBQUssQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUE7UUFDbEQsQ0FBQzthQUFNLENBQUM7WUFDTixpQ0FBaUM7WUFDakMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQTtRQUNsRCxDQUFDO1FBQ0QsTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRCx1QkFBdUI7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUtDLFNBQVM7UUFDUCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztJQUN0QixDQUFDO0lBRUQsYUFBYTtRQUNYLDBCQUEwQjtRQUMxQixxQ0FBcUM7UUFDckMsdUNBQXVDO1FBQ3ZDLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQztJQUVELGlCQUFpQjtRQUNmLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLENBQUM7K0dBak5VLGdCQUFnQjttR0FBaEIsZ0JBQWdCLHNMQUNoQiwwQkFBMEIsZ0RDbEN2Qyw4bFpBd05ZLDZ1RURoTVIsWUFBWSxnWkFBQyxXQUFXLDhWQUFDLG1CQUFtQiw4QkFDNUMsWUFBWSwrQkFDWixVQUFVLG1GQUFDLE9BQU8sME5BQUMsU0FBUyxvUEFBQyxPQUFPLHlGQUFDLFFBQVEsc0RBQ3BDLE9BQU8sMkpBQUMsV0FBVyxpYUFBQyxVQUFVLHdEQUFDLFVBQVUsdUtBQ2xELGFBQWE7Z0JBQ2IsR0FBRztnQkFDSCwwQkFBMEI7OzRGQUdqQixnQkFBZ0I7a0JBZjVCLFNBQVM7K0JBQ0UscUJBQXFCLGNBR3BCLElBQUksV0FDUDt3QkFDTixZQUFZLEVBQUMsV0FBVyxFQUFDLG1CQUFtQjt3QkFDNUMsWUFBWTt3QkFDWixVQUFVLEVBQUMsT0FBTyxFQUFDLFNBQVMsRUFBQyxPQUFPLEVBQUMsUUFBUTt3QkFDN0MsUUFBUSxFQUFDLE9BQU8sRUFBQyxXQUFXLEVBQUMsVUFBVSxFQUFDLFVBQVU7d0JBQ2xELGFBQWE7d0JBQ2IsR0FBRzt3QkFDSCwwQkFBMEI7cUJBQzNCO3NSQUdzQyxTQUFTO3NCQUEvQyxTQUFTO3VCQUFDLDBCQUEwQjtnQkFFNUIsSUFBSTtzQkFBWixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQsQWZ0ZXJWaWV3SW5pdCwgT3V0cHV0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLFJvdXRlciwgUm91dGVyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEFsZXJ0Q29udHJvbGxlciwgTmF2Q29udHJvbGxlciwgUGxhdGZvcm0sIFRvYXN0Q29udHJvbGxlciB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyJztcbmltcG9ydCB7IEZtb2RlQ2hhdCxGbW9kZUNoYXRNZXNzYWdlIH0gZnJvbSAnLi4vLi4vc2VydmljZS1mbWFpL3NlcnZpY2UtY2hhdCc7XG5pbXBvcnQgeyBDaGF0U2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2UtZm1haS9zZXJ2aWNlLWNoYXQnO1xuXG4vLyBpbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJ2Ztb2RlLW5nJztcbmltcG9ydCBQYXJzZSBmcm9tIFwicGFyc2VcIjtcbi8vIGltcG9ydCB7IEFjY291bnRTZXJ2aWNlIH0gZnJvbSAncHJvamVjdHMvbm92YS1haWdjL3NyYy9tb2R1bGVzL2FjY291bnQvYWNjb3VudC5zZXJ2aWNlJztcbmltcG9ydCB7IE56TWVzc2FnZVNlcnZpY2UgfSBmcm9tICduZy16b3Jyby1hbnRkL21lc3NhZ2UnO1xuaW1wb3J0IHsgSW1hZ2luZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlLWZtYWkvc2VydmljZS1pbWFnaW5lL2ltYWdpbmUuc2VydmljZSc7XG5pbXBvcnQgeyBJb25CdXR0b24sIElvbkNvbnRlbnQsIElvbkljb24sIElvbklucHV0LCBJb25JdGVtLCBJb25MaXN0LCBJb25Nb2RhbCwgSW9uUG9wb3ZlciwgSW9uVGV4dGFyZWEsIElvblRvb2xiYXIgfSBmcm9tICdAaW9uaWMvYW5ndWxhci9zdGFuZGFsb25lJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IE56TW9kYWxNb2R1bGUgfSBmcm9tICduZy16b3Jyby1hbnRkL21vZGFsJztcblxuaW1wb3J0IHsgTW9kYWxBdWRpb01lc3NhZ2VDb21wb25lbnQgfSBmcm9tIFwiLi9tb2RhbC1hdWRpby1tZXNzYWdlL21vZGFsLWF1ZGlvLW1lc3NhZ2UuY29tcG9uZW50XCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2ZtLWNoYXQtbW9kYWwtaW5wdXQnLFxuICB0ZW1wbGF0ZVVybDogJy4vbW9kYWwtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9tb2RhbC1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxuICBzdGFuZGFsb25lOnRydWUsXG4gIGltcG9ydHM6W1xuICAgIENvbW1vbk1vZHVsZSxGb3Jtc01vZHVsZSxSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFJvdXRlck1vZHVsZSxcbiAgICBJb25Ub29sYmFyLElvbkl0ZW0sSW9uQnV0dG9uLElvbkxpc3QsSW9uTW9kYWwsXG4gICAgSW9uSW5wdXQsSW9uSWNvbixJb25UZXh0YXJlYSxJb25Qb3BvdmVyLElvbkNvbnRlbnQsXG4gICAgTnpNb2RhbE1vZHVsZSxcbiAgICAvLyBcbiAgICBNb2RhbEF1ZGlvTWVzc2FnZUNvbXBvbmVudFxuICBdXG59KVxuZXhwb3J0IGNsYXNzIEZtQ2hhdE1vZGFsSW5wdXQgaW1wbGVtZW50cyBPbkluaXR7XG4gIEBWaWV3Q2hpbGQoTW9kYWxBdWRpb01lc3NhZ2VDb21wb25lbnQpIGF1ZGlvQ29tcDpNb2RhbEF1ZGlvTWVzc2FnZUNvbXBvbmVudFxuXG4gIEBJbnB1dCgpIGNoYXQ6Rm1vZGVDaGF0O1xuICBASW5wdXQoKSBtZXNzYWdlOkZtb2RlQ2hhdE1lc3NhZ2VcbiAgQElucHV0KCkgcm9sZTpQYXJzZS5PYmplY3RcbiAgdXNlcjpQYXJzZS5Vc2VyXG4gIGVycm9yVGV4dDpzdHJpbmcgPSBgYFxuXG4gIGlzQXVkaW9Nb2RhbDpib29sZWFuID0gZmFsc2U7XG4gIGNsb3NlQXVkaW8oKXtcbiAgICB0aGlzLmF1ZGlvQ29tcD8uY2FuY2VsKCk7XG4gICAgdGhpcy5pc0F1ZGlvTW9kYWw9ZmFsc2U7XG4gIH1cbiAgXG4gIGFjY291bnQ6YW55O1xuICBhdXRoU2Vydjphbnk7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdG9hc3RDdHJsOlRvYXN0Q29udHJvbGxlcixcbiAgICBwcml2YXRlIGFsZXJ0Q3RybDpBbGVydENvbnRyb2xsZXIsXG4gICAgcHJpdmF0ZSBuYXZDdHJsOk5hdkNvbnRyb2xsZXIsXG4gICAgcHJpdmF0ZSByb3V0ZXI6Um91dGVyLFxuICAgIHByaXZhdGUgaW1hZ2luZVNlcnY6SW1hZ2luZVNlcnZpY2UsXG4gICAgLy8gcHJpdmF0ZSBhdXRoU2VydjpBdXRoU2VydmljZSxcbiAgICBwdWJsaWMgY2hhdFNlcnY6Q2hhdFNlcnZpY2UsXG4gICAgLy8gcHJpdmF0ZSBhY2NvdW50OkFjY291bnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgcm91dGU6QWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBtZXNzYWdlczogTnpNZXNzYWdlU2VydmljZVxuICApe1xuICAgIC8vIHRoaXMuY2hhdFNlcnYuZ2V0Q2hhdFNlc3Npb24oKS50aGVuKCgpPT57XG4gICAgLy8gICBjb25zb2xlLmxvZyh0aGlzLmNoYXRTZXJ2LmNoYXRMaXN0KTtcbiAgICAvLyB9KVxuICAgIHRoaXMudXNlciA9IFBhcnNlLlVzZXIuY3VycmVudCgpO1xuXG4gIH1cbiAgbmdPbkluaXQoKXtcbiAgICB0aGlzLmxvYWRNb2RlbCgpO1xuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuY2hhdCk7XG4gIH1cblxuICAvLyBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gIC8vICAgY29uc29sZS5sb2codGhpcy5jaGF0KVxuICAvLyB9XG5cbiAgYXN5bmMgbG9hZE1vZGVsKCl7XG4gICAgbGV0IG1vZGVsID0gdGhpcy5jaGF0Py5yb2xlPy5nZXQoXCJtb2RlbFwiKVxuICAgIGF3YWl0IHRoaXMuY2hhdFNlcnYubG9hZE1vZGVsTGlzdChtb2RlbClcbiAgfVxuICBcbiAgYXN5bmMgc2V0TWVzc2FnZUltYWdlKCl7XG4gICAgLy8gbGV0IHVybCA9IGBodHRwczovL2ZpbGUtY2xvdWQuZm1vZGUuY24vU3ZlaGw2RmNlTC8yMDI0MDUxNS8wNjE1MDM2NzEuanBlZ2A7XG4gICAgbGV0IHVybCA9IGF3YWl0IHRoaXMuaW1hZ2luZVNlcnYuZ2V0aW1nKCk7XG4gICAgdGhpcy5jaGF0LnVzZXJJbWFnZSA9IHVybDtcbiAgICBjb25zb2xlLmxvZyh0aGlzLmNoYXQ/LnVzZXJJbWFnZSk7XG4gICAgLy8gY29udGVudOaYr+aVsOe7hO+8jOa3u+WKoFxuICAgIC8vIGNvbnRlbnTpnZ7mlbDnu4TvvIzph43nu4RcbiAgfVxuIFxuICBcbiAgb25LZXlEb3duKGV2ZW50OktleWJvYXJkRXZlbnQpe1xuICAgIC8vIOajgOafpeaYr+WQpuaMieS4i+S6hkN0cmzplK7lkoxFbnRlcumUrlxuICAgIGlmIChldmVudC5jdHJsS2V5ICYmIGV2ZW50LmtleSA9PT0gJ0VudGVyJykge1xuICAgICAgLy8g5omn6KGM55u45bqU55qE6YC76L6RXG4gICAgICBjb25zb2xlLmxvZygnQ3RybCtFbnRlciDooqvmjInkuIsnKTtcbiAgICAgIHRoaXMuc2VuZE1lc3NhZ2UoKTtcbiAgICB9XG4gIH1cbiAgYXN5bmMgc2VuZE1lc3NhZ2UoKXtcblxuICAgIC8vIOajgOa1i+eUqOaIt+eZu+W9leaDheWGtVxuICAgIC8vIGxldCBpc0xvZ2luTG9jayA9IGF3YWl0IHRoaXMuYXV0aFNlcnYuY2hlY2tMb2dpbkxvY2soKVxuICAgIC8vIGlmKCFpc0xvZ2luTG9jaykgcmV0dXJuIGZhbHNlXG5cbiAgICAvLyDmo4DmtYvkvZnpop3lj4rmqKHlnovku5jotLnpmZDliLZcbiAgICAvLyBsZXQgcGF5Q2hlY2sgPSBhd2FpdCB0aGlzLmNoZWNrQmFsYW5jZSgpXG4gICAgLy8gaWYoIXBheUNoZWNrKSByZXR1cm4gZmFsc2VcblxuICAgIC8vIOajgOa1i+eUqOaIt+i+k+WFpeWGheWuueepuuWAvFxuICAgIGlmKCF0aGlzLmNoYXQudXNlcklucHV0KXtcbiAgICAgIHRoaXMuZXJyb3JUZXh0ID0gYOWGheWuueS4jeiDveS4uuepumBcbiAgICAgIGxldCB0b2FzdCA9IGF3YWl0IHRoaXMudG9hc3RDdHJsLmNyZWF0ZSh7XG4gICAgICAgIG1lc3NhZ2U6dGhpcy5lcnJvclRleHQsXG4gICAgICAgIHBvc2l0aW9uOlwidG9wXCIsXG4gICAgICAgIGljb246J2FsZXJ0JyxcbiAgICAgICAgY29sb3I6XCJ3YXJuaW5nLWNpcmNsZVwiLFxuICAgICAgICBkdXJhdGlvbjoxMDAwXG4gICAgICB9KVxuICAgICAgdG9hc3QucHJlc2VudCgpO1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8g5q2j5bi45Y+R6YCB5raI5oGvXG4gICAgLy8gdGhpcy5jaGF0LmlzVGFsa01vZGU9dHJ1ZTsgLy8g5byA5ZCv6K+06K+d5qih5byPXG4gICAgdGhpcy5jaGF0Py5zZW5kTWVzc2FnZSh0aGlzLmNoYXQ/LnVzZXJJbnB1dCx0aGlzLmNoYXQ/LnVzZXJJbWFnZSwobXNnKT0+e30se1xuICAgICAgb25TU01MQ29tcGxldGU6KHZvaWNlOmFueSk9PntcbiAgICAgICAgY29uc29sZS5sb2codm9pY2UpXG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5jaGF0LnVzZXJJbnB1dCA9IGBgXG4gICAgdGhpcy5jaGF0LnVzZXJJbWFnZSA9IGBgXG4gIH1cbiAgYXN5bmMgY2hlY2tCYWxhbmNlKCl7XG4gICAgaWYoIXRoaXMuY2hhdFNlcnY/LmN1cnJlbnRNb2RlbD8uZ2V0KFwicGF5TGltaXRcIikpIHJldHVybiB0cnVlIC8vIOaooeWei+aYr+WQpuW8gOWQr+S7mOi0uemZkOWItlxuICAgIC8vIOagoemqjOi0puaIt+S9meminVxuICAgIGxldCBiaWxsaW5nID0gYXdhaXQgdGhpcy5hY2NvdW50LmdldEJpbGxpbmcoKTtcbiAgICAvLyBsZXQgcHJpY2UgPSBhd2FpdCB0aGlzLmNhbGNQcmljZSgpXG4gICAgbGV0IHByaWNlID0gMTA7XG4gICAgaWYgKGJpbGxpbmc/LmNyZWRpdD8uYmFsYW5jZSA8IHByaWNlKSB7XG4gICAgICBsZXQgYWxlcnQgPSBhd2FpdCB0aGlzLmFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgICBoZWFkZXI6XCLms6jmhI9cIixcbiAgICAgICAgc3ViSGVhZGVyOlwi5oKo55qE5L2Z6aKd5LiN6Laz77yM6K+35YWF5YC85ZCO6Kej6ZSB6auY57qn5qih5Z6LXCIsXG4gICAgICAgIGJ1dHRvbnM6W1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJvbGU6XCJjYW5jZWxcIixcbiAgICAgICAgICAgIHRleHQ6XCLlj5bmtohcIlxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgcm9sZTpcImRlc3RydWN0aXZlXCIsXG4gICAgICAgICAgICB0ZXh0Olwi5YWF5YC8XCIsXG4gICAgICAgICAgICBoYW5kbGVyOigpPT57XG4gICAgICAgICAgICAgIC8vIOW+heabtOaNouaIkOWOn+WcsOW8ueeql++8jOWOn+WcsOS7mOi0ue+8jOmBv+WFjemhtemdoui3s+i9rFxuICAgICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZUJ5VXJsKFwiL2FjY291bnQvYmlsbGluZ1wiKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgXVxuICAgICAgfSlcbiAgICAgIGFsZXJ0LnByZXNlbnQoKVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICAvL+afpeivoumXruetlOWGheWuueWIhuS6q+aVsOaNruihqO+8mkNoYXRTaGFyZVxuICBhc3luYyBnZXRDaGF0U2hhcmUoKXtcbiAgICB0aGlzLnVzZXIgPSBQYXJzZS5Vc2VyLmN1cnJlbnQoKTtcbiAgICBsZXQgcXVlcnkgPSBuZXcgUGFyc2UuUXVlcnkoJ0NoYXRTaGFyZScpO1xuICAgIHF1ZXJ5LmVxdWFsVG8oJ3VzZXInLCBQYXJzZS5Vc2VyLmN1cnJlbnQoKS5pZCk7XG4gICAgcXVlcnkuZXF1YWxUbygnc2Vzc2lvbicsIHRoaXMuY2hhdD8uc2Vzc2lvbklkKVxuICAgIGxldCBjaGF0U2hhcmUgPSBhd2FpdCBxdWVyeS5maXJzdCgpXG4gICAgLy8gY29uc29sZS5sb2coY2hhdFNoYXJlKTtcbiAgfVxuXG4gIGFzeW5jIHRvZ2dsZUNoYXRTaGFyZSgpIHtcbiAgICAvL+iOt+WPlkNoYXRTaGFyZeaVsOaNruihqFxuICAgIGxldCBxdWVyeSA9IG5ldyBQYXJzZS5RdWVyeSgnQ2hhdFNoYXJlJyk7XG4gICAgcXVlcnkuZXF1YWxUbygndXNlcicsIFBhcnNlLlVzZXIuY3VycmVudCgpLmlkKTtcbiAgICBxdWVyeS5lcXVhbFRvKCdyb2xlJywgdGhpcy5jaGF0Py5yb2xlLmlkKTtcbiAgICBxdWVyeS5lcXVhbFRvKCdzZXNzaW9uJywgdGhpcy5jaGF0Py5zZXNzaW9uSWQpO1xuICAgIC8vIHF1ZXJ5LmVxdWFsVG8oJ21lc3NhZ2VMaXN0JywgdGhpcy5jaGF0Py5tZXNzYWdlTGlzdCk7XG4gICAgcXVlcnkuc2VsZWN0KCdvYmplY3RJZCcpXG4gICAgbGV0IHNoYXJlID0gYXdhaXQgcXVlcnkuZmlyc3QoKTtcbiAgICAvLyBjb25zb2xlLmxvZyhzaGFyZSk7XG5cbiAgICAvL+WmguaenGlk5LiN5a2Y5Zyo77yM5Zyo5pWw5o2u6KGo5YaF5Yib5bu65paw55qE6K6w5b2VXG4gICAgaWYoIXNoYXJlPy5pZCl7XG4gICAgICBsZXQgb2JqID0gUGFyc2UuT2JqZWN0LmV4dGVuZCgnQ2hhdFNoYXJlJylcbiAgICAgIHNoYXJlID0gbmV3IG9iaigpXG4gICAgICBzaGFyZS5zZXQoJ3VzZXInLCB7XG4gICAgICAgIFwiX190eXBlXCI6IFwiUG9pbnRlclwiLFxuICAgICAgICBcImNsYXNzTmFtZVwiOiBcIl9Vc2VyXCIsXG4gICAgICAgIFwib2JqZWN0SWRcIjogUGFyc2UuVXNlci5jdXJyZW50KCk/LmlkXG4gICAgICB9KVxuICAgICAgc2hhcmUuc2V0KCdzZXNzaW9uJywge1xuICAgICAgICBcIl9fdHlwZVwiOiBcIlBvaW50ZXJcIixcbiAgICAgICAgXCJjbGFzc05hbWVcIjogXCJDaGF0U2Vzc2lvblwiLFxuICAgICAgICBcIm9iamVjdElkXCI6IHRoaXMuY2hhdD8uc2Vzc2lvbklkXG4gICAgICB9KVxuICAgICAgc2hhcmUuc2V0KCdyb2xlJywge1xuICAgICAgICBcIl9fdHlwZVwiOiBcIlBvaW50ZXJcIixcbiAgICAgICAgXCJjbGFzc05hbWVcIjogXCJBdmF0YXJSb2xlXCIsXG4gICAgICAgIFwib2JqZWN0SWRcIjogdGhpcy5jaGF0Py5yb2xlLmlkXG4gICAgICB9KVxuICAgICAgc2hhcmUuc2V0KCdjb21wYW55Jywge1xuICAgICAgICBcIl9fdHlwZVwiOiBcIlBvaW50ZXJcIixcbiAgICAgICAgXCJjbGFzc05hbWVcIjogXCJDb21wYW55XCIsXG4gICAgICAgIFwib2JqZWN0SWRcIjogXCJFNEtwR3ZURXRvXCJcbiAgICAgIH0pXG4gICAgICBzaGFyZS5zZXQoJ21lc3NhZ2VMaXN0JywgdGhpcy5jaGF0Py5tZXNzYWdlTGlzdClcbiAgICB9IGVsc2Uge1xuICAgICAgLy9pZOWtmOWcqO+8jOeCueWHu+WIhuS6q+aMiemSruaJp+ihjOabtOaWsG1lc3NhZ2VMaXN05pWw5o2u55qE5pON5L2cXG4gICAgICBzaGFyZS5zZXQoJ21lc3NhZ2VMaXN0JywgdGhpcy5jaGF0Py5tZXNzYWdlTGlzdClcbiAgICB9XG4gICAgYXdhaXQgc2hhcmUuc2F2ZSgpO1xuICAgIHRoaXMuZ2V0Q2hhdFNoYXJlKCk7XG59XG5cbmNoYXRTaGFyZVN1Y2Nlc3NNZXNzYWdlKCk6IHZvaWQge1xuICB0aGlzLm1lc3NhZ2VzLnN1Y2Nlc3MoJ+WIhuS6q+aIkOWKnycpO1xufVxuXG4gIC8v5YiG5Lqr5by55qGG57uE5Lu2XG4gIGlzU2hhcmUgPSBmYWxzZTtcblxuICBzaG93U2hhcmUoKTogdm9pZCB7XG4gICAgdGhpcy5pc1NoYXJlID0gdHJ1ZTtcbiAgfVxuXG4gIGhhbmRsZU9rU2hhcmUoKTogdm9pZCB7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5jaGF0KTtcbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLmNoYXQ/LnNlc3Npb25JZCk7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5jaGF0Py5tZXNzYWdlTGlzdCk7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5jaGF0Py5yb2xlLmlkKTtcbiAgICB0aGlzLnRvZ2dsZUNoYXRTaGFyZSgpO1xuICAgIHRoaXMuY2hhdFNoYXJlU3VjY2Vzc01lc3NhZ2UoKTtcbiAgICB0aGlzLmlzU2hhcmUgPSBmYWxzZTtcbiAgfVxuXG4gIGhhbmRsZUNhbmNlbFNoYXJlKCk6IHZvaWQge1xuICAgIHRoaXMuaXNTaGFyZSA9IGZhbHNlO1xuICB9XG59XG4iLCI8aW9uLXRvb2xiYXI+XG4gICAgPGlvbi1pdGVtIGNsYXNzPVwiYnV0dG9uLWl0ZW1cIiBsaW5lcz1cIm5vbmVcIj5cbiAgICAgICAgPCEtLSDorr7nva4gLS0+XG4gICAgICAgIDwhLS0gPGlvbi1idXR0b24gZmlsbD1cIm91dGxpbmVcIiBzbG90PVwic3RhcnRcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwic2V0dGluZ3Mtb3V0bGluZVwiPjwvaW9uLWljb24+IFxuICAgICAgICA8L2lvbi1idXR0b24+IC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBidXR0b24gb2YgY2hhdD8ubGVmdEJ1dHRvbnNcIj5cbiAgICAgICAgICA8aW9uLWJ1dHRvbiBzdHlsZT1cIi0tcGFkZGluZy1zdGFydDoxMHB4Oy0tcGFkZGluZy1lbmQ6MTBweDtcIlxuICAgICAgICAgICBzaGFwZT1cInJvdW5kXCIgKm5nSWY9XCJidXR0b24uc2hvdygpXCIgZmlsbD1cIm91dGxpbmVcIiBbdGl0bGVdPVwiYnV0dG9uPy50aXRsZVwiIHNsb3Q9XCJzdGFydFwiIChjbGljayk9XCJidXR0b24ub25DbGljaygpXCI+XG4gICAgICAgICAgICA8aW9uLWljb24gW25hbWVdPVwiYnV0dG9uPy5pY29uXCIgW3Nsb3RdPVwiYnV0dG9uPy5zaG93VGl0bGU/J3N0YXJ0JzonaWNvbi1vbmx5J1wiPjwvaW9uLWljb24+XG4gICAgICAgICAgICB7e2J1dHRvbj8uc2hvd1RpdGxlJiZidXR0b24/LnRpdGxlfX1cbiAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGJ1dHRvbiBvZiBjaGF0Py5yb2xlPy5nZXQoJ2J1dHRvbnMnKVwiPlxuICAgICAgICAgICAgPGlvbi1idXR0b24gc2hhcGU9XCJyb3VuZFwiIChjbGljayk9XCJjaGF0U2Vydi5kb0J1dHRvbkFjdGlvbihidXR0b24pXCIgZmlsbD1cIm91dGxpbmVcIiAgc2xvdD1cInN0YXJ0XCI+XG4gICAgICAgICAgICAgICAge3tidXR0b24/Lm5hbWV9fVxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0t5YiG5Lqr5oyJ6ZKuLS0+XG4gICAgICAgIDxpb24tYnV0dG9uIHNoYXBlPVwicm91bmRcIiAqbmdJZj1cImNoYXQ/Lm1lc3NhZ2VMaXN0Py5sZW5ndGg+MVwiIChjbGljayk9XCJzaG93U2hhcmUoKVwiIGZpbGw9XCJvdXRsaW5lXCIgdGl0bGU9XCLliIbkuqtcIiBzbG90PVwiZW5kXCI+XG4gICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cInNoYXJlLXNvY2lhbC1vdXRsaW5lXCI+PC9pb24taWNvbj5cbiAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICA8IS0tIDxidXR0b24gbnotYnV0dG9uICpuZ0lmPVwiY2hhdD8ubWVzc2FnZUxpc3Q/Lmxlbmd0aD4xXCJcbiAgICAgICAgIG56VHlwZT1cInByaW1hcnlcIiB0aXRsZT1cIuWIhuS6q1wiIChjbGljayk9XCJzaG93U2hhcmUoKVwiIHN0eWxlPVwid2lkdGg6IDMxLjE4OHB4O2hlaWdodDogMjJweDtib3gtc2hhZG93OiBub25lO2JhY2tncm91bmQ6ICNmZmY7Ym9yZGVyOiAxcHggc29saWQgIzQ1ODhmZjtib3JkZXItcmFkaXVzOiA1cHg7XCI+IDxzcGFuIGNsYXNzPVwiaWNvbmZvbnQgaWNvbi1mZW54aWFuZ1wiIHN0eWxlPVwiY29sb3I6ICM0NTg4ZmY7XCI+PC9zcGFuPjwvYnV0dG9uPlxuICAgICAgICAgIC0tPlxuICAgICAgICAgIDxpb24tbW9kYWwgW2lzT3Blbl09XCJpc1NoYXJlXCI+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgIDxpb24taGVhZGVyPlxuICAgICAgICAgICAgICAgIDxpb24tdG9vbGJhcj5cbiAgICAgICAgICAgICAgICAgIDxpb24tYnV0dG9ucyBzbG90PVwic3RhcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImhhbmRsZUNhbmNlbFNoYXJlKClcIj7lj5bmtog8L2lvbi1idXR0b24+XG4gICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b25zPlxuICAgICAgICAgICAgICAgICAgPGlvbi10aXRsZT7lr7nor53liIbkuqs8L2lvbi10aXRsZT5cbiAgICAgICAgICAgICAgICAgIDxpb24tYnV0dG9ucyBzbG90PVwiZW5kXCI+XG4gICAgICAgICAgICAgICAgICAgIDxpb24tYnV0dG9uIChjbGljayk9XCJoYW5kbGVPa1NoYXJlKClcIj7liIbkuqs8L2lvbi1idXR0b24+XG4gICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b25zPlxuICAgICAgICAgICAgICAgIDwvaW9uLXRvb2xiYXI+XG4gICAgICAgICAgICAgIDwvaW9uLWhlYWRlcj5cbiAgICAgICAgICAgICAgPGlvbi1jb250ZW50IGNsYXNzPVwiaW9uLXBhZGRpbmdcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicG9wdXAtY29udGVudFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgbWVzc2FnZSBvZiBjaGF0Py5tZXNzYWdlTGlzdFwiPlxuICAgICAgICAgICAgICAgICAgICA8IS0tIOWktOWDjyAtLT5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tcm93IHVzZXJcIiAqbmdJZj1cIm1lc3NhZ2U/LnJvbGUhPSdzeXN0ZW0nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuei1hdmF0YXIgKm5nSWY9XCJtZXNzYWdlPy5yb2xlIT0ndXNlcidcIiBbbnpTcmNdPVwiKGNoYXQ/LnJvbGU/LmdldCgnYXZhdGFyJykgfHwgY2hhdD8ucm9sZT8uZ2V0KCd0aHVtYicpIHx8ICdodHRwczovL2ZpbGUtY2xvdWQuZm1vZGUuY24vRTRLcEd2VEV0by8yMDIzMDkzMC9sNDEzZTYwOTA3MzE4NTQucG5nJykrJz8nKyd4LWltYWdlLXByb2Nlc3M9aW1hZ2UvcmVzaXplLG1fZml4ZWQsd18xMDAnKycmaW1hZ2VWaWV3Mi8xL3cvMzIvaC8zMidcIj48L256LWF2YXRhcj5cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidXNlci1xdWVzdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGFwcC1jb21wLXVzZXItYXZhdGFyIFt1c2VyXT1cInVzZXJcIiAqbmdJZj1cIm1lc3NhZ2U/LnJvbGU9PSd1c2VyJ1wiPjwvYXBwLWNvbXAtdXNlci1hdmF0YXI+XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8IS0tIOWGheWuuSAtLT5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lc3NhZ2Utd3JhcHBlclwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZXNzYWdlLWNvbnRlbnQtdXNlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInVzZXItbWVzc2FnZVwiICpuZ0lmPVwibWVzc2FnZT8ucm9sZSA9PT0gJ3VzZXInXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwiIW1lc3NhZ2U/LmNvbXBsZXRlXCIgY2xhc3M9XCJjb250ZW50LXN0eWxlXCIgW2NvbnRlbnRdPVwibWVzc2FnZT8uY29udGVudFwiIFtyZW5kZXJdPVwiZmFsc2VcIj48L2ZtLW1hcmtkb3duLXByZXZpZXc+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwibWVzc2FnZT8uY29tcGxldGVcIiBjbGFzcz1cImNvbnRlbnQtc3R5bGVcIiBbY29udGVudF09XCJtZXNzYWdlPy5jb250ZW50XCI+PC9mbS1tYXJrZG93bi1wcmV2aWV3PlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZXNzYWdlLWNvbnRlbnQtcm9sZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvbGUtbWVzc2FnZVwiICpuZ0lmPVwibWVzc2FnZT8ucm9sZSAhPT0gJ3VzZXInICYmIG1lc3NhZ2U/LnJvbGUgIT09ICdzeXN0ZW0nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwiIW1lc3NhZ2U/LmNvbXBsZXRlXCIgY2xhc3M9XCJjb250ZW50LXN0eWxlXCIgW2NvbnRlbnRdPVwibWVzc2FnZT8uY29udGVudFwiIFtyZW5kZXJdPVwiZmFsc2VcIj48L2ZtLW1hcmtkb3duLXByZXZpZXc+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwibWVzc2FnZT8uY29tcGxldGVcIiBjbGFzcz1cImNvbnRlbnQtc3R5bGVcIiBbY29udGVudF09XCJtZXNzYWdlPy5jb250ZW50XCI+PC9mbS1tYXJrZG93bi1wcmV2aWV3PlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZXNzYWdlLWNvbnRlbnQtc3lzdGVtXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3lzdGVtLW1lc3NhZ2VcIiAqbmdJZj1cIm1lc3NhZ2U/LnJvbGUgPT09ICdzeXN0ZW0nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwiIW1lc3NhZ2U/LmNvbXBsZXRlXCIgY2xhc3M9XCJjb250ZW50LXN0eWxlXCIgW2NvbnRlbnRdPVwibWVzc2FnZT8uY29udGVudFwiIFtyZW5kZXJdPVwiZmFsc2VcIj48L2ZtLW1hcmtkb3duLXByZXZpZXc+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwibWVzc2FnZT8uY29tcGxldGVcIiBjbGFzcz1cImNvbnRlbnQtc3R5bGVcIiBbY29udGVudF09XCJtZXNzYWdlPy5jb250ZW50XCI+PC9mbS1tYXJrZG93bi1wcmV2aWV3PlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNoYXQtdGltZVwiICpuZ0lmPVwibWVzc2FnZT8uY3JlYXRlZEF0XCIgW25nQ2xhc3NdPVwieydyb2xlLXRpbWUnOiBtZXNzYWdlPy5yb2xlICE9PSAndXNlcid9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3ttZXNzYWdlPy5jcmVhdGVkQXQgfCBkYXRlOlwiZGQvTU0veXl5eSwgSEgvbW0vc3MgYVwifX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+ICAgXG4gICAgICAgICAgICAgIDwvaW9uLWNvbnRlbnQ+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvaW9uLW1vZGFsPlxuXG4gICAgICAgIDxuei1tb2RhbCAqbmdJZj1cImZhbHNlXCJcbiAgICAgICAgICBbKG56VmlzaWJsZSldPVwiaXNTaGFyZVwiXG4gICAgICAgICAgbnpUaXRsZT1cIumXruetlOWIhuS6q1wiXG4gICAgICAgICAgbnpDZW50ZXJlZFxuICAgICAgICAgIG56T2tUZXh0PVwi5YiG5LqrXCJcbiAgICAgICAgICBuekNhbmNlbFRleHQ9XCLlj5bmtohcIlxuICAgICAgICAgIChuek9uQ2FuY2VsKT1cImhhbmRsZUNhbmNlbFNoYXJlKClcIlxuICAgICAgICAgIChuek9uT2spPVwiaGFuZGxlT2tTaGFyZSgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm56TW9kYWxDb250ZW50PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBvcHVwLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBtZXNzYWdlIG9mIGNoYXQ/Lm1lc3NhZ2VMaXN0XCI+XG4gICAgICAgICAgICAgICAgICA8IS0tIOWktOWDjyAtLT5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLXJvdyB1c2VyXCIgKm5nSWY9XCJtZXNzYWdlPy5yb2xlIT0nc3lzdGVtJ1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDxuei1hdmF0YXIgKm5nSWY9XCJtZXNzYWdlPy5yb2xlIT0ndXNlcidcIiBbbnpTcmNdPVwiKGNoYXQ/LnJvbGU/LmdldCgndGh1bWInKSB8fCAnaHR0cHM6Ly9maWxlLWNsb3VkLmZtb2RlLmNuL0U0S3BHdlRFdG8vMjAyMzA5MzAvbDQxM2U2MDkwNzMxODU0LnBuZycpKyc/JysneC1pbWFnZS1wcm9jZXNzPWltYWdlL3Jlc2l6ZSxtX2ZpeGVkLHdfMTAwJysnJmltYWdlVmlldzIvMS93LzMyL2gvMzInXCI+PC9uei1hdmF0YXI+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidXNlci1xdWVzdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxhcHAtY29tcC11c2VyLWF2YXRhciBbdXNlcl09XCJ1c2VyXCIgKm5nSWY9XCJtZXNzYWdlPy5yb2xlPT0ndXNlcidcIj48L2FwcC1jb21wLXVzZXItYXZhdGFyPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgPCEtLSDlhoXlrrkgLS0+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWVzc2FnZS13cmFwcGVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtZXNzYWdlLWNvbnRlbnQtdXNlclwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ1c2VyLW1lc3NhZ2VcIiAqbmdJZj1cIm1lc3NhZ2U/LnJvbGUgPT09ICd1c2VyJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIml0ZW0tY29udGVudFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwiIW1lc3NhZ2U/LmNvbXBsZXRlXCIgY2xhc3M9XCJjb250ZW50LXN0eWxlXCIgW2NvbnRlbnRdPVwibWVzc2FnZT8uY29udGVudFwiIFtyZW5kZXJdPVwiZmFsc2VcIj48L2ZtLW1hcmtkb3duLXByZXZpZXc+IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8Zm0tbWFya2Rvd24tcHJldmlldyAqbmdJZj1cIm1lc3NhZ2U/LmNvbXBsZXRlXCIgY2xhc3M9XCJjb250ZW50LXN0eWxlXCIgW2NvbnRlbnRdPVwibWVzc2FnZT8uY29udGVudFwiPjwvZm0tbWFya2Rvd24tcHJldmlldz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1lc3NhZ2UtY29udGVudC1yb2xlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvbGUtbWVzc2FnZVwiICpuZ0lmPVwibWVzc2FnZT8ucm9sZSAhPT0gJ3VzZXInICYmIG1lc3NhZ2U/LnJvbGUgIT09ICdzeXN0ZW0nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbS1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gPGZtLW1hcmtkb3duLXByZXZpZXcgKm5nSWY9XCIhbWVzc2FnZT8uY29tcGxldGVcIiBjbGFzcz1cImNvbnRlbnQtc3R5bGVcIiBbY29udGVudF09XCJtZXNzYWdlPy5jb250ZW50XCIgW3JlbmRlcl09XCJmYWxzZVwiPjwvZm0tbWFya2Rvd24tcHJldmlldz4gLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxmbS1tYXJrZG93bi1wcmV2aWV3ICpuZ0lmPVwibWVzc2FnZT8uY29tcGxldGVcIiBjbGFzcz1cImNvbnRlbnQtc3R5bGVcIiBbY29udGVudF09XCJtZXNzYWdlPy5jb250ZW50XCI+PC9mbS1tYXJrZG93bi1wcmV2aWV3PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWVzc2FnZS1jb250ZW50LXN5c3RlbVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzeXN0ZW0tbWVzc2FnZVwiICpuZ0lmPVwibWVzc2FnZT8ucm9sZSA9PT0gJ3N5c3RlbSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpdGVtLWNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSA8Zm0tbWFya2Rvd24tcHJldmlldyAqbmdJZj1cIiFtZXNzYWdlPy5jb21wbGV0ZVwiIGNsYXNzPVwiY29udGVudC1zdHlsZVwiIFtjb250ZW50XT1cIm1lc3NhZ2U/LmNvbnRlbnRcIiBbcmVuZGVyXT1cImZhbHNlXCI+PC9mbS1tYXJrZG93bi1wcmV2aWV3PiAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGZtLW1hcmtkb3duLXByZXZpZXcgKm5nSWY9XCJtZXNzYWdlPy5jb21wbGV0ZVwiIGNsYXNzPVwiY29udGVudC1zdHlsZVwiIFtjb250ZW50XT1cIm1lc3NhZ2U/LmNvbnRlbnRcIj48L2ZtLW1hcmtkb3duLXByZXZpZXc+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjaGF0LXRpbWVcIiAqbmdJZj1cIm1lc3NhZ2U/LmNyZWF0ZWRBdFwiIFtuZ0NsYXNzXT1cInsncm9sZS10aW1lJzogbWVzc2FnZT8ucm9sZSAhPT0gJ3VzZXInfVwiPlxuICAgICAgICAgICAgICAgICAgICA8c3Bhbj57e21lc3NhZ2U/LmNyZWF0ZWRBdCB8IGRhdGU6XCJkZC9NTS95eXl5LCBISC9tbS9zcyBhXCJ9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgXG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvbnotbW9kYWw+XG5cbiAgICAgICAgPCEtLSDlm77niYcgLS0+XG4gICAgICAgIDxpb24tYnV0dG9uIHNoYXBlPVwicm91bmRcIiAqbmdJZj1cImNoYXRTZXJ2Py5jdXJyZW50TW9kZWw/LmdldCgnY29uZmlnJyk/LmltYWdlRW5hYmxlZFwiIGZpbGw9XCJvdXRsaW5lXCIgIHNsb3Q9XCJlbmRcIiAoY2xpY2spPVwic2V0TWVzc2FnZUltYWdlKClcIj5cbiAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImltYWdlLW91dGxpbmVcIj48L2lvbi1pY29uPlxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDwhLS0g5qih5Z6LIC0tPlxuICAgICAgICAgPGlvbi1idXR0b24gc2hhcGU9XCJyb3VuZFwiIGZpbGw9XCJvdXRsaW5lXCIgc2xvdD1cImVuZFwiICBpZD1cIm1vZGVsLWJ1dHRvblwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJjaGV2cm9uLWRvd24tb3V0bGluZVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICB7e2NoYXRTZXJ2Py5jdXJyZW50TW9kZWw/LmdldCYmY2hhdFNlcnY/LmN1cnJlbnRNb2RlbD8uZ2V0KFwibmFtZVwiKXx8XCLpo57noIE0LjBcIn19XG4gICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgPGlvbi1wb3BvdmVyIHRyaWdnZXI9XCJtb2RlbC1idXR0b25cIiBbZGlzbWlzc09uU2VsZWN0XT1cInRydWVcIj5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgPGlvbi1jb250ZW50PlxuICAgICAgICAgICAgICAgIDxpb24tbGlzdD5cbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgbW9kZWwgb2YgY2hhdFNlcnYubW9kZWxMaXN0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gKGNsaWNrKT1cImNoYXRTZXJ2LmN1cnJlbnRNb2RlbCA9IG1vZGVsXCIgW2J1dHRvbl09XCJ0cnVlXCIgW2RldGFpbF09XCJmYWxzZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB7e21vZGVsPy5nZXQoXCJuYW1lXCIpfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1ub3RlIHNsb3Q9XCJlbmRcIj57e21vZGVsPy5nZXQoXCJjcmVkaXRcIil9fS9rPC9pb24tbm90ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgIDwvaW9uLWxpc3Q+XG4gICAgICAgICAgICAgIDwvaW9uLWNvbnRlbnQ+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvaW9uLXBvcG92ZXI+XG5cbiAgICA8L2lvbi1pdGVtPlxuXG4gICAgPGlvbi1pdGVtIGNsYXNzPVwiaW5wdXQtaXRlbVwiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICA8IS0tIOivremfs+a2iOaBr+i+k+WFpSAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNoYXQ/LmlzVm9pY2VJbnB1dE1vZGVcIj5cbiAgICAgICAgICA8IS0tIOWIh+aNouaWh+acrOi+k+WFpSAtLT5cbiAgICAgICAgICA8aW9uLWJ1dHRvbiBjbGFzcz1cImJ0bi1pbnB1dC1jaGFuZ2VcIiBjb2xvcj1cInByaW1hcnlcIiAoY2xpY2spPVwiY2hhdC5pc1ZvaWNlSW5wdXRNb2RlPWZhbHNlXCIgc2hhcGU9XCJyb3VuZFwiIHNpemU9XCJsYXJnZVwiPlxuICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJjaGF0Ym94LWVsbGlwc2VzLW91dGxpbmVcIiBzbG90PVwiaWNvbi1vbmx5XCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgICAgXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi12b2ljZS1zdGFydFwiIChjbGljayk9XCJpc0F1ZGlvTW9kYWw9dHJ1ZVwiPlxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgIOeCueWHu+iusuivnVxuICAgICAgICAgICAgPC9zcGFuPiBcbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSDmlofmnKzmtojmga/ovpPlhaUgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhY2hhdD8uaXNWb2ljZUlucHV0TW9kZVwiPlxuICAgICAgICAgIDwhLS0g5YiH5o2i6K+t6Z+z6L6T5YWlIC0tPlxuICAgICAgICAgIDxpb24tYnV0dG9uIFtzdHlsZS5kaXNwbGF5XT1cImNoYXQuaXNUZXh0aW5nPydub25lJzonZmxleCdcIiBjbGFzcz1cImJ0bi1pbnB1dC1jaGFuZ2VcIiBjb2xvcj1cInByaW1hcnlcIiAqbmdJZj1cImNoYXQ/LnJvbGU/LmdldCgndm9pY2VDb25maWcnKVwiIChjbGljayk9XCJjaGF0LmlzVm9pY2VJbnB1dE1vZGU9dHJ1ZVwiIHNoYXBlPVwicm91bmRcIiBzaXplPVwibGFyZ2VcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwibWljLW91dGxpbmVcIiBzbG90PVwiaWNvbi1vbmx5XCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L2lvbi1idXR0b24+XG5cbiAgICAgICAgICA8IS0tIOaWh+acrOi+k+WFpeWMuuWfnyAtLT5cbiAgICAgICAgICA8aW9uLXRleHRhcmVhICpuZ0lmPVwiY2hhdFwiIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQpXCJcbiAgICAgICAgICBbZXJyb3JUZXh0XT1cImVycm9yVGV4dFwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJjaGF0LnVzZXJJbnB1dFwiXG4gICAgICAgICAgKGlvbkZvY3VzKT1cImNoYXQuaXNUZXh0aW5nPXRydWVcIlxuICAgICAgICAgIChpb25CbHVyKT1cImNoYXQuaXNUZXh0aW5nPWZhbHNlXCJcbiAgICAgICAgICBbYXV0b0dyb3ddPVwidHJ1ZVwiIHNoYXBlPVwicm91bmRcIiBmaWxsPVwib3V0bGluZVwiXG4gICAgICAgICAgbGFiZWw9XCJDdHJsICsgRW50ZXIg5Y+R6YCB5raI5oGvXCIgcGxhY2Vob2xkZXI9XCLor7fovpPlhaXmgqjnmoTmj5DnpLror41cIlxuICAgICAgICAgIGxhYmVsUGxhY2VtZW50PVwiZmxvYXRpbmdcIj48L2lvbi10ZXh0YXJlYT5cbiAgICAgICAgICBcbiAgICAgICAgICA8IS0tIOaWh+acrOWPkemAgeaMiemSriAtLT5cbiAgICAgICAgICA8aW9uLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiBzaGFwZT1cInJvdW5kXCIgc2l6ZT1cImxhcmdlXCIgKGNsaWNrKT1cInNlbmRNZXNzYWdlKClcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwicGFwZXItcGxhbmUtb3V0bGluZVwiIHNsb3Q9XCJpY29uLW9ubHlcIj48L2lvbi1pY29uPlxuICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9pb24taXRlbT5cbjwvaW9uLXRvb2xiYXI+XG5cblxuPCEtLSDor63pn7Pmtojmga/ovpPlhaXvvJrlvLnlh7rljLrln58gLS0+XG48aW9uLW1vZGFsICNhdWRpb01vZGFsIFtpc09wZW5dPVwiaXNBdWRpb01vZGFsXCIgKHdpbGxEaXNtaXNzKT1cImNsb3NlQXVkaW8oKVwiIFtpbml0aWFsQnJlYWtwb2ludF09XCIwLjM1XCIgW2JyZWFrcG9pbnRzXT1cIlswLCAwLjM1LCAwLjVdXCI+XG4gIDxuZy10ZW1wbGF0ZT5cbiAgICA8Zm0tbW9kYWwtYXVkaW8tbWVzc2FnZSAjYXVkaW9Db21wICpuZ0lmPVwiaXNBdWRpb01vZGFsXCIgW2NoYXRdPVwiY2hhdFwiIFttb2RhbF09XCJhdWRpb01vZGFsXCI+PC9mbS1tb2RhbC1hdWRpby1tZXNzYWdlPlxuICA8L25nLXRlbXBsYXRlPlxuPC9pb24tbW9kYWw+Il19
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @copyright © 未来飞马 © 未来全栈 www.fmode.cn
|
|
4
|
+
* 版权所有 © 未来飞马 © 江西脑控科技有限公司 Copyright © Fmode Technology Co., Ltd.
|
|
5
|
+
* 保留所有权利 All Rights Reserved.
|
|
6
|
+
* /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs
|
|
7
|
+
*/
|
|
8
|
+
import{Component,Input,ViewChild}from"@angular/core";import{ActivatedRoute,Router,RouterModule}from"@angular/router";import{AlertController,NavController,ToastController}from"@ionic/angular";import{FmodeChat}from"../../service-fmai/service-chat";import{ChatService}from"../../service-fmai/service-chat";import Parse from"parse";import{NzMessageService}from"ng-zorro-antd/message";import{ImagineService}from"../../service-fmai/service-imagine/imagine.service";import{IonButton,IonContent,IonIcon,IonInput,IonItem,IonList,IonModal,IonPopover,IonTextarea,IonToolbar}from"@ionic/angular/standalone";import{CommonModule}from"@angular/common";import{FormsModule,ReactiveFormsModule}from"@angular/forms";import{NzModalModule}from"ng-zorro-antd/modal";import{ModalAudioMessageComponent}from"./modal-audio-message/modal-audio-message.component";import*as i0 from"@angular/core";import*as i1 from"@ionic/angular";import*as i2 from"@angular/router";import*as i3 from"../../service-fmai/service-imagine/imagine.service";import*as i4 from"../../service-fmai/service-chat";import*as i5 from"ng-zorro-antd/message";import*as i6 from"@angular/common";import*as i7 from"@angular/forms";import*as i8 from"ng-zorro-antd/modal";export class FmChatModalInput{closeAudio(){this.audioComp?.cancel(),this.isAudioModal=!1}constructor(e,n,t,o,a,s,i,r){this.toastCtrl=e,this.alertCtrl=n,this.navCtrl=t,this.router=o,this.imagineServ=a,this.chatServ=s,this.route=i,this.messages=r,this.errorText="",this.isAudioModal=!1,this.isShare=!1,this.user=Parse.User.current()}ngOnInit(){this.loadModel()}async loadModel(){let e=this.chat?.role?.get("model");await this.chatServ.loadModelList(e)}async setMessageImage(){let e=await this.imagineServ.getimg();this.chat.userImage=e,console.log(this.chat?.userImage)}onKeyDown(e){e.ctrlKey&&"Enter"===e.key&&(console.log("Ctrl+Enter 被按下"),this.sendMessage())}async sendMessage(){if(!this.chat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.chat?.sendMessage(this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}}),this.chat.userInput="",this.chat.userImage=""}async checkBalance(){if(!this.chatServ?.currentModel?.get("payLimit"))return!0;let e=await this.account.getBilling();if(e?.credit?.balance<10){return(await this.alertCtrl.create({header:"注意",subHeader:"您的余额不足,请充值后解锁高级模型",buttons:[{role:"cancel",text:"取消"},{role:"destructive",text:"充值",handler:()=>{this.router.navigateByUrl("/account/billing")}}]})).present(),!1}return!0}async getChatShare(){this.user=Parse.User.current();let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse.Query("ChatShare");e.equalTo("user",Parse.User.current().id),e.equalTo("role",this.chat?.role.id),e.equalTo("session",this.chat?.sessionId),e.select("objectId");let n=await e.first();if(n?.id)n.set("messageList",this.chat?.messageList);else{n=new(Parse.Object.extend("ChatShare")),n.set("user",{__type:"Pointer",className:"_User",objectId:Parse.User.current()?.id}),n.set("session",{__type:"Pointer",className:"ChatSession",objectId:this.chat?.sessionId}),n.set("role",{__type:"Pointer",className:"AvatarRole",objectId:this.chat?.role.id}),n.set("company",{__type:"Pointer",className:"Company",objectId:"E4KpGvTEto"}),n.set("messageList",this.chat?.messageList)}await n.save(),this.getChatShare()}chatShareSuccessMessage(){this.messages.success("分享成功")}showShare(){this.isShare=!0}handleOkShare(){this.toggleChatShare(),this.chatShareSuccessMessage(),this.isShare=!1}handleCancelShare(){this.isShare=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,deps:[{token:i1.ToastController},{token:i1.AlertController},{token:i1.NavController},{token:i2.Router},{token:i3.ImagineService},{token:i4.ChatService},{token:i2.ActivatedRoute},{token:i5.NzMessageService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmChatModalInput,isStandalone:!0,selector:"fm-chat-modal-input",inputs:{chat:"chat",message:"message",role:"role"},viewQueries:[{propertyName:"audioComp",first:!0,predicate:ModalAudioMessageComponent,descendants:!0}],ngImport:i0,template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <div class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar>\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n <nz-modal *ngIf="false"\n [(nzVisible)]="isShare"\n nzTitle="问答分享"\n nzCentered\n nzOkText="分享"\n nzCancelText="取消"\n (nzOnCancel)="handleCancelShare()"\n (nzOnOk)="handleOkShare()"\n >\n <ng-container *nzModalContent>\n <div class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar>\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ng-container>\n </nz-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chatServ?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chatServ?.currentModel?.get&&chatServ?.currentModel?.get("name")||"飞码4.0"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chatServ.modelList">\n <ion-item (click)="chatServ.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="isAudioModal=true">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="chat.isTexting=true"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n<ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="0.35" [breakpoints]="[0, 0.35, 0.5]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal>',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i6.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i6.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i6.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i6.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i7.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i7.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:RouterModule},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonTextarea,selector:"ion-textarea",inputs:["autoGrow","autocapitalize","autofocus","clearOnEdit","color","cols","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","maxlength","minlength","mode","name","placeholder","readonly","required","rows","shape","spellcheck","value","wrap"]},{kind:"component",type:IonPopover,selector:"ion-popover"},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"ngmodule",type:NzModalModule},{kind:"component",type:i8.NzModalComponent,selector:"nz-modal",inputs:["nzMask","nzMaskClosable","nzCloseOnNavigation","nzVisible","nzClosable","nzOkLoading","nzOkDisabled","nzCancelDisabled","nzCancelLoading","nzKeyboard","nzNoAnimation","nzCentered","nzDraggable","nzContent","nzFooter","nzZIndex","nzWidth","nzWrapClassName","nzClassName","nzStyle","nzTitle","nzCloseIcon","nzMaskStyle","nzBodyStyle","nzOkText","nzCancelText","nzOkType","nzOkDanger","nzIconType","nzModalType","nzAutofocus","nzOnOk","nzOnCancel"],outputs:["nzOnOk","nzOnCancel","nzAfterOpen","nzAfterClose","nzVisibleChange"],exportAs:["nzModal"]},{kind:"directive",type:i8.NzModalContentDirective,selector:"[nzModalContent]",exportAs:["nzModalContent"]},{kind:"component",type:ModalAudioMessageComponent,selector:"fm-modal-audio-message",inputs:["chat","modal"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatModalInput,decorators:[{type:Component,args:[{selector:"fm-chat-modal-input",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,RouterModule,IonToolbar,IonItem,IonButton,IonList,IonModal,IonInput,IonIcon,IonTextarea,IonPopover,IonContent,NzModalModule,ModalAudioMessageComponent],template:'<ion-toolbar>\n <ion-item class="button-item" lines="none">\n \x3c!-- 设置 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="settings-outline"></ion-icon> \n </ion-button> --\x3e\n <ng-container *ngFor="let button of chat?.leftButtons">\n <ion-button style="--padding-start:10px;--padding-end:10px;"\n shape="round" *ngIf="button.show()" fill="outline" [title]="button?.title" slot="start" (click)="button.onClick()">\n <ion-icon [name]="button?.icon" [slot]="button?.showTitle?\'start\':\'icon-only\'"></ion-icon>\n {{button?.showTitle&&button?.title}}\n </ion-button>\n </ng-container>\n\n <ng-container *ngFor="let button of chat?.role?.get(\'buttons\')">\n <ion-button shape="round" (click)="chatServ.doButtonAction(button)" fill="outline" slot="start">\n {{button?.name}}\n </ion-button>\n </ng-container>\n\n \x3c!--分享按钮--\x3e\n <ion-button shape="round" *ngIf="chat?.messageList?.length>1" (click)="showShare()" fill="outline" title="分享" slot="end">\n <ion-icon name="share-social-outline"></ion-icon>\n </ion-button>\n \x3c!-- <button nz-button *ngIf="chat?.messageList?.length>1"\n nzType="primary" title="分享" (click)="showShare()" style="width: 31.188px;height: 22px;box-shadow: none;background: #fff;border: 1px solid #4588ff;border-radius: 5px;"> <span class="iconfont icon-fenxiang" style="color: #4588ff;"></span></button>\n --\x3e\n <ion-modal [isOpen]="isShare">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="handleCancelShare()">取消</ion-button>\n </ion-buttons>\n <ion-title>对话分享</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="handleOkShare()">分享</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n <div class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'avatar\') || chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar>\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ion-content>\n </ng-template>\n </ion-modal>\n\n <nz-modal *ngIf="false"\n [(nzVisible)]="isShare"\n nzTitle="问答分享"\n nzCentered\n nzOkText="分享"\n nzCancelText="取消"\n (nzOnCancel)="handleCancelShare()"\n (nzOnOk)="handleOkShare()"\n >\n <ng-container *nzModalContent>\n <div class="popup-content">\n <div *ngFor="let message of chat?.messageList">\n \x3c!-- 头像 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'">\n <div>\n <nz-avatar *ngIf="message?.role!=\'user\'" [nzSrc]="(chat?.role?.get(\'thumb\') || \'https://file-cloud.fmode.cn/E4KpGvTEto/20230930/l413e6090731854.png\')+\'?\'+\'x-image-process=image/resize,m_fixed,w_100\'+\'&imageView2/1/w/32/h/32\'"></nz-avatar>\n </div>\n <div class="user-question">\n <app-comp-user-avatar [user]="user" *ngIf="message?.role==\'user\'"></app-comp-user-avatar>\n </div>\n </div>\n \x3c!-- 内容 --\x3e\n <div class="message-wrapper">\n <div class="message-content-user">\n <div class="user-message" *ngIf="message?.role === \'user\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-role">\n <div class="role-message" *ngIf="message?.role !== \'user\' && message?.role !== \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n <div class="message-content-system">\n <div class="system-message" *ngIf="message?.role === \'system\'">\n <div class="item-content">\n \x3c!-- <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content" [render]="false"></fm-markdown-preview> --\x3e\n <fm-markdown-preview *ngIf="message?.complete" class="content-style" [content]="message?.content"></fm-markdown-preview>\n </div>\n </div>\n </div>\n </div>\n <div class="chat-time" *ngIf="message?.createdAt" [ngClass]="{\'role-time\': message?.role !== \'user\'}">\n <span>{{message?.createdAt | date:"dd/MM/yyyy, HH/mm/ss a"}}</span>\n </div>\n </div>\n </div> \n </ng-container>\n </nz-modal>\n\n \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chatServ?.currentModel?.get(\'config\')?.imageEnabled" fill="outline" slot="end" (click)="setMessageImage()">\n <ion-icon name="image-outline"></ion-icon>\n </ion-button>\n \x3c!-- 模型 --\x3e\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chatServ?.currentModel?.get&&chatServ?.currentModel?.get("name")||"飞码4.0"}}\n </ion-button>\n <ion-popover trigger="model-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ng-container *ngFor="let model of chatServ.modelList">\n <ion-item (click)="chatServ.currentModel = model" [button]="true" [detail]="false">\n {{model?.get("name")}}\n <ion-note slot="end">{{model?.get("credit")}}/k</ion-note>\n </ion-item>\n </ng-container>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n\n </ion-item>\n\n <ion-item class="input-item" lines="none">\n \x3c!-- 语音消息输入 --\x3e\n <ng-container *ngIf="chat?.isVoiceInputMode">\n \x3c!-- 切换文本输入 --\x3e\n <ion-button class="btn-input-change" color="primary" (click)="chat.isVoiceInputMode=false" shape="round" size="large">\n <ion-icon name="chatbox-ellipses-outline" slot="icon-only"></ion-icon>\n </ion-button>\n \n <div class="btn-voice-start" (click)="isAudioModal=true">\n <span>\n 点击讲话\n </span> \n </div>\n </ng-container>\n\n \x3c!-- 文本消息输入 --\x3e\n <ng-container *ngIf="!chat?.isVoiceInputMode">\n \x3c!-- 切换语音输入 --\x3e\n <ion-button [style.display]="chat.isTexting?\'none\':\'flex\'" class="btn-input-change" color="primary" *ngIf="chat?.role?.get(\'voiceConfig\')" (click)="chat.isVoiceInputMode=true" shape="round" size="large">\n <ion-icon name="mic-outline" slot="icon-only"></ion-icon>\n </ion-button>\n\n \x3c!-- 文本输入区域 --\x3e\n <ion-textarea *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="chat.isTexting=true"\n (ionBlur)="chat.isTexting=false"\n [autoGrow]="true" shape="round" fill="outline"\n label="Ctrl + Enter 发送消息" placeholder="请输入您的提示词"\n labelPlacement="floating"></ion-textarea>\n \n \x3c!-- 文本发送按钮 --\x3e\n <ion-button color="primary" shape="round" size="large" (click)="sendMessage()">\n <ion-icon name="paper-plane-outline" slot="icon-only"></ion-icon>\n </ion-button>\n </ng-container>\n </ion-item>\n</ion-toolbar>\n\n\n\x3c!-- 语音消息输入:弹出区域 --\x3e\n<ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="0.35" [breakpoints]="[0, 0.35, 0.5]">\n <ng-template>\n <fm-modal-audio-message #audioComp *ngIf="isAudioModal" [chat]="chat" [modal]="audioModal"></fm-modal-audio-message>\n </ng-template>\n</ion-modal>',styles:['@charset "UTF-8";:host-context(body.dark) .btn-voice-start{background-color:#222428;color:#fff}:host-context(body.dark) ion-textarea{background-color:#222428;color:#fff}ion-toolbar{--background:none}ion-toolbar .button-item{--inner-padding-start:5px;--inner-padding-end:0px;--padding-start:5px;--padding-end:0px}ion-toolbar ion-item{--background:transparent}ion-textarea.custom{--background: #373737;--color: #fff;--padding-end: 10px;--padding-start: 10px;--placeholder-color: #ddd;--placeholder-opacity: .8}ion-textarea.custom textarea{width:calc(100% - 95px)}ion-textarea.custom ion-button{position:absolute;right:0}.input-item{display:flex;min-height:77px;align-items:center;border:none;--inner-padding-start:0px;--inner-padding-end:0px;--padding-start:0px;--padding-end:0px}.input-item ion-textarea{background-color:#fff;max-height:400px;padding:0 5px;margin:0 5px;border-radius:20px;overflow-y:auto}.input-item .btn-voice-start{display:flex;flex:1;justify-content:center;align-items:center;font-weight:700;background:#fff;border-radius:20px;min-height:50px}ion-textarea{transition:width .5s ease}ion-textarea:hover .btn-input-change,ion-textarea:focus-within .btn-input-change{display:none}.input-item:hover ion-textarea,.input-item:focus-within ion-textarea{border-color:var(--logo-color-primary)}::ng-deep .ant-modal-body{max-height:600px;overflow-y:auto}::ng-deep .ant-modal-footer{display:flex;justify-content:space-around}::ng-deep .ant-btn{width:40%}.popup-content{position:relative}.popup-content .message-content-user{display:flex;justify-content:flex-end}.popup-content .message-content-role{display:flex;justify-content:flex-start}.popup-content .message-content-system{display:flex;justify-content:center}.popup-content .user-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#e7f8ff}.popup-content .role-message{padding:10px 10px 0;border-radius:10px;width:fit-content;max-width:100%;background-color:#f6f6f6}.popup-content .user-question{margin-bottom:5px;display:flex;justify-content:flex-end}.popup-content .chat-time{margin-bottom:10px;display:flex;justify-content:flex-end;font-size:14px;color:#a3a3a3}.popup-content .role-time{justify-content:flex-start}\n']}]}],ctorParameters:()=>[{type:i1.ToastController},{type:i1.AlertController},{type:i1.NavController},{type:i2.Router},{type:i3.ImagineService},{type:i4.ChatService},{type:i2.ActivatedRoute},{type:i5.NzMessageService}],propDecorators:{audioComp:[{type:ViewChild,args:[ModalAudioMessageComponent]}],chat:[{type:Input}],message:[{type:Input}],role:[{type:Input}]}});
|
|
9
|
+
var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9lc20yMDIyL2xpYi9haWdjL2NoYXQvY2hhdC1tb2RhbC1pbnB1dC9tb2RhbC1pbnB1dC5jb21wb25lbnQubWpz`
|
|
10
|
+
|